2012-10-16 128 views
3

DB後dropps空閒連接或DB是往下再往我收到以下錯誤在我的webapp:Guice JPA - 「此連接已關閉。」錯誤

javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1365) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1293) 
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:265)  
... 60 more 
Caused by: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode 
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:131) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:395) 
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterNonTransactionalQuery(TransactionCoordinatorImpl.java:195) 
    at org.hibernate.internal.SessionImpl.afterOperation(SessionImpl.java:565) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1220) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) 
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:256) 
... 70 more 
Caused by: org.postgresql.util.PSQLException: This connection has been closed. 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:712) 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.java:678) 
    at sun.reflect.GeneratedMethodAccessor138.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:63) 
    at $Proxy66.getAutoCommit(Unknown Source) 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:392) 

當這個開始,我得到一個

SQL Error: 0, SQLState: 08006 - An I/O error occured while sending to the backend. 

但之後,它只是:

SQL Error: 0, SQLState: 08003 - This connection has been closed. 

問題是:我已經設置testOnBorrow,所以我希望只獲得打開的連接。

如果有幫助:池ususaly包含好的和壞的連接組合,並且問題似乎隨着時間的推移而逐漸消失,但是我的服務器運行時間> 12h,並且返回的連接仍然不正常。 重啓後,evertything工作正常(一段時間)。

我已經調試了一些更多的問題,好像池正在返回不良連接,例如如果在DB上有所有連接中斷後,我得到:

SQL Error: 0, SQLState: 57P01 

然後通常的東西 - 從池中返回的連接被終止。 問題是:它是一個應用程序問題嗎?

我嘗試通過JMX清除池但這似乎沒有任何效果。 另一個奇怪的是,即使應用程序顯然沒有做任何事情(通過線程轉儲進行檢查),JMX bean顯示7個活動連接和0個空閒連接。當我執行一個需要數據庫訪問的請求時,我立即得到響應(說明沒有可用的空閒連接),但JMX在此之後顯示7個活動連接和0個空閒連接。

PS。也許我錯過了一些明顯的東西,這是我的一個連接管理問題?我正在使用通過persistence.xml配置的JPA EntityManager,所以也許我做錯了什麼,連接在使用後沒有正確關閉(返回)?

+0

你是怎麼解決這個問題? –

回答

5

其實我是對的,當我懷疑應用程序錯誤。

這都是很好的描述下在Issue 730: Automatically started UnitOfWork is never ended

當使用JpaPersistService,如果您嘗試訪問 的EntityManager活躍的UnitOfWork之外,吉斯將 自動啓動一個給你。但是,由於Guice沒有(而且 不能)知道何時結束這個UnitOfWork,它從來不會這樣做。

結果?在整個應用程序的整個生命週期中,有問題的線程都將與相同的EntityManager 卡住。對於 應用程序來說,這是一個糟糕的狀態,我們不可避免地會在一段時間內崩潰後耗盡可用的內存。

這裏真正的殺手鐗是,它都不明顯,當你做了 這個錯誤。唯一真正的跳球的是,你得到 不一致的數據從數據庫中不同的線程之間(由於 中,EMS一級緩存),或應用程序的內存消耗 不斷增長。 在我的情況下,它是這讓我懷疑它,然後池中的有效連接,當我打開詳細的日誌記錄我注意到,應用程序不是借用連接池可言,相反,它被再利用已持有的連接通過未關閉的EntityManager。

其實也有這個問題頗有些重複報道:http://code.google.com/p/google-guice/issues/list?can=1&q=UnitOfWork

0

如果您已將META-INF/context.xml修改爲包含validationQuery,則Tomcat可能會緩存舊定義conf/engine/host/webapp.xml。關閉Tomcat,刪除該文件,然後重新啓動Tomcat。在Tomcat關閉的情況下,刪除work目錄也無妨。

+0

我不這麼認爲 - 它在多臺服務器上發生過多次(重啓之間)。我也沒有修改validationQuery自初始部署。 –

5

通配:代碼here暗示,validationInterval也檢查testOnBorrow也。

由於您將此值從默認的30秒設置爲5分鐘,這意味着在數據庫斷開連接後的5分鐘內,您仍然可以獲得過時的連接。如果您的數據庫超時時間少於5分鐘...運氣不好。

爲了測試這個理論,你可以設置validationInterval爲一個荒謬的低值。

如果這有幫助(閱讀:我們找到了合適的旋鈕),您應該至少將其設置爲比數據庫超時更短的時間。因此,當數據庫決定放棄一個空閒連接時,下一個validationInterval將確保連接在下次借用前被檢查。數據庫服務器重新啓動(即沒有超時)導致的關閉連接將不受此解決方案的影響,但至少返回到正常狀態的時間也會減少。

注:我剛纔問谷歌的代碼。我不知道這是實際的代碼還是古代的代碼。

+0

的[實際的Tomcat源(http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/ pool/PooledConnection.java?view = markup)也可用,而不是查看SpringSource的er,它的副本。 –

+0

它看起來像@ A.H。很可能是正確的:驗證時間間隔也適用於借用驗證,至少在使用Tomcat的jdbc池時。 –

+0

對不起,這是一個大驚小怪,但我不認爲這就是它。我已經讓服務器在這種情況下運行了12小時以上,每10分鐘有一個腳本調用它。我整個時間每小時都會有2或3次錯誤。 我仍然會嘗試設置一個較低的值,看看會發生什麼。 –

相關問題