在Tomcat上部署的DBCP中的死锁问题
我在Spring配置中使用DBCP数据源(使用默认配置)来管理我与数据库的连接,并且当客户端数量增加时,我遇到了死锁状态。
我发现在我使用的DBCP 1.2.1中存在死锁问题,应该在1.4中解决。 所以我升级到1.4,但问题仍然存在。
在线程转储中,有许multithreading被阻塞,顶部有以下堆栈跟踪:
java.lang.Thread.State: WAITING on org.apache.commons.pool.impl.GenericObjectPool$Latch@b6b09e at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104) at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106) at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044) at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:200) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:350) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:261) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:631)
欢迎任何建议!
几年前我切换到了c3p0 。 你可以试试。 我相信你不需要改变太多,这只是一个配置游戏。
一些相关的线程, 与JDBC的连接池选项:DBCP与C3P0 。 好吧,实际上我把它与之相关了。
[编辑,19/10/12]
Tomcat 7有一个不错的连接池, 即Tomcat JDBC连接池 。
您确定commons-pool版本与dbcp版本匹配吗?
此外,我没有在堆栈跟踪中看到死锁,它看起来就像你有线程等待连接释放..你有多少线程同时尝试连接? 您为池等配置了多少个连接..?
在调试这种情况时,查看已建立连接的线程正在做什么也很有用。
应用程序上的加载负载对并发连接的要求越来越高。 由于您的线程挂在borrowConnection()
– 意味着您没有足够的ActiveConnections
可用。
在数据源属性中包含maxActive
,并将WHEN_EXHAUSTED_BLOCK
设置为600ms - 1000ms
。 只有在经过600ms -1000 ms后才能获得No element available
exception。
我认为这是因为没有关闭应用程序代码中的连接,所以你刚刚用完了池中的连接。 也许你应该尝试在DBCP中设置“removeAbandoned”属性。 这在http://commons.apache.org/dbcp/configuration.html中记录为
将此设置为true可以从未能关闭连接的编写不良的应用程序中恢复数据库连接。
祝你好运!
我遇到了类似的问题,这是通过以下步骤解决的
-
按适当顺序关闭所有数据库资源
resultSet.close(); statement.close(); connection.close();
不同的驱动程序实现方式不同,如果底层的resultSet未关闭,某些驱动程序仍会在连接上进行实际操作。
- 需要调整Apache DBCP默认值
dataSource.setDefaultAutoCommit(true);
dataSource.setMaxActive(700); // make sure db server has it 800 dataSource.setRemoveAbandoned(true); dataSource.setTestOnBorrow(true); dataSource.setLogAbandoned(true); dataSource.setTestWhileIdle(true); dataSource.setTestOnReturn(true); dataSource.setRemoveAbandonedTimeout(60);
确保数据库服务器允许至少50个以上的连接数超过setMaxActive中指定的数量,因为dbcp首先提供x
新连接,然后尝试清除超过setMaxActive
数的连接。 在清理时,dbcp会显示服务器日志/控制台上未关闭的所有连接。