1 背景

如果将​​​​中的endTransaction注释掉,那么将会有连接泄漏,本文是一个实践

private void endTransactionReal() {
//getOdsSqlSessionManager().close();
}


 

2

2.1 连接池信息

初始:4

最大:10

 

2.2 取得连接的过程

org.apache.commons.dbcp.BasicDatasource.getConnection

org.apache.commons.dbcp.BasicDatasource.createDataSource

org.apache.commons.dbcp.PoolingDatasource.getConnection

org.apache.commons.pool.impl.GenericObjectPool.borrowObject

 

2.3 归还连接的过程

org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.close

org.apache.commons.dbcp.PoolableConnection.close

org.apache.commons.pool.impl.GenericObjectPool.returnObject

 

3 服务器启动后

借用​​​​ 的方式检测初始oracle连接

$ netstat -ano|grep ip

TCP localinstanceip:49413 oracleip:1568 TIME_WAIT 0

TCP localinstanceip:54128 oracleip:1567 ESTABLISHED 18612

TCP localinstanceip:54130 oracleip:1567 ESTABLISHED 18612

TCP localinstanceip:54132 oracleip:1568 ESTABLISHED 18612

TCP localinstanceip:60356 oracleip:1568 ESTABLISHED 18612

 

请注意,由于使用了懒加载,所以首次打开页面之前没有这些连接,后才有

可以看到4条establish

 4 和 5 两种情况都是这个结果

 

4 no endtransaction

4.1 4次访问后(含首次激活懒加载的那个第一次)

仍然显示4条连接

 

4.2 第5次访问后

出现5条连接,证明连接没有归还,导致连接池新开了连接

 

4.3 第6-第10次访问

断点调试调用链:

org.apache.commons.dbcp.PoolingDatasource.getConnection

org.apache.commons.pool.impl.GenericObjectPool.borrowObject

commit

end

org.apache.commons.dbcp.PoolableConnection.close

org.apache.commons.pool.impl.GenericObjectPool.returnObject  注意没有这两条

 

结果显示10条连接

 

4.4 第11次刷新页面,页面阻塞

 jstack

可以看到有一条业务线程,(使用scef项目名ctrl F)

 

"GUI-Thread-43, TaskID:825, Start Time:07-09 04:26:28" #145 prio=10 os_prio=2 tid=0x00000000277fa800 nid=0x5bec in Object.wait() [0x000000007324c000]

java.lang.Thread.State: WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

at java.lang.Object.wait(Object.java:502)

at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118)

- locked <0x000000078093e458> (a org.apache.commons.pool.impl.GenericObjectPool$Latch)

at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)

at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)

at com.citi.risk.core.data.db.provider.impl.LazyDataSource.getConnection(LazyDataSource.java:124)

at org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:140)

at org.apache.ibatis.transaction.jdbc.JdbcTransaction.getConnection(JdbcTransaction.java:62)

at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:315)

at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:75)

at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:61)

at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:303)

at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:154)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:102)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113)

at sun.reflect.GeneratedMethodAccessor317.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.apache.ibatis.session.SqlSessionManager$SqlSessionInterceptor.invoke(SqlSessionManager.java:334)

at com.sun.proxy.$Proxy179.selectList(Unknown Source)

at org.apache.ibatis.session.SqlSessionManager.selectList(SqlSessionManager.java:190)

at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:122)

at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:64)

at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53)

at com.sun.proxy.$Proxy325.queryUserByLikeId(Unknown Source)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

 

阻塞

 

 

 

5 has endtransaction

重复4的步骤

 

5.1 第5次访问开始后若干次,仍然显示4条连接

 

5.2 调用链

org.apache.commons.dbcp.PoolingDatasource.getConnection

org.apache.commons.pool.impl.GenericObjectPool.borrowObject

commit

end

org.apache.commons.dbcp.PoolableConnection.close

org.apache.commons.pool.impl.GenericObjectPool.returnObject