2017-09-06 406 views
0

配置c3p0設置時遇到問題。該senario是:我有一個Java項目,將於每天凌晨3:00開始,然後連接到數據庫做一些事情。有時候,數據庫可能會在當時關閉,並可能在2或3小時後恢復。
因此,我需要讓程序嘗試在特定的時間間隔內重新連接數據庫,以查看數據庫是否正常,直到它可以成功連接到數據庫。 我試圖配置c3p0無限重新連接數據庫直到成功,但似乎陷入了一些僵局。以下是我的c3p0設置。 我在Spring框架中使用c3p0 v0.9.1和hibernate,數據庫是DB2。當數據庫關閉時,C3p0無法重新連接數據庫

<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[email protected]21eb3f -- APPARENT DEADLOCK!!! 
Creating emergency threads for unassigned pending tasks! 
[WARN]: com[email protected]21eb3f -- APPARENT DEADLOCK!!! 
Complete Status: 
Managed Threads: 3 
Active Threads: 3 
Active Tasks: 
    [email protected]d (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0) 
    [email protected]c (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1) 
    [email protected]3 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2) 
Pending Tasks: 
    [email protected]4 
    [email protected]0 
    [email protected] 
    [email protected]2 
    [email protected] 
    [email protected] 
    [email protected] 
Pool thread stack traces: 
    ... 
[WARN] [2017-09-04 ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task [email protected] 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). 
[WARN] [2017-09-04 ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task [email protected] 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). 
[WARN] [2017-09-04 ThreadPoolAsynchronousRunner.processReplacedThreads() ] Task [email protected] 
(in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). 

[WARN] [2017-09-04 BasicResourcePool$AcquireTask.run()] [email protected] -- 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()] [email protected] -- 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()] [email protected] -- 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) 

能否請你幫糾正我,如果設置有什麼錯?先謝謝你!

+0

這個'application'是如何啓動的? cron的? –

+0

@Scary是的,是的。 – cmjauto

+0

然後你可以嘗試使用工具,例如數據庫客戶端cli,測試數據庫是否啓動,然後嘗試啓動您的應用程序,並將其放入您的應用程序啓動腳本 –

回答

0

首先,你不應該使用c3p0-0.9.1。這是古老的。當前版本是0.9.5.2。

這裏的問題是,當你的數據庫關閉時,嘗試連接並沒有失敗並伴有異常,它們掛起。因此c3p0的線程池正在嘗試獲取連接,既不能成功也不能失敗,但會無限期掛起。一旦線程池完全飽和並被阻塞了一段時間,c3p0就會聲明一個APPARENT DEADLOCK,並且你看到了你所看到的。

要做的最好的事情是修復您的網絡或服務器中導致嘗試連接數據庫掛起而不是成功或失敗的錯誤。如果你能解決這個問題,你的問題可能會消失。

如果你不能解決這個問題,你可以用c3p0設置maxAdministrativeTaskTime來解決這個問題。如果你設置了這個,在你定義的秒數之後,c3p0會考慮任何掛起的任務(比如你的連接獲取嘗試),並且試圖通過在任務掛起的線程上調用interrupt()來強制失敗。如果幸運的話,你的凍結獲得任務將失敗,並且生命將持續下去InterruptedException

如果您確實使用maxAdministrativeTaskTime,那麼您需要設置一個明顯長於數據庫可能合理需要的連接的值(而DBMS已啓動且可用)。你可能還想從默認值3增加numHelperThreads,這樣在沒有無盡掛起但仍然緩慢的獲取任務中,有更多的線程可以在整個線程池飽和並引發僵局之前使用它們。

+0

謝謝你的詳細解釋,我會用你的建議嘗試一個新版本。 – cmjauto