MySQLのロックについて調べてみました。MySQLのドキュメントは製品特有のことだけではなく、RDBに関する知識も豊富なので勉強しがいがあります。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 14.2.3 InnoDB のロックモード
ポイント
- 共有ロック(S)
- 排他ロック(X)
- インテンションロック(IS、IX)
共有ロックと排他ロック
共有ロックと排他ロックは互いに影響を与えます。トランザクションAが共有ロックを行Rに対して獲得している場合、ほかトランザクションは行Rに対して共有ロックを獲得できますが排他ロックは獲得できません。一方で、トランザクションAが排他ロックを行Rに対して獲得している場合、他のトランザクションは行Rに対して共有ロックも排他ロックも獲得できません。
実演 共有ロック
共有ロックを獲得するには SELECT ... LOCK IN SHARE MODE
文を発行します。このSELECT文でマッチした行はすべて共有ロックを獲得します。
次の例は、異なる2つのトランザクションが共有ロックを同じ行に対して獲得できる事を示します。なお、ステートメントを発行する左端にどのトランザクションかを示しています。
T1> BEGIN; Query OK, 0 rows affected (0.00 sec) T1> SELECT name FROM books WHERE id = 1 LOCK IN SHARE MODE; +-------------------------+ | name | +-------------------------+ | Refactoring 2nd Edition | +-------------------------+ 1 row in set (0.00 sec) T2> BEGIN; Query OK, 0 rows affected (0.00 sec) T2> SELECT name FROM books WHERE id = 1 LOCK IN SHARE MODE; +-------------------------+ | name | +-------------------------+ | Refactoring 2nd Edition | +-------------------------+ 1 row in set (0.00 sec)
次の例は、共有ロックが獲得されている行に対して排他ロックは獲得できないことを示します。
T1> BEGIN; Query OK, 0 rows affected (0.00 sec) T1> SELECT name FROM books WHERE id = 1 LOCK IN SHARE MODE; +-------------------------+ | name | +-------------------------+ | Refactoring 2nd Edition | +-------------------------+ 1 row in set (0.00 sec) T2> BEGIN; Query OK, 0 rows affected (0.00 sec) T2> UPDATE books SET name = 'Refactoring 2nd Edition(NEW)' WHERE id = 1; ...(待機)
実演 排他ロック
排他ロックは UPDATE
や SELECT ... FOR UPDATE
文などで獲得できます。
次の例は、異なる2つのトランザクションで同じ行に対し排他ロックまたは共有ロックをかけることができない事を示します。
T1> BEGIN; Query OK, 0 rows affected (0.00 sec) T1> SELECT * FROM books WHERE id = 1 FOR UPDATE; +----+-------------------------+--------------------------+---------------+ | id | name | publisher | author | +----+-------------------------+--------------------------+---------------+ | 1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler | +----+-------------------------+--------------------------+---------------+ 1 row in set (0.00 sec) T2> BEGIN; Query OK, 0 rows affected (0.00 sec) T2> SELECT * FROM books WHERE id = 1 LOCK IN SHARE MODE; ...(待機)
テーブルに対するロック
共有ロック、排他ロックをテーブルに対して明示的に獲得する事もできます。テーブルに対してロックを獲得するには LOCK TABLES
を、ロックを開放するには UNLOCK TABLES
を使います。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.3.5 LOCK TABLES および UNLOCK TABLES 構文
インテンションロック
テーブルレベルに対するロック。トランザクションがテーブル内の各行でどのようなタイプ(S、X)を取ろうとしているのかを示すのに使われます。共有ロック、排他ロックは実際に行に対しロックを獲得するのに対し、インテンションロックは意図を示すので少々難しく感じます。
インテンションロックは実際にはテーブルに対するロック以外何もブロックしません。ドキュメントには以下のように記述されています。インテンションロックはテーブルに対するロックと、行に対するロックを共存させるための仕組みにすぎないため、テーブルロックを使用しない場合(ほとんどの場合だと思います)は意識する必要がないように感じます。
インテンションロックでは、完全なテーブルリクエスト (LOCK TABLES ... WRITE など) 以外は何もブロックされません。IX および IS ロックの主な目的は、だれかが行をロックしていることや、テーブル内の行をロックしようとしていることを示すことです。
インテンションとは ... 意図、意向、意図するもの、目的、(交際中の女性に対する男性の)結婚の意志