デッドロック / ロックの競合 (ORA-00060、1213、40P01)
デッドロックが発生した (Oracle ORA-00060、MySQL 1213、PG 40P01、MSSQL 1205)。グラフを取得し、パターンを把握し、再発を防ぐ。デッドロックは設計によって解消するものであり、目標はその頻度を減らすことである。
まずデッドロックグラフを取得する
どの 2 つ (またはそれ以上) のセッションが、どのリソースで、どのロックモードで衝突したか? これを確認せずに当てずっぽうの修正をしない。
-- Check the trace file referenced in the alert log (deadlock graph). For history:
SELECT * FROM dba_hist_active_sess_history WHERE event LIKE 'enq: TX%' ORDER BY sample_time DESC FETCH FIRST 20 ROWS ONLY;- グラフを取得した — 2 つのトランザクションが逆の順序でリソースをロックしている
- 多数のトランザクションが単一の行 / テーブルに集中している (ホットスポット)
- 広範囲のロックがある (多数の行がロックされる)
ロックしているクエリはインデックスを使用しているか?
インデックスがないと、UPDATE/DELETE は WHERE 句を満たすために多数の行 (テーブル全体の場合もある) をロックする → デッドロックの原因。実行計画を確認する。
EXPLAIN <the UPDATE/DELETE involved in the deadlock>; -- type=ALL means a full scan, no index- インデックスがない / フルスキャンを行っている
- インデックスはあるが、それでも競合する
根本原因: 逆順のロック
デッドロックの最も一般的な原因: 2 つのトランザクションが異なる順序でリソースにアクセスしている。A→B と B→A が同時に起こるとデッドロックになる。
根本原因: インデックス不足 → 広範なロック
インデックスのない UPDATE/DELETE は必要以上の行をロックし、デッドロックの可能性を大幅に高める。
根本原因: ホットスポット
カウンター行 / キーなどの単一のリソースに、多数のトランザクションが同時に集中している。