3

何百万ものレコードに対してバッチ更新の準備済みステートメントを使用していましたが、400k を超えるレコードを実行した後、最終的に実行時に次のエラーが発生しました。

java.sql.SQLException: ORA-01000: 開いているカーソルの最大数を超えました

これが次のコードによって引き起こされているかどうかはわかりません

try{    
conn = ConnectionManager.getConnection();
// turn off autocommit
conn.setAutoCommit(false);

PreparedStatement stmt = conn.prepareStatement(query);

//for each of the records to be updated
for(int k=0;k<objects.length;k++) { 

    stmt.setString(1, objects[k].getValueA());
    stmt.setString(2, objects[k].getValueB());

    stmt.addBatch();

    //running batch execute on every 10000 records
    if(k%10000 == 0 || k == objects.length-1) {
        // submit the batch for execution
        int[] updateCounts = stmt.executeBatch();

        conn.commit();

        if(k < objects.length-1)
        {
            stmt.close();
            stmt = conn.prepareStatement(query);
        }
    }
}
}catch( Exception e ) {
    e.printStackTrace();
}finally {
    if(conn!=null){
        conn.close();
    }
}

これにより、接続がコミットされた後、PreparedStatement が閉じられ、新しい PreparedStatement に置き換えられます。同じ接続の繰り返しのコミットがこの問題を引き起こしている可能性があるかどうかはわかりません。

誰でも問題の解決策を提案したり、準備されたステートメントのこのバッチ更新を処理するためのより良いアーキテクチャを提案したりできますか?

P/S: エラー行は実際には文の実行を削除することを指していますが、これが根本的な原因ではないと思います。バッチ更新の準備された文コードが追加される前は、この問題は存在しませんでした。

try {
    if ( hasData ) {
        conn = ConnectionManager.getConnection();
        CommonStore.deleteRecords( conn, queryStr ); //the error point to this line
        hasData = false;
    }
}catch( Exception e ) {
    e.printStackTrace();
}finally {
    if(conn!=null){
        conn.close();
    }
}

提案をありがとう

4

1 に答える 1

0

私が観察したことの1つはこれです:

if(k < objects.length-1)
{
    stmt.close();
    stmt = conn.prepareStatement(query);
}

オブジェクトの代わりに、再利用することをclosingstmt勧めします。これは回避できる単なるオーバーヘッドです。

同じものを閉じて再度開くことは何の目的にもならないと思いますPreparedStatementPreparedStatement.clearParameters()また、後で電話することを検討することもできますaddBatch()

于 2012-08-27T04:38:43.000 に答える