3

DBがアイドル状態の接続をドロップするか、DBがダウンしてバックアップした後、Webアプリケーションで次のエラーが発生します。

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を設定したので、開いている接続のみを取得することを期待します。

それが役立つ場合:プールには通常、良好な接続と不良な接続が混在しており、問題は時間の経過とともに解消されるようですが、サーバーを12時間以上実行しても、不良な接続が返されました。再起動後、すべてが正常に機能しています(しばらくの間)。

問題をもう少しデバッグしましたが、プールが不正な接続を返しているようです。たとえば、DBですべての接続を切断した後、次のようになります。

SQL Error: 0, SQLState: 57P01

そして通常のもの-殺された接続はプールから返されます。問題は、それはアプリケーションの問題ですか?

JMX経由でプールをパージしようとしましたが、効果がないようです。もう1つの奇妙なことは、アプリが明らかに何もしていないにもかかわらず(スレッドダンプを介してチェック)、JMXBeanが7つのアクティブな接続と0つのアイドルな接続を示していることです。DBアクセスを必要とする要求を実行すると、すぐに応答が返されます(使用可能なアイドル接続がないにもかかわらず)が、JMXはその後7つのアクティブ接続と0のアイドル接続を示します。

PS。たぶん私は明らかな何かを見逃しています、そしてこれは私の側の接続管理の問題ですか?私はpersistence.xmlを介して構成されたJPAEntityManagerを使用しているので、何か間違ったことをしていて、使用後に接続が適切に閉じられない(戻されない)可能性がありますか?

4

3 に答える 3

6

実際、アプリケーションエラーを疑ったときは正しかった。

それはすべてIssue730でうまく説明されています:自動的に開始されたUnitOfWorkは決して終了しません

JpaPersistServiceを使用しているときに、アクティブなUnitOfWorkの外部でEntityManagerにアクセスしようとすると、Guiceが自動的に開始します。ただし、GuiceはこのUnitOfWorkをいつ終了するかを知らない(そしてできない)ため、決して終了しません。

結果?問題のあるスレッドは、アプリケーションの存続期間中、同じEntityManagerでスタックします。これは、アプリケーションを実行するのに悪い状態であり、しばらくすると、必然的に使用可能なメモリを使い果たしてクラッシュします。

ここでの本当のキラーは、あなたがこの間違いをしたとき、それがまったく明白ではないということです。唯一の本当のヒントは、データベースから異なるスレッド間で一貫性のないデータを取得していること(EMの第1レベルのキャッシュのため)、またはアプリケーションのメモリ消費量が増え続けることです。私の場合、それを疑うのはプール内のアクティブな接続でした。その後、詳細ログをオンにすると、アプリがプールから接続をまったく借用しておらず、代わりに、によってすでに保持されている接続を再利用していることに気付きました。閉じられていないEntityManager。

実際には、この問題のかなりの重複が報告されています:http ://code.google.com/p/google-guice/issues/list?can=1&q=UnitOfWork

于 2012-10-26T12:41:36.527 に答える
5

ワイルドショット:ここvalidationIntervalのコードは、もチェックされることを示唆していますtestOnBorrow

この値をデフォルトの30秒から最大5分に設定したため、これは、DBが接続を切断してから5分間、古い接続を取得できることを意味します。DBタイムアウトが5分未満の場合...運が悪い。

この理論をテストするためvalidationIntervalに、ばかげた低い値に設定することができます。

それが役立つ場合(読んで:正しいノブを見つけました)、少なくともDBタイムアウトよりも短い時間に設定する必要があります。したがって、DBがアイドル状態の接続をドロップすることを決定した場合、下位validationIntervalは次の借用の前に接続がチェックされることを確認します。DBサーバーの再起動(つまり、タイムアウトなし)によって閉じられた接続は、このソリューションの影響を受けませんが、少なくとも正常な状態に戻る時間も短くなります。

注:Googleにコードを要求しました。これが実際のコードなのか古代のコードなのかわかりません。

于 2012-10-16T20:10:28.877 に答える
0

META-INF/context.xmlを含めるように変更した場合validationQuery、Tomcatはで古い定義をキャッシュしている可能性がありますconf/engine/host/webapp.xml。Tomcatをシャットダウンし、そのファイルを削除して、Tomcatを再起動します。workTomcatがダウンしているときにディレクトリを削除しても問題はありません。

于 2012-10-16T14:30:57.257 に答える