【でっどろっく】

デッドロック とは?

最終更新:
💡 互いに必要なロックの解放を待って進めない状態

処理が互いのロックなどの解放を待ち、進めなくなる状態。2つの処理の待ち関係、ロック順序の統一、DBの検出と中断、タイムアウトの限界を解説します。

📌 このページのポイント
デッドロック:互いの解放を待って進めない処理AXを保持BのYの解放を待つ処理BYを保持AのXの解放を待つA → Bを待つ待ち関係が循環する取得順序をそろえることが予防に役立つ検出・中断・再試行は製品の仕様に従う
矢印は解放を待つ相手への方向で、ロック取得成功やデータ通信ではありません。AがBを待ちBがAを待つ例で、3つ以上の処理で循環する場合もあります。
ひよこ ひよこ
どんなときに、待ち合うの?
ペンギン先生 ペンギン先生
処理AがXを持ってYを待ち、処理BがYを持ってXを待つ例だよ。互いが進めないので、必要なロックも解放されない。片方が長いだけの待ちと、この循環した待ちを区別する。
ひよこ ひよこ
テーブルではなく、行をロックすれば防げる?
ペンギン先生 ペンギン先生
行ロックでも起こる。PostgreSQLの公式例では、2つの取引が別々の行を先に更新し、それぞれ相手が持つ行を更新しようとして待ち合う。ロックを小さくするだけでは予防を保証できない。
ひよこ ひよこ
DBは、自動で直してくれる?
ペンギン先生 ペンギン先生
PostgreSQLは検出すると、関係するトランザクションの一つを中断して他を進める。ただし、どれが中断されるかには依存できない。アプリはエラーを処理する必要があり、全ての仕組みで同じ動作とは限らない。
ひよこ ひよこ
どう予防するの?
ペンギン先生 ペンギン先生
複数の対象をロックする全ての処理で、例えばXからYという順序をそろえる方法がある。関連する処理全体で守ることが大切だ。取得後に長く待つ処理も避け、必要以上にロックを持ち続けないようにする。
ひよこ ひよこ
タイムアウトなら、必ず解決?
ペンギン先生 ペンギン先生
待つ時間を制限するだけでは足りない。失敗した処理を中断し、持っているロックを解放するなどの後始末が必要だ。再試行する場合も、トランザクション全体や外部への処理の扱いを確認するんだ。
もっと詳しく知りたい人へ

中断されたトランザクションは、途中のSQLだけ再試行する?

途中だけを機械的に再実行せず、中断されたトランザクションの状態と製品の仕様を確認します。PostgreSQLではデッドロックにより中断されたトランザクションを再試行する対応が示されています。外部送信などDB外の処理がある場合は、重複して実行しない設計も必要です。

図の矢印は、ロックを取れたという意味?

いいえ。矢印は相手が持つロックの解放を待つ方向です。AからB、BからAの待ちが循環しているため、介入がなければ先へ進めない例を示しています。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「デッドロック」って出てきたら「互いに必要なロックの解放を待って進めない状態」と思えばだいたいOK!
📖 おまけ:英語の意味
「Deadlock」 = 行き詰まり・膠着状態
💬 ここでは、処理がお互いのロックなどを待つことで進めなくなる状態を扱います。単に実行が遅いこととは違います。

参考資料

← 用語集にもどる