共有ロックと排他ロック
InnoDBは標準的な行レベルロックを実装しており、主要なロックタイプとして共有ロック(Sロック)と排他ロック(Xロック)が存在します。
- 共有ロック:このロックを保持するトランザクションは行の読み取りが可能
- 排他ロック:このロックを保持するトランザクションは行の更新または削除が可能
トランザクションT1が行rで共有ロックを保持している場合:
- 別トランザクションT2による共有ロック要求は即時許可される
- T2による排他ロック要求は即時許可されない
トランザクションT1が行rで排他ロックを保持している場合、他のトランザクションによるあらゆるロック要求はT1のロック解放まで待機状態となります。
インテンションロック
InnoDBはマルチグレインロックをサポートし、行ロックとテーブルロックの共存を可能にします。インテンションロックはテーブルレベルロックで、後続の行ロックのタイプを示します。
- インテンション共有ロック(IS):行への共有ロック予定を示す
- インテンション排他ロック(IX):行への排他ロック予定を示す
ロック取得プロトコル:
- 行の共有ロック取得前にはテーブルレベルのISロック以上の取得が必要
- 行の排他ロック取得前にはテーブルレベルのIXロック取得が必要
| X | IX | S | IS | |
|---|---|---|---|---|
| X | 衝突 | 衝突 | 衝突 | 衝突 |
| IX | 衝突 | 互換 | 衝突 | 互換 |
| S | 衝突 | 衝突 | 互換 | 互換 |
| IS | 衝突 | 互換 | 互換 | 互換 |
レコードロック
インデックスレコードに対するロックで、例:
SELECT col1 FROM tbl WHERE col1 = 15 FOR UPDATE;
このクエリはcol1値が15の行の更新を防止します。インデックスが存在しない場合、InnoDBは暗黙的クラスタ化インデックスを作成してロックを実装します。
ギャップロック
インデックスレコード間の間隔に対するロックで、範囲クエリでのデータ整合性を保証します:
SELECT col1 FROM tbl WHERE col1 BETWEEN 10 AND 20 FOR UPDATE;
このロックは10~20の範囲への新規挿入を防止します。ユニークインデックスを使用するポイントクエリではギャップロックは発生しません。
ネクストキーロック
インデックスレコードロックと前方ギャップロックの組み合わせで、デフォルトのREPEATABLE READ分離レベルでファントムリードを防止します。
ロック範囲の例:
(-∞, 10] (10, 11] (11, 13] (13, 20] (20, +∞)
挿入インテンションロック
INSERT操作で使用される特殊なギャップロックで、非衝突位置への挿入を許可します:
INSERT INTO items (id) VALUES (105);
このロックは挿入位置のギャップをロックしつつ、非重複位置への挿入を並行して許可します。
オートインクリメントロック
AUTO_INCREMENT列を持つテーブル専用のテーブルレベルロックで、連続した主キー値を保証します。
innodb_autoinc_lock_mode変数でロック動作を制御可能です。
空間インデックスプレディケートロック
空間インデックスに対して最小境界矩形(MBR)を使用する述語ロックで、地理空間データの整合性を保持します。