0

Java コードで JDBC バッチ更新 (Statement - void addBatch( String sql ) および int[] executeBatch()) を使用しています。このジョブは、テーブルに約 27,000 レコードを挿入し、後続のバッチで約 18,000 レコードを更新することになっています。

午前 6 時にジョブを実行すると、数千のレコードが欠落しています (これはデータベース監査ログから確認できました)。ジョブ ログから、更新ステートメントがすべての 18k レコードに対して生成されていることがわかります。すべての update ステートメントが順番にバッチに追加されることは理解していますが、バッチの先頭からのレコードのみが欠落しているようです。また、毎日固定数ではありません。ある日、最初の 4534 の更新ステートメントがスキップされ、別の日には最初の 8853 レコードがスキップされ、別の日には 5648 レコードがスキップされます。

当初、これはスレッドの問題である可能性があると考えていましたが、スキップされるブロックに常に同じ数の更新ステートメントが含まれているとは限らないため、その思考プロセスから離れました。最初の数千回の更新が挿入前に行われていると仮定すると、更新は少なくともデータベース監査ログに表示されるはずです。しかし、そうではありません。

これは、メモリ/ヒープの問題が原因であると考えています。ジョブを別の時間に実行すると、すべての 18k update ステートメントが取得され、それらが正常に実行されるからです。Oracle データベースの監査ログを確認したところ、欠落している更新ステートメントが午前 6 時の実行中にテーブルで実行されていないことがわかりました。それ以外の場合は、すべての更新ステートメントがデータベース監査ログに表示されます。

このジョブは現在ほぼ 3 年間正常に実行されており、この動作はほんの数週間前から始まりました。サーバー/環境への変更を確認しようとしましたが、何も飛び出しませんでした.

これが発生する理由を特定しようとしています。具体的には、JVM ヒープを使いすぎているプロセスがあり、その結果、更新ステートメントが上書きされたり実行されなかったりする場合です。

データベース: Oracle 11g Enterprise Edition リリース 11.2.0.3.0 - 64 ビット Java: Java バージョン "1.6.0_51" Java(TM) SE ランタイム環境 (ビルド 1.6.0_51-b11) Java HotSpot(TM) サーバー VM (ビルド 20.51-b01) 、 ミックスモード)

void main()
{
    DataBuffer dataBuffer;//assume that all the selected data to be updated is stored in this object
    List<String> TransformedList = transform(dataBuffer);
    int status = bulkDML(TransformedList);
}

public List<String> transform(DataBuffer i_SourceData) 
{
    //i_SourceData has all the data selected from 
    //the source table, that has to be updated
    List<Row> AllRows = i_SourceData.getAllRows();
    List<String> AllColumns = i_SourceData.getColumnNames();
    List<String> transformedList = new ArrayList<String>();
    for(Row row: AllRows)
    {
        int index = AllColumns.indexOf("unq_idntfr_col");
        String unq_idntfr_val = (String)row.getFieldValues().get(index);
        index = AllColumns.indexOf("col1");
        String val1 = (String)row.getFieldValues().get(index);
        String query = null;
        query =   "UPDATE TABLE SET col1 = " + val1 + " where unq_idntfr_col=" + unq_idntfr_val;//this query is not the issue either - it is parameterized in our code
        transformedList.add(query);
    }
    return transformedList;
}

public int bulkDML(List<String> i_QueryList)
{
    Connection connection = getConnection();
    Statement statement = getStatement(connection);
    try
    {
        connection.setAutoCommit(false);
        for (String Query: i_QueryList)
        {
            statement.addBatch(Query);
        }
        statement.executeBatch();   
        connection.commit();
    }
    //handle various exceptions and all of them return -1
    //not pertinent to the issue at hand
    catch(Exception e)
    {
            return -1;
    }
    CloseResources(connection, statement, null);
    return 0;
}

どんな提案でも大歓迎です、ありがとう。

4

1 に答える 1