0

コードはキューからデータを取得し、それを準備済みステートメントにバッチとして追加し、バッチを実行してからコミットします。

int counter = 0;
while (!this.dataQueue.isEmpty()
        && counter <= config.MAX_FLUSH_COUNT) {
    DataRecord record = this.dataQueue.poll();
    if (record.ip.length() > 40) {
        record.ip = record.ip.substring(0, 40);
    }
    try {
        this.dataFlush.setInt(1, record.uid);
        this.dataFlush.setInt(2, record.fid);
        this.dataFlush
                .setTimestamp(3, new Timestamp(record.time));
        this.dataFlush.setString(4, record.ip);
        this.dataFlush.addBatch();
    } catch (Exception ex) {
        Log.logError("Error building record: " + ex.getMessage());
    }
    counter++;
}
if (counter > 0) {
    try {
        this.dataFlush.executeBatch();
        this.dataFlush.getConnection().commit();
    } catch (SQLException ex) {
        Log.logError("Error executing flush: " + ex.getMessage());
    }
}

このフラッシュには数千のエントリ (MAX_FLUSH_COUNT でバッチあたり 2000 に制限) が含まれる可能性があるため、デッドロックが発生することがあります (フラッシュは 8 秒ごとに実行され、デッドロックは約 5 ~ 6 時間ごとに発生します)。

編集:これは私の準備されたステートメントです:

Connection conn = DBBase.getConnection();
conn.setAutoCommit(false);
this.snatchFlush = conn.prepareStatement("INSERT INTO slog (uid, fid, time, ip) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE fid=VALUES(fid), time=VALUES(time), ip=VALUES(ip)");

uid は、このテーブルの主キーです。データベース エンジンは InnoDB であり、外部キーもトリガーもありません。このテーブルは、Web サーバーとこのアプリケーションによって同時に読み書きされる可能性がありますが、これはほとんどありませんが可能です。

最初の変更は、バッチを複数のバッチに分割し、そのサイズを 200 ~ 500 データセットに制限することです。

今の問題: デッドロックが発生した場合、通常の解決策はトランザクションを再開することです。

これは、データを dataFlush Prepared Statement に再度追加し、executeBatch して再度コミットする必要があるということですか? はいの場合、キューからポーリングされたデータを保存する必要があることを意味します。そうしないとデータが失われるためです。

ポーリングされたデータを保存する必要のない、より良い解決策はありますか? (executeBatchはバッチデータを削除するため、catch-Blockでの単純なexecuteBatchとcommitは機能しないと想定しています)。

4

0 に答える 0