数据库关闭时,C3p0无法重新连接数据库

时间:2017-09-06 06:29:14

标签: java spring jdbc db2 c3p0

我在配置c3p0设置时遇到了问题。 Senario是:我有一个java项目,它将在每天凌晨3:00启动,然后连接到数据库做一些事情。有时,数据库可能会在那时停机,并可能在2或3小时后恢复 所以,我需要让程序尝试在特定的时间间隔内重新连接数据库以查看数据库是否正常,直到它可以成功连接到数据库。 我试图配置c3p0无限重新连接数据库,直到成功,但似乎陷入了一些僵局。下面是我的c3p0设置。 我在Spring框架中使用c3p0 v0.9.1和hibernate,数据库是DB2。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>

    <property name="acquireRetryAttempts" value="0"/>

    <property name="acquireRetryDelay" value="10000"/>

    <property name="maxIdleTime"value="60"/>
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="200"/>
    <property name="idleConnectionTestPeriod" value="30" />
    <property name="preferredTestQuery" value="values(1)" />
</bean>

当我运行程序时,它失败了,错误日志如下所示:

[WARN]: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@21eb3f -- APPARENT DEADLOCK!!! 
Creating emergency threads for unassigned pending tasks!
[WARN]: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@21eb3f -- APPARENT DEADLOCK!!! 
Complete Status:
 Managed Threads: 3
 Active Threads: 3
 Active Tasks: 
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@15e796d (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@176150c (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1)
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@15fc793 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2)
 Pending Tasks: 
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@127bd04
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@1ea8fc0
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@83969e
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@1159092
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@c69203
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@9c035a
  com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@a0416a
Pool thread stack traces:
  ...
[WARN] [2017-09-04  ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask@15e796d 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt().
[WARN] [2017-09-04  ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask@176150c 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt().
[WARN] [2017-09-04  ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask@15fc793 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt().

[WARN] [2017-09-04 BasicResourcePool$AcquireTask.run()] com.mchange.v2.resourcepool.BasicResourcePool@53b9e444 -- Thread unexpectedly interrupted
while performing an acquisition attempt.
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask.run (BasicResourcePool.java:1805)
   at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
[WARN] [2017-09-04 BasicResourcePool$AcquireTask.run()] com.mchange.v2.resourcepool.BasicResourcePool@53b9e444 -- Thread unexpectedly interrupted
while performing an acquisition attempt.
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask.run (BasicResourcePool.java:1805)
   at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
[WARN] [2017-09-04 BasicResourcePool$AcquireTask.run()] com.mchange.v2.resourcepool.BasicResourcePool@53b9e444 -- Thread unexpectedly interrupted
while performing an acquisition attempt.
java.lang.InterruptedException: sleep interrupted
   at java.lang.Thread.sleep(Native Method)
   at com.mchange.v2.resourcepol.BasicResourcePool$AcquireTask.run (BasicResourcePool.java:1805)
   at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)

如果设置有问题,请帮忙纠正我的问题?提前谢谢!

1 个答案:

答案 0 :(得分:1)

首先,你不应该使用c3p0-0.9.1。这是古老的。目前的版本是0.9.5.2。

这里的问题是,当您的数据库关闭时,尝试连接不会因异常而失败,它们会挂起。因此,c3p0的线程池正在尝试获取既不会成功也不会失败但无限期挂起的Connections。一旦线程池完全饱和并被阻塞了一段时间,c3p0就会声明一个APPARENT DEADLOCK,你会看到你看到的内容。

最好的办法是修复网络或服务器中的任何错误,导致尝试连接到数据库挂起而不是成功或失败。如果你能解决这个问题,你的问题可能就会消失。

如果您无法解决此问题,您可以使用c3p0设置maxAdministrativeTaskTime来解决问题。如果你设置了这个,在你定义的秒数之后,c3p0会考虑任何挂起的任务(比如你的连接获取尝试)被破坏,并试图通过在线程上调用interrupt()来强制它们的失败。雄。如果幸运的话,你的冻结获取任务将失败,InterruptedException生命将会继续。

如果您确实使用maxAdministrativeTaskTime,那么您希望设置一个值远远长于数据库连接可能合理要求的值(当DBMS启动并可用时)。您可能还希望将numHelperThreads从其默认值3增加,以便不会无休止地挂起但仍然缓慢的获取任务在它们使整个线程池饱和并引发死锁之前有更多线程可以使用