画像ツール一覧

デッドロック

Deadlock

データベース

複数の処理が、相手の保持するロック等の解放を循環して待ち、介入なしでは先へ進めなくなる状態です。DBは検出して一方を中断する場合があり、システム全体が永久停止するとは限りません。

🐾 猫で例えると?

お互いに相手の顔へ向けて猫パンチを放ち、肉球がヒットした状態のまま完全に動きが止まっているアメショと茶トラ猫
互いの行動がぶつかり合い、どちらも引けなくなった停止状態

茶トラが赤いおもちゃ、アメショが青いおもちゃを押さえ、二匹とも「相手のおもちゃをもらうまで自分の物は放さない」と待つ場面を想像します。この「一つを持ったまま、相手の物を待つ輪」がデッドロックです。写真の相打ちは、単なる停止と区別して考えるきっかけになります。

🐾 PR

💻 データベース運用における「デッドロック」とは?

システムの開発やデータベースの運用において、デッドロックは非常に厄介なクリティカルエラーの一つです。例えば、処理Aが「データ1」をロック(他から変更できないように占有)し、処理Bが「データ2」をロックしたとします。その後、処理Aがさらに「データ2」の書き換えを要求し、同時に処理Bが「データ1」の書き換えを要求した場合に発生します。

処理AはBのロックを待ち、BはAのロックを待つため、どちらも通常の処理では解放まで進めません。単に一方が処理中で他方が待っているロック待ちとは異なります。DBの検出機構は、この循環を見つけて解消します。

⚠️ デッドロックの仕組みと注意点

データベース管理システム(RDBMS)の多くは、デッドロックを自動的に検知する機構(デッドロック検出器)を備えています。検知された場合、システムはどちらか一方の処理を強制的にエラー(ロールバック)として終了させ、もう一方の処理を優先して進めることで全体の停止を回避します。

トランザクションの設計ミスが原因に

更新順序の食い違いは代表的な原因ですが、実際のロックはインデックスや制約、分離レベルにも関係します。デッドロックのログから、どのトランザクションが何を保持し、何を待っていたかを確認します。

-- デッドロックが発生しやすい危険なSQLの実行パターンの例

-- 【処理A】
START TRANSACTION;
UPDATE accounts SET balance = balance - 1000 WHERE id = 1; -- ① id=1をロック
UPDATE accounts SET balance = balance + 1000 WHERE id = 2; -- ③ id=2の解放を待つ(デッドロック!)

-- 【処理B(処理Aと同時期に実行)】
START TRANSACTION;
UPDATE accounts SET balance = balance - 500 WHERE id = 2;  -- ② id=2をロック
UPDATE accounts SET balance = balance + 500 WHERE id = 1;  -- ④ id=1の解放を待つ(デッドロック!)

これは独立した二つのDB接続で①②③④の順に実行したときの概念例です。最初から一つの接続で順に貼り付けても同じ状態にはなりません。検証用DBで行い、中断したトランザクションはロールバックしてから必要な処理全体を再試行します。

🛠️ デッドロックを賢く防ぐためのポイント

デッドロックは完全にゼロにすることは難しいものの、設計段階の工夫によって発生確率を大幅に下げることができます。

互いに手を出したまま止まる2匹のように、待ち合いの輪ができると処理は進みません。ロックを取る順序と保持時間を見直し、DBが一方を中断した場合の扱いも決めましょう。再試行する場合は、同じ処理を重ねても支障がないか確認が必要です。