章: 第4章: データ整合性と運用
本番でシステムが突然応答しなくなる——デッドロックを疑っていますか?
「トランザクションが完了しない」「接続がタイムアウトする」——こうした症状の裏にデッドロックが潜んでいることがあります。デッドロックは完全にゼロにはできませんが、検知の方法と設計上の対策を知っていれば、被害を最小化できます。
デッドロックはなぜ起きるのか
デッドロックは、2つのトランザクションがお互いの持つロックを待ち続けて、どちらも進めなくなる状態です。MySQLのInnoDBはデッドロックを自動検知して、どちらか一方をロールバックします。しかし頻発すると処理が遅延し、ユーザー体験に直接影響します。
典型的なパターンは「テーブルAを更新してからテーブルBを更新するトランザクション」と「テーブルBを更新してからテーブルAを更新するトランザクション」が同時に走るケースです。
デッドロックの検知と対策の比較
| 観点 | 内容 |
| ログ確認方法 | SHOW ENGINE INNODB STATUS の LATEST 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を捕捉し、自動再試行する設計を組み合わせましょう
次回は バックアップとリストアの基本 を学びます。障害時に確実にデータを復元できる手順を設計段階から整備する方法を見ていきましょう。