0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【MySQL】大量DELETEバッチでAPIがタイムアウトした話と対処まとめ

0
Posted at

エラー内容

DBテーブルの大量レコードを削除するバッチ実行中に、同じDBへ読み書きするAPIリクエストを継続的に投げると、以下の問題が発生しました。

  • 性能劣化:一部リクエストで20〜30秒の遅延
  • エラー発生:一部リクエストでタイムアウト

{ "message": "Endpoint request timed out" }

原因

削除バッチによる長時間のロック保持により、APIリクエストがロック待ちとなりタイムアウトしていました。

主な要因は以下の通りです。

① ギャップロック(Next-Key Lock)

MySQLのデフォルト分離レベルである REPEATABLE READ では、
削除対象の行だけでなく「インデックスの範囲」もロックされます。

今回のSQL:

DELETE FROM table WHERE create_date < ten_minutes_ago;

このような 範囲条件(<, >, BETWEENなど) は、
インデックスを利用する場合にギャップロックが発生しやすく、
広範囲のロックにつながります。

② 長時間トランザクション

DELETEを1トランザクションで大量に実行していたため、

  • トランザクションが長時間継続
  • ロックが解放されない

という状態になっていました。

※ ロックは「テーブル単位」ではなく「トランザクション単位」で保持されます。

③ 待ち行列の発生

(高負荷時に)APIリクエストがロック待ちとなり、

  • リクエストが詰まる
  • タイムアウトが連鎖

という典型的な「スローダウン → 崩壊」パターンに陥っていました。

対応内容

対応①:トランザクション分離レベルの変更

削除バッチのセッションで、分離レベルを READ COMMITTED に変更しました。

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

効果は以下の通りです。

  • ギャップロック(Next-Key Lock)が抑制される
  • 削除対象行のみロックされるようになる
  • APIリクエストへの影響が軽減される

ただし、注意点として、READ COMMITTEDでは以下の特性があります。

  • 他トランザクションのコミット結果が見える
  • 同一トランザクション内でも読み取り結果が変わる可能性がある(ファジーリード)

ただし今回のバッチでは

  • 単方向処理(DELETE → COMMIT)
  • 同じデータを複数回読むことがない

ため、実用上問題ないと判断しました。

また、この設定はセッション単位のため、API側の挙動には影響しません。

トランザクション分離レベルの詳細は、下記をご参照ください。

対応②:トランザクションの分割(COMMITの細分化)

以下のように、テーブル単位でCOMMITするように変更しました。

DELETE FROM table1 WHERE create_date < ten_minutes_ago;
COMMIT;  -- ここでロック解放

DELETE FROM table2 WHERE create_date < ten_minutes_ago;
COMMIT;  -- ここでロック解放

これにより、以下の効果が得られます。

  • トランザクション時間の短縮
  • ロック保持時間の短縮
  • COMMITごとにロックが解放されるため、待機中リクエストが処理可能になる

まとめ

上記対応により、エラーや性能劣化が解消されたことを確認できました。

ただし、大量DELETEはそのまま流さず、分割して実行することも大事です。
今回は上記の対応としましたが、そのような方策が可能であれば検討すべきでしょう。

以上!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?