MySQLを実務で触っているのですが、改めてInnoDBのロックの仕様について頭の整理をするためにまとめてみました。
ロックの種類
共有ロックと排他のロックの2種類があり、トランザクション分離レベルによって挙動が変わります。
InnoDBのデフォルトは"REPEATABLE READ"で、SELECT @@transaction_ISOLATION
で確認が可能です。
トランザクション分離レベルについては以下を参照。
MySQL :: MySQL 8.0 Reference Manual :: 15.7.2.1 Transaction Isolation Levels
なお以下の説明は"REPEATABLE READ"での挙動になります。
共有ロック
- 別トランザクションからの読み取り(SELECT)を許可し、更新(INSERT, UPDATE, DELETE)は禁止します。
- SELECTする際にFOR SHARE(MySQL 8.0.0以前の記法だとLOCK IN SHARE MODE)を付与すると共有ロックをかけられます。
排他ロック
- 別トランザクションからの読み取り(SELECT)、更新(INSERT, UPDATE, DELETE)の双方を禁止します。
- INSERT, UPDATE, DELETEする際に排他ロックがかかります。
- ただ必ずしもすべてのSELECTが禁止されるわけではなく、通常のSELECT(non-locking read / consistent read)では読み取りは許可されます。
ロックの範囲
共有ロック、排他ロックが適用される範囲にはいくつか種類があります。
各ロックの相関関係や扱われ方については、自分で書くよりこちらのブログの説明が視覚的にも分かりやすいので紹介いたします。
レコードロック
- 特定のレコードに対してのロック。
ギャップロック
- インデックスの隙間に対してのロック。
ネクストキーロック
- レコードロックとギャップロックを併用したロック。
テーブルロック
- 対象のテーブル全体へのロック。
ロックの範囲はどのように決まるのか
参考
MySQL :: MySQL 8.0 Reference Manual :: 15.7.1 InnoDB Locking
MySQL|占有ロック(FOR UPDATE)と共有ロック(LOCK IN SHARE MODE) - わくわくBank
MySQL - InnoDBのロック関連まとめ - Qiita
良く分かるMySQL Innodbのギャップロック - Qiita
主要RDBMS製品の比較 – 同時実行制御, トランザクション分離レベル | コーソルDatabaseエンジニアのBlog