第19回: デッドロックの見つけ方と対策 — 止まらないシステムを設計で守る

章: 第4章: データ整合性と運用

本番でシステムが突然応答しなくなる——デッドロックを疑っていますか?

「トランザクションが完了しない」「接続がタイムアウトする」——こうした症状の裏にデッドロックが潜んでいることがあります。デッドロックは完全にゼロにはできませんが、検知の方法と設計上の対策を知っていれば、被害を最小化できます。

デッドロックはなぜ起きるのか

デッドロックは、2つのトランザクションがお互いの持つロックを待ち続けて、どちらも進めなくなる状態です。MySQLのInnoDBはデッドロックを自動検知して、どちらか一方をロールバックします。しかし頻発すると処理が遅延し、ユーザー体験に直接影響します。

典型的なパターンは「テーブルAを更新してからテーブルBを更新するトランザクション」と「テーブルBを更新してからテーブルAを更新するトランザクション」が同時に走るケースです。

デッドロックの検知と対策の比較

観点 内容
ログ確認方法 SHOW ENGINE INNODB STATUSLATEST DETECTED DEADLOCK セクションを読む
自動解決 InnoDBがどちらか一方をロールバック(ER_LOCK_DEADLOCKエラーが返る)
発生を減らす設計 複数テーブルの更新順序をすべてのコードで統一する
リトライ設計 ER_LOCK_DEADLOCK を捕捉して自動再試行を実装する
トランザクション短縮 ロック保持時間を短くし、競合確率を下げる

チェックポイント: デッドロックが発生したら、まず SHOW ENGINE INNODB STATUS を実行して LATEST DETECTED DEADLOCK セクションを確認しましょう。どのトランザクションがどの順序でロックを取得したかが記録されています。更新順序の不一致が原因ならコードを統一し、再試行ロジックをアプリ側に追加します。

コードサンプル


SHOW ENGINE INNODB STATUS;

-- アプリ側では ER_LOCK_DEADLOCK を捕まえて再試行

まとめ & 次のステップ

  • デッドロックは2つのトランザクションが互いのロックを待つことで発生します
  • InnoDBは自動検知してロールバックしますが、頻発するとシステムの遅延につながります
  • SHOW ENGINE INNODB STATUS でデッドロックの原因トランザクションを特定できます
  • 複数テーブルの更新順序をコード全体で統一することが最も効果的な予防策です
  • アプリ側で ER_LOCK_DEADLOCK を捕捉し、自動再試行する設計を組み合わせましょう

次回は バックアップとリストアの基本 を学びます。障害時に確実にデータを復元できる手順を設計段階から整備する方法を見ていきましょう。

Related Articles