デッドロック
Deadlock
複数の処理(プロセスやスレッド)が互いに相手の占有しているリソースの解放を待ち合ってしまい、どちらの処理も永続的に進めなくなってしまう完全な停止状態のこと。
🐾 猫で例えると?
いつもは仲良しな2匹ですが、たまにじゃれ合いから本気の喧嘩へとエスカレートすることがあります。お互いに渾身の猫パンチを同時に繰り出した結果、相打ちの体勢のまま「次にどう動くか」を待ち合って完全にフリーズしてしまいました。この、お互いが相手の次の動き(リソースの解放)を待ち続けて身動きが取れなくなる現象が「デッドロック」です。
🐾 猫あるある:IT現場の日常
- 廊下で鉢合わせして見つめ合って固まる:2つのプロセスが同じデータに対して同時にアクセスを試み、互いにロックの解除を待ち続けて処理が中断する現象。
- 1つのおもちゃを同時に噛んでどちらも動けない:複数のスレッドが互いに必要な共有リソースを占有し合い、次の処理へ進むための解放待ちがループする状態。
- 行動を起こすトリガーを互いに待ち合って膠着する:クライアントとサーバーが、相手からのデータ送信や応答の完了を相互に待ち続けて通信が完全にストップする。
💻 データベース運用における「デッドロック」とは?
システムの開発やデータベースの運用において、デッドロックは非常に厄介なクリティカルエラーの一つです。例えば、処理Aが「データ1」をロック(他から変更できないように占有)し、処理Bが「データ2」をロックしたとします。その後、処理Aがさらに「データ2」の書き換えを要求し、同時に処理Bが「データ1」の書き換えを要求した場合に発生します。
処理Aは処理Bがデータ2を離すのを待ち、処理Bは処理Aがデータ1を離すのを待つという、終わりのない相互待ちのループに陥ります。プログラムは自動的にこの状態を解消できないため、タイムアウトなどの例外処理が発生するか、システムが強制終了するまで固まり続けてしまいます。
⚠️ デッドロックの仕組みと注意点
データベース管理システム(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の解放を待つ(デッドロック!)
上記の例では、処理Aと処理Bが異なる順番で同じデータを更新しようとしているため、運悪くタイミングが重なると確実にデッドロックを引き起こします。実務ではこれを防ぐためのコーディング規約や設計の共通化が極めて重要です。
🛠️ デッドロックを賢く防ぐためのポイント
デッドロックは完全にゼロにすることは難しいものの、設計段階の工夫によって発生確率を大幅に下げることができます。
- リソースへのアクセス順序を統一する: 複数のデータを更新する際は、どの処理からでも必ず同じ順番(例:主キーの昇順)でアクセスするように実装し、待ち合いのループを根本から防ぎます。
- トランザクションの時間を最小限に抑える: データをロックしている時間をできるだけ短くするため、不要な処理をトランザクション内に含めず、クエリを実行したら速やかに確定(コミット)させます。
- 適切なロックタイムアウトを設定する: 万が一デッドロックに近い状態に陥っても、一定時間応答がなければ自動でエラーを返して処理を解放し、システム全体がフリーズするのを防ぎます。
お互いの手が顔にヒットしたまま、完全に動きを止めてしまったアメショと茶トラ。システム開発でも、こうした競合状態(デッドロック)を未然に防ぐ正しいアクセス順序を設計し、2匹が毎日仲良くリソースを共有して毛づくろいし合えるような、平和でスマートなシステムを構築していきましょう。