在Tomcat上部署的DBCP中的死锁问题

时间:2011-04-19 09:49:08

标签: java spring tomcat deadlock apache-commons-dbcp

我在Spring配置中使用DBCP数据源(使用默认配置)来管理我与数据库的连接,当客户端数量增加时,我遇到了死锁状态。

我发现在我使用的DBCP 1.2.1中存在死锁问题,应该在1.4中解决。所以我升级到1.4,但问题仍然存在。

在线程转储中,有许多线程被阻塞,顶部有以下堆栈跟踪:

   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)

欢迎任何建议!

5 个答案:

答案 0 :(得分:8)

几年前我切换到c3p0。你可以试试。我相信你不需要改变太多,这只是一个配置游戏。

有点相关的帖子,Connection pooling options with JDBC: DBCP vs C3P0。好吧,实际上我把它与之相关了。

[编辑,19/10/12]

Tomcat 7有一个不错的连接池,The Tomcat JDBC Connection Pool

答案 1 :(得分:1)

您确定commons-pool版本与dbcp版本匹配吗?

另外,我没有在堆栈跟踪中看到死锁,它看起来就像你有线程等待连接释放..你有多少线程同时尝试连接?您为池等配置了多少个连接..?

在调试这种情况时,查看已建立连接的线程正在做什么也很有用。

答案 2 :(得分:1)

在应用程序上加载加载对并发连接的要求越来越高。由于你的帖子挂在borrowConnection()上 - 意味着你没有足够的ActiveConnections可用。

在数据源属性中加载maxActive并将WHEN_EXHAUSTED_BLOCK设置为600ms - 1000ms之类的时间。只有在经过600ms -1000 ms后才会出现No element available异常。

答案 3 :(得分:0)

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

  

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

祝你好运!

答案 4 :(得分:0)

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

  1. 按正确顺序关闭所有数据库资源

    resultSet.close();
    statement.close();
    connection.close();
    
  2. 不同的驱动程序实现方式不同,如果基础resultSet未关闭,某些驱动程序仍然会在连接上进行实际操作。

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