MySQL Connector/J を使用して、準備されたステートメントが MySQL データベースにヒットするという奇妙な状況に陥っています。特定の環境では、既存の (> 5 分) 準備済みステートメントが長くなるという問題が定期的に発生します。executeBatch を呼び出すと、次のような例外が頻繁に発生します。
「ステートメントが閉じられた後、操作は許可されていません」
ただし、私が見ることができるステートメントを閉じる可能性のあるコードはありません。コードは次のようになります。
private void execute(MyClass myObj, List<MyThing> things) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = ConnectionHelper.getConnection();
pstmt = con.prepareStatement(INSERT_SQL);
int c = 0;
for (MyThing thing : things) {
pstmt.setInt(1, myObj.getA());
pstmt.setLong(2, thing.getB());
pstmt.addBatch();
if (++c % 500 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch();
}
finally {
ConnectionHelper.close(pstmt, con);
}
}
ConnectionHelper.close は基本的に、ステートメントと接続に対して close を呼び出すだけです。ConnectionHelper.getConnection はちょっとした穴です。java.sql.DriverManager と proxool を使用してプールから接続を大まかに取得し、それを Spring DataSourceUtils でラップします。
通常、最後の pstmt.executeBatch() で失敗しますが、他の場所で失敗することもあります。確認したところ、wait_timeout と interactive_timeout はデフォルト (間違いなく 5 分以上) に設定されています。さらに、ほとんどの場合、接続とステートメントはループ内で使用されますが、数秒後にステートメントがループの外で失敗します。DB サーバーとアプリ サーバーは同じサブネット上で実行されているため、ネットワークの問題はほとんどないようです。
この問題をデバッグする方法に関するヒントを探しています。現時点では、MySQL Connector/J コードを掘り下げて、何らかの方法で追加のデバッグ ステートメントを取得できるかどうかを確認しようとしています。残念ながら、現時点では一部の環境でしか再現できないため、デバッガーを接続することはできません。