InnoDBのロックについてまとめた
MySQLを実務で触っているのですが、改めてInnoDBのロックの仕様について頭の整理をするためにまとめてみました。
ロックの種類
共有ロックと排他のロックの2種類があり、トランザクション分離レベルによって挙動が変わります。
InnoDBのデフォルトは“REPEATABLE READ”で、SELECT @@transaction_ISOLATIONで確認が可能です。
トランザクション分離レベルについては以下を参照。
https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
なお以下の説明は“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)では読み取りは許可されます。
ロックの範囲
共有ロック、排他ロックが適用される範囲にはいくつか種類があります。
各ロックの相関関係や扱われ方については、自分で書くよりこちらのブログの説明が視覚的にも分かりやすいので紹介いたします。
レコードロック
- 特定のレコードに対してのロック。
ギャップロック
- インデックスの隙間に対してのロック。
ネクストキーロック
- レコードロックとギャップロックを併用したロック。
テーブルロック
- 対象のテーブル全体へのロック。
ロックの範囲はどのように決まるのか
- インデックスが貼られている、またはUNIQUE制約のあるカラムを対象にした場合は「レコードロック」or「ギャップロック」or「ネクストキーロック」
- 上記以外は「テーブルロック」
参考
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
https://www.wakuwakubank.com/posts/201-mysql-lock/
https://qiita.com/mizzwithliam/items/31fb68217899bd0559e8
https://softwarenote.info/p1067/
https://cosol.jp/techdb/2022/09/rdbms_compare_conc_cntl_transaction/