2009-12-11 95 views
8

在我的應用程序中,Spring管理連接池以訪問數據庫。 Hibernate使用這些連接進行查詢。乍一看,我對池沒有任何問題:它對併發客戶端和只有一個連接的池正常工作。我可以執行很多查詢,所以我認爲我(或Spring)不會保留打開的連接。連接在閒置之後掛起

我的問題出現一段時間後不活動(有時30分鐘,有時超過2小時)。然後,當Hibernate進行一些搜索時,它會持續太久。 Log4j級別設置追查,我得到這個日誌:

... 
18:27:01 DEBUG nsactionSynchronizationManager - Retrieved value [[email protected]] for key [[email protected]] bound to thread [http-8080-Processor24] 
18:27:01 DEBUG HibernateTransactionManager  - Found thread-bound Session [[email protected]] for Hibernate transaction 
18:27:01 DEBUG HibernateTransactionManager  - Using transaction object [org.springframework.orm.hi[email protected]1b2ffee] 
18:27:01 DEBUG HibernateTransactionManager  - Creating new transaction with name [com.acjoventut.service.GenericManager.findByExample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
18:27:01 DEBUG HibernateTransactionManager  - Preparing JDBC Connection of Hibernate Session [[email protected]] 
18:27:01 TRACE SessionImpl      - setting flush mode to: AUTO 
18:27:01 DEBUG JDBCTransaction     - begin 
18:27:01 DEBUG ConnectionManager    - opening JDBC connection 

這被冷凍約2 - 10分鐘。但接着繼續:

18:30:11 DEBUG JDBCTransaction     - current autocommit status: true 
18:30:11 DEBUG JDBCTransaction     - disabling autocommit 
18:30:11 TRACE JDBCContext      - after transaction begin 
18:30:11 DEBUG HibernateTransactionManager  - Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@212.31.39.50:30998:orcl, UserName=DEVELOP, Oracle JDBC driver] 
18:30:11 DEBUG nsactionSynchronizationManager - Bound value [[email protected]] for key [[email protected]] to thread [http-8080-Processor24] 
18:30:11 DEBUG nsactionSynchronizationManager - Initializing transaction synchronization 
... 

之後,它的工作沒有問題,直到另一個不活動的時期。恕我直言,它似乎像連接池返回一個無效/關閉連接,當Hibernate意識到這一點時,要求另一個連接池。

我不知道我該如何解決這個問題,或者我可以用它來分隔它。任何幫助實現這一點將不勝感激。

謝謝。

編輯:嗯,它最終是由於防火牆的規則。數據庫檢測到連接丟失,但池(dbcp或c3p0)不是。所以,它試圖查詢數據庫沒有成功。對我來說仍然很奇怪的是,超時時間非常多變。也許這個規則特別奇怪,或者防火牆無法正常工作。無論如何,我無法訪問該機器,我只能等待解釋。 :(

+0

你是如何確定這是否是防火牆的問題?我遇到了一個類似的問題,其中dbcp無限期地掛在我的Spring Batch事務上,並且永遠不會返回 – YogendraJ 2016-05-20 05:06:31

回答

7

我以前有過這樣的問題,當數據庫是在一個單獨的盒子,並且有一個之間的防火牆設置以超時閒置連接

在某些環境防火牆會阻止連接,導致JDBC端無法檢測到,並嘗試使用它會導致無限期的阻塞。

在我的情況下,它是一個自定義連接池,它在從池中返回它之前向連接發送測試查詢。我將此測試查詢配置爲有超時(使用Statement.setQueryTimeout),以便它不會無限期地阻塞。

+0

我不確定爲什麼你會使用自定義池來只發送測試查詢。一個體面的連接池和/或容器管理的數據源已經可以做到這一點。例如DBCP和Tomcat JNDI。請參閱每個關鍵字'validationQuery'下的配置文檔。 – BalusC 2009-12-11 17:28:20

+0

這是一個很久以前的項目,它使用了一個定製的連接池,並且在代碼段中確實與DBCP中的validationQuery做了類似的事情。 – Joe 2009-12-11 17:54:03

+0

你是對的。看來這個問題是一些防火牆排除我的控制。我認爲最好的解決方案是改變防火牆行爲。謝謝。 – sinuhepop 2009-12-29 14:18:37

1

檢查池實現的配置。通常情況下,它的Apache DBCP具有a timeout爲每個連接後,它會關閉它。

在你的代碼,你不應該保持周圍連接。獲取一個,使用它,立即關閉池將確保這不會花費太多

+0

Spring管理我的連接,所以我不是那個必須明確調用Connection.close()的人。我是嗎?正如你所說,我正在使用org.apache.commons.dbcp.BasicDataSource,並使用destroy-method =「close」。我會研究它。 – sinuhepop 2009-12-11 16:07:36

+1

還有其他兩個問題的根源:您和數據庫服務器之間可能存在防火牆(但空閒TCP連接上的2h超時有點短)。或者您的數據庫配置爲在一段時間後關閉空閒連接。查看DBCP的其他配置選項來檢查死連接並定期ping數據庫以保持管道打開。 – 2009-12-12 12:39:02

+0

至於關閉:不,你不應該關閉它,但你應該結束事務(這將使Spring看到連接可以返回到池中)。 – 2009-12-12 12:39:48

1

解決空閒超時問題的一種方法是擁有雙連接池,一個處於活動狀態,另一個處於待機狀態(尚未創建連接)。有一個觸發時間比FIREWALL_IDLE_TIMEOUT小得多的定時器,並在連接池之間切換。我試過這個和它的工作。

1

你必須添加在您的數據源的一些參數:

更重要補充testOnBorrow和validationQuery

1

我們解決的問題有類似症狀也橫空出世由防火牆引起。

我們可以通過改變其阻止去閒置和防火牆關閉連接的連接testWhileIdle連接池屬性來解決此問題。見Apache commons dbcp BasicDataSource。下面是從配置文件,persistentce-context.xml中的使出的是解決了這一問題:

<property name="testWhileIdle"> 
    <value>true</value> 
</property> 
<property name="minEvictableIdleTimeMillis"> 
    <value>600000</value> 
</property> 
<property name="timeBetweenEvictionRunsMillis"> 
    <value>600000</value> 
</property> 

最有可能的,我們只需要添加testWhileIdle(默認爲false),但添加了其他兩個屬性的好辦法。

在我們的案例中,這裏是我們看到的一些日誌。注意在這個調試日誌中,在連接可能被使用之前,需要16分鐘才能打開連接,這是導致一切都掛起的原因。沒有任何錯誤導致難以追查。

09-06-13 @ 16:36:34 [DEBUG] HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [[email protected]] 
09-06-13 @ 16:36:34 [DEBUG] ConnectionManager - opening JDBC connection 
09-06-13 @ 16:52:00 [DEBUG] DataSourceUtils - Setting JDBC Connection 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - begin 
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - current autocommit status: true