在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 availableexception。

我认为这是因为没有关闭应用程序代码中的连接,所以你刚刚用完了池中的连接。 也许你应该尝试在DBCP中设置“removeAbandoned”属性。 这在http://commons.apache.org/dbcp/configuration.html中记录为

将此设置为true可以从未能关闭连接的编写不良的应用程序中恢复数据库连接。

祝你好运!

我遇到了类似的问题,这是通过以下步骤解决的

  1. 按适当顺序关闭所有数据库资源

     resultSet.close(); statement.close(); connection.close(); 

不同的驱动程序实现方式不同,如果底层的resultSet未关闭,某些驱动程序仍会在连接上进行实际操作。

  1. 需要调整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会显示服务器日志/控制台上未关闭的所有连接。