17

我在 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)

欢迎任何建议!

4

5 回答 5

8

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

有点相关的线程,使用 JDBC 的连接池选项: DBCP vs C3P0。好吧,实际上我把它联系起来了。

[已编辑,2012 年 19 月 10 日]

Tomcat 7 有一个不错的连接池,即 Tomcat JDBC 连接池

于 2011-04-19T10:36:21.940 回答
1

增加应用程序的负载正在增加对并发连接的要求。由于您的线程挂起borrowConnection()- 意味着您没有足够的ActiveConnections可用资源。

增加maxActive您的数据源属性并设置WHEN_EXHAUSTED_BLOCK为某个时间,例如600ms - 1000ms. No element available只有经过 600 毫秒 -1000 毫秒后,您才会收到异常。

于 2012-10-15T20:27:21.717 回答
1

您是否确保 commons-pool 版本与 dbcp 版本匹配?

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

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

于 2011-04-19T10:42:19.270 回答
0

我认为这是由于未关闭应用程序代码中的连接造成的,因此您只是用完了池中的连接。也许您应该尝试在 DBCP 中设置“removeAbandoned”属性。这在http://commons.apache.org/dbcp/configuration.html中记录为

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

祝你好运!

于 2012-07-24T12:59:18.377 回答
0

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

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

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

不同的驱动程序实现不同,如果底层结果集没有关闭,一些驱动程序仍然会手动连接。

  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因为 dbcpx首先提供新连接,然后尝试清理超过setMaxActive数量的连接。在清理时,dbcp 会在服务器日志/控制台上显示未关闭的所有连接。

于 2017-09-26T07:21:09.540 回答