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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5714511/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:26:29  来源:igfitidea点击:

Deadlock issue in DBCP deployed on Tomcat

javaspringtomcatdeadlockapache-commons-dbcp

提问by Iravanchi

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.

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

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.

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

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!

欢迎任何建议!

采纳答案by Adeel Ansari

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.

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

Somewhat related thread, Connection pooling options with JDBC: DBCP vs C3P0. Well, actually I made it related.

有点相关的线程,JDBC 的连接池选项: DBCP vs C3P0。嗯,实际上我让它相关。

[edited, 19/10/12]

[编辑,2012 年 10 月 19 日]

Tomcat 7 has a decent connection pool, The Tomcat JDBC Connection Pool.

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

回答by Mikko Wilkman

Did you make sure the commons-pool version matches the dbcp version?

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

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.

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

回答by arviarya

Incrasing load on application is increasing requirement to concurrent connections. As your threads are hanging on borrowConnection()- means you are not having sufficient ActiveConnectionsavailable.

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

Incrkease maxActivein your datasource properties and set WHEN_EXHAUSTED_BLOCKto some time like 600ms - 1000ms. You will get No element availableexception only after elapsed of 600ms -1000 ms.

IncrkeasemaxActive在你的数据源属性并设置WHEN_EXHAUSTED_BLOCK一些时间一样600ms - 1000msNo element available只有在 600 毫秒 -1000 毫秒过去后才会出现异常。

回答by veer7

I was facing similar issues and this was solved by following steps

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

  1. Close all database resources in proper sequence

    resultSet.close();
    statement.close();
    connection.close();
    
  1. 按正确顺序关闭所有数据库资源

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

Different drivers are implemented differently, some driver would still hand-on on the connection if underlying resultSet is not closed.

不同的驱动程序实现不同,如果底层 resultSet 没有关闭,一些驱动程序仍然会在连接上进行操作。

  1. Apache DBCP defaults needs to be tuned
  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);

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 setMaxActiveas the dbcp gives xnew connections first and then try to clean up connections exceeding setMaxActivenumber. On clean-up dbcp shows which all connections were not closed on the server log/console.

确保数据库服务器可以允许至少 50 多个连接超过指定的数量,setMaxActive因为 dbcpx首先提供新连接,然后尝试清理超出setMaxActive数量的连接。清理时 dbcp 显示服务器日志/控制台上的所有连接都没有关闭。

回答by jcamillo

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.htmlas

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

Setting this to true can recover db connections from poorly written applications which fail to close a connection.

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

Best of luck!

祝你好运!