この質問はSOで数回、他のサイトで何度も尋ねられています。しかし、満足のいく答えは得られませんでした。
私の問題:
単純な[〜#〜] jdbc [〜#〜]を使用してmysqlデータベースを介して接続するJava WebアプリケーションGlassfishアプリケーションサーバー。
次の構成でglassfishサーバーの接続プーリングを使用しました。
初期プールサイズ:25
最大プールサイズ:100
プールのサイズ変更数量:2
アイドルタイムアウト:300秒
最大待機時間:60,000ミリ秒
このアプリケーションは過去3か月間配備されており、問題なく実行されていました。
ただし、過去2日間から、ログイン時に次のエラーが発生します。
部分的なStackTrace
com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed due to underlying exception/error:
** BEGIN NESTED EXCEPTION **
com.mysql.jdbc.CommunicationsException
MESSAGE: Communications link failure due to underlying exception:
** BEGIN NESTED EXCEPTION **
Java.io.EOFException
MESSAGE: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
STACKTRACE:
Java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.Java:1997)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.Java:2411)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.Java:2916)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.Java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.Java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.Java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.Java:1313)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.Java:1448)
............
............
my application traces....
このエラーが突然発生した原因は?私はこのために多くの時間を失いました。
EDIT:サーバーを再起動しても問題は解決しません。 DBAによると、重要なmysqlサーバー構成の2つは次のとおりです。
wait_timeout: 1800秒
connect_timeout: 10秒
NOTE:同じデータベースに接続し、異なるプールを使用する同じサーバーにデプロイされた他のアプリケーションは、スムーズに実行されています。
EDIT-2:多くのことを読んで、いくつかの肯定的な結果を期待した後、接続プールにこれらの変更を加えました。
最大待機時間: 0(以前は60秒でした)
接続検証:必須
検証方法: table
テーブル名:デモ
最大1回検証: 40秒
Creation Retry Attempts: 1
再試行間隔: 5秒
最大接続使用率: 5
そして、アプリケーションが3日間一貫して実行されているため、これは機能しました。しかし、私はこれについて非常に奇妙で興味深い結果を得ました。接続プールを監視しているときに、次の図が見つかりました。
NumConnAcquired: 44919カウント
NumConnReleased: 44919カウント
NumConnCreated: 9748カウント
NumConnDestroyed: 9793カウント
NumConnFailedValidation: 70 Count
NumConnFree: 161カウント
NumConnUsed: -136カウント
HowNumConnFree
はMaximum Pool Size = 100
があるので161になりますか?
HowNumConnUsed
は-136、negative数?
HowNumConnDestroyed
>NumConnCreated
?
接続は、おそらくファイアウォールのアイドルタイムアウトなどが原因で失敗しました。失敗時に再接続するようにJDBCドライバーを設定していない場合、新しい接続を開かない限り、このエラーは消えません。
データベース接続プールを使用している場合(あなたはareを使用しています、そうですか?)、おそらく、接続をアプリケーションに戻す前に、接続が機能しているかどうかを確認するクエリ。 Apache commons-dbcpでは、これはvalidationQuery
と呼ばれ、SELECT 1
のような単純なものに設定されることがよくあります。
MySQLを使用しているため、実際のSQLクエリを発行するよりも軽いConnector/J固有の「ping」クエリを使用し、検証クエリを/* ping */ SELECT 1
(ping部 正確にする必要があります )。
ほとんどの場合、データベースが再起動したか、データベースへのネットワーク接続が切断されたことを意味します(例:NAT接続がタイムアウトしました)...接続。
Webコンテナを再起動しても問題が解決しない場合は、さらに深刻な問題である可能性があります。
次の質問をしました:
How can the NumConnFree become 161 as I have Maximum Pool Size = 100 ?
How can the NumConnUsed become -136, a negative number ?
How can the NumConnDestroyed > NumConnCreated ?
一見すると、これらは意味をなしません。ただし、これらは、スレッドセーフでない方法で更新された使用カウンタの結果である可能性があります。これは必ずしも元の問題とは関係ありません。
これはJavaのEndOfFileExceptionであり、カーソルの開始点が終了点にあるとき、または予期しない例外のためにデータベース接続が閉じられたときに発生します。
明確な解決策はありませんが、アプリサーバーとデータベース間の通信を妨害しているようです。以下は、問題を特定するために試みることができるいくつかのことです。
これがmysqlの問題か、またはJavaコードの問題かを判断します。アプリサーバーと同じホストからコマンドラインツールを使用してmysqlに接続し、同様のSQLを発行してログインします。単純なJava選択を行うコード、同じインフラストラクチャーにデプロイし、何が起こるかなどを確認します。また、mysqlサーバーのログを確認し、何か有用なものが見つかるかどうかを確認します
アイドル状態の接続を閉じるには、アプリサーバー内で実行される接続プールコードによる方法と、mysql自体による方法の2つがあります。必ず両方の設定を確認してください
ネットワークインフラストラクチャ設定が最近変更されていないか確認してください。アプリサーバー<-> mysql接続を妨げる新しいファイアウォールルールはありましたか?オープンを禁止する設定はありましたかTCP Xより長い接続アイドル状態ですか?
接続プーリングの可能性を排除するために、別の接続プーリングライブラリを試してください。
がんばろう
ファイアウォール関連の問題である可能性があります。
私はこの問題を抱えていましたが、MySQLデータベースの設定を変更することはできませんでした。そのため、SQLコネクタクラスでは、接続が再度開始される前に必ず接続が閉じられるようにしました。何かのようなもの:
public static Connection getConnection() {
if (DatabaseConnnector.conn == null) {
initConn();
} else {
try {
DatabaseConnnector.conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
initConn();
}
return DatabaseConnnector.conn;
}
これで問題は解決しました。