DBAtlas · データベース運用アトラス

デッドロック / ロックの競合 (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 は必要以上の行をロックし、デッドロックの可能性を大幅に高める。

根本原因: ホットスポット

カウンター行 / キーなどの単一のリソースに、多数のトランザクションが同時に集中している。

DBAtlas で開く →