Tomcat上部署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)
欢迎任何建议!
I'm using DBCP data source (with default configuration) in Spring configuration to manage my connections to the database, and I'm running into a deadlock condition when the number of clients increase.
I found that there is a deadlock issue in DBCP 1.2.1 which I was using, which was supposed to be resolved in 1.4. So I upgraded to 1.4, but the issue still persists.
In the thread dump, there are many threads blocked with the following stack trace on top:
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)
Any suggestions are welcome!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
几年前,我切换到 c3p0。你可以尝试一下。我相信你不必做太多改变,这只是一个配置的游戏。
有点相关的线程,Connection pooling options with JDBC: DBCP vs C3P0。嗯,实际上我把它联系起来了。
[已编辑,2012年10月19日]
Tomcat 7 有一个不错的连接池,Tomcat JDBC 连接池。
I switched to c3p0, few years back. You can try that. I believe you didn't have to change much, it's just a game of configuration.
Somewhat related thread, Connection pooling options with JDBC: DBCP vs C3P0. Well, actually I made it related.
[edited, 19/10/12]
Tomcat 7 has a decent connection pool, The Tomcat JDBC Connection Pool.
您是否确保 commons-pool 版本与 dbcp 版本匹配?
另外,我没有在堆栈跟踪中看到死锁,它看起来只是有线程等待连接释放。您有多少个线程尝试同时连接?您为池等配置了多少个连接?
在调试此类情况时,查看已获得连接的线程正在执行的操作也很有用。
Did you make sure the commons-pool version matches the dbcp version?
Also, I'm not seeing a deadlock in the stacktrace, it simply looks like you have threads waiting for connections to free up.. How many threads do you have trying to connect at the same time? How many connections have you configured for the pool etc..?
In debugging this kind of cases it's also useful to look at what the threads that have gotten a connection are doing.
应用程序负载的增加增加了对并发连接的要求。由于您的线程挂在
borrowConnection()
上 - 意味着您没有足够的ActiveConnections
可用。在数据源属性中增加
maxActive
并将WHEN_EXHAUSTED_BLOCK
设置为某个时间,例如600ms - 1000ms
。仅在经过 600 毫秒 -1000 毫秒后,您才会收到No element available
异常。Incrasing load on application is increasing requirement to concurrent connections. As your threads are hanging on
borrowConnection()
- means you are not having sufficientActiveConnections
available.Incrkease
maxActive
in your datasource properties and setWHEN_EXHAUSTED_BLOCK
to some time like600ms - 1000ms
. You will getNo element available
exception only after elapsed of 600ms -1000 ms.我认为这是由于没有关闭应用程序代码中的连接而导致的,因此您只是耗尽了池中的连接。
也许您应该尝试在 DBCP 中设置“removeAbandoned”属性。
这记录在 http://commons.apache.org/dbcp/configuration.html作为
祝你好运!
I think this is caused by not closing connections in your app code, so you just run out of connections in the pool.
Maybe you should try to set the "removeAbandoned" property in DBCP.
This is documented in http://commons.apache.org/dbcp/configuration.html as
Best of luck!
我遇到了类似的问题,通过以下步骤解决了这个问题
以正确的顺序关闭所有数据库资源
不同的驱动程序实现方式不同,如果底层 resultSet 未关闭,某些驱动程序仍会手动连接。
dataSource.setDefaultAutoCommit(true);
dataSource.setMaxActive(700); // 确保数据库服务器有它 800
dataSource.setRemoveAbandoned(true);
dataSource.setTestOnBorrow(true);
dataSource.setLogAbandoned(true);
dataSource.setTestWhileIdle(true);
dataSource.setTestOnReturn(true);
dataSource.setRemoveAbandonedTimeout(60);
确保数据库服务器允许的连接数至少超过
setMaxActive
中指定的数量,因为 dbcp 首先提供x
个新连接,并且然后尝试清理超过setMaxActive
数量的连接。 清理 dbcp 会在服务器日志/控制台上显示哪些连接未关闭。I was facing similar issues and this was solved by following steps
Close all database resources in proper sequence
Different drivers are implemented differently, some driver would still hand-on on the connection if underlying resultSet is not closed.
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);
Make sure database server can allow atleast 50+ connecitions more than number specified in
setMaxActive
as the dbcp givesx
new connections first and then try to clean up connections exceedingsetMaxActive
number. On clean-up dbcp shows which all connections were not closed on the server log/console.