2

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 コードを掘り下げて、何らかの方法で追加のデバッグ ステートメントを取得できるかどうかを確認しようとしています。残念ながら、現時点では一部の環境でしか再現できないため、デバッガーを接続することはできません。

4

1 に答える 1

0

次の行を見てください。

            if (++c % 500 == 0) {
                pstmt.executeBatch();
            }

それが実行されたが、ループが終了した場合はどうなりますか。次に、バッチに何も入れずに pstmt.executeBatch を再度呼び出します。

于 2014-12-17T19:59:47.763 に答える