外部キー制約項目の更新(削除)によるロックエスカレーション
外部キー制約を使用する場合、原則的に子表の外部キーにはインデックス(第一キーに含む)を設定するようにしたい。
というのは、インデックスを設置しないと整合性チェックは子表全体のテーブルフルスキャンが実行される。
そのためにデッドロックが発生する可能性を抱えることになってしまう。
インデックスの容量と更新時のコストは少なからず消費してしまうもののデッドロックに悩まされるのとは比べられない。
※ この状態がロックエスカレーションというのが適切かどうかはわからない。
オラクルはロックエスカレーションが発生しない行レベルによるロッキングと宣言しているので、
ロックエスカレーションと位置付けてはいない可能性もある。
しかし、実質的には行ロックと思っている状態が表ロックにエスカレート(拡大)しているケースではあることには変わりない。
外部キー制約による表共有ロック、共有行排他ロック
インデックスを設定してない状態での親表、子表への更新において共有ロックが発生する。
(ロックの名称とその相互関係について ⇒ 表ロックの種類と相互関係)
個別のセッション A, B において
- (セッションA) 子表のレコード削除
- (セッションB) 親表のレコード削除 (制約にかからない、異なるレコードへの操作)
この操作を行うとロックとロックリクエストは以下の表の状態になる。
セッション | 表 | ロック(取得済) | ロック要求(待機) |
A.子表の更新・削除 | 親表 | 行共有(表ロック:RS) | - |
子表 | 行排他(表ロック:RX) | - |
子表 | 排他(行ロック) | - |
B.親表の削除(更新) | 親表 | 行排他(表ロック:RX) | - |
子表 | - | 共有(表ロック:S) CASCADE発生時には共有行排他(表ロック:SRX) |
親表 | 排他(行ロック) | - |
この状態になると、共有ロック要求により、後続セッションで子表への更新操作(表ロック:RX)がすべて待機される。
単独の親表の更新では子表への共有ロックは発生しない。
共有ロックにならないケース
親表更新、子表更新の場合にはどうなるか?
- (セッションC) 親表のレコード削除
- (セッションD) 子表のレコード削除
この操作を行うとロックとロックリクエストは以下の表の状態になる。
この場合には問題は発生しない。
セッション | 表 | ロック(取得済) | ロック要求(待機) |
C.親表の削除(更新) | 親表 | 行排他(表ロック:RX) | - |
子表 | 行排他(表ロック:RX) | - |
親表 | 排他(行ロック) | - |
D.子表の更新・削除 | 親表 | 行共有(表ロック:RS) | - |
子表 | 行排他(表ロック:RX) | - |
子表 | 排他(行ロック) | - |
関連事項