我在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)
欢迎任何建议!
答案 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)
我遇到了类似的问题,通过以下步骤解决了这个问题
按正确顺序关闭所有数据库资源
resultSet.close();
statement.close();
connection.close();
不同的驱动程序实现方式不同,如果基础resultSet未关闭,某些驱动程序仍然会在连接上进行实际操作。
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会显示服务器日志/控制台上未关闭的所有连接。