1

質問したいのですが、OutOfMemoryErrorバッチ挿入中に処理するのは普通ですか?

次のコードを使用して、mysql にバッチ挿入しています。

try
{
    Connection con = null;
    PreparedStatement ps = null;

    con = Manager.getInstance().getConnection();
    ps = con.prepareStatement("INSERT INTO" + 
    " movie_release_date_pushed_to_subscriber"
    + "(movie_id,cinema_id,msisdn,sent_timestamp)VALUES(?,?,?,?)");

    for (String msisdn : subscriberBatch)
    {
        try
        {
            ps.setInt(1, movieToBeReleased.getMovieId());
            ps.setInt(2, movieToBeReleased.getCinemaId());
            ps.setString(3, msisdn);
            ps.setTimestamp(4, new java.sql.Timestamp(new Date().getTime()));
            ps.addBatch();
        }
        catch (OutOfMemoryError oome)
        {
            ....
            ps.executeBatch();
        }
    }

    ps.executeBatch();
}
catch (Throwable e)
{
    ....
}
finally
{
    try
    {
        Manager.getInstance().close(ps);
        if (con != null)
        {
            con.close();
        }
    }
    catch (Throwable e)
    {
        ....
    }
}

注:どんな種類のアドバイス/推奨事項も大歓迎です。

4

2 に答える 2

5

いいえ、正常ではありません。そして、キャッチハンドラーはまったく効果がありません。OOME をキャッチしても、根本的な原因であるプログラム メモリの枯渇を奇跡的に解決することはできません。ランタイムがメモリを再利用するために最善を尽くし、失敗した後に、このエラーが発生します。その時点でコードを実行しようとしてはいけません。メッセージをログに記録することさえできないかもしれません!

なんらかの理由でバッチ ステートメントが OOME を引き起こす可能性があると思われる場合は、次のいずれかを行う必要があります。

  • バッチ サイクルを小さな「バケット」に分割する
  • プログラムで使用できるメモリを増やす
于 2013-02-26T11:25:32.190 に答える
2

を取得した場合、バッチを実行しようとしても意味がありませんOutOfMemoryErrorINSERTただし、クエリをand に置き換えることができますINSERT IGNORE INTO。OOME の場合は、JVM の再起動後にバッチを再度実行するようにユーザーに依頼してください。

主キーがテーブルに既に存在する場合は挿入をINSERT IGNORE INTO実行しないため、アプリがクラッシュした場所からバッチが再開されます。

ただし、これはおそらくこの状況を回避するための非常に汚い方法であることを警告する必要があります。

于 2013-02-26T11:27:53.953 に答える