MySQLのロックに関する調査メモ その3 - @ledsun blog の続きです。
SHOW ENGINE INNODB STATUS\G
で出力されるロック情報を眺めていたら意味がわかってきました。
まずテーブルに格納されているレコードの情報です。
select * from mysqlcasual; +----+------+------+ | id | col1 | col2 | +----+------+------+ | 1 | 2 | 0 | | 2 | 4 | 0 | | 3 | 6 | 0 | | 4 | 8 | 0 | | 5 | 10 | 0 | | 6 | 12 | 0 | | 7 | 14 | 0 | | 8 | 16 | 0 | +----+------+------+
1つ目のレコードを選択
begin;SELECT id, col1 FROM mysqlcasual WHERE col1 = 2 FOR UPDATE;
三つのロック情報が出てきます。 一つ目から見ていきます。
RECORD LOCKS space id 173 page no 4 n bits 80 index idx_col1 of table `sandbox`.`mysqlcasual` trx id 7731 lock_mode X Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 4; hex 80000002; asc ;; 1: len 4; hex 80000001; asc ;;
index idx_col1 of table
はインデックス idx_col1 に対するロックであることを表しています。
lock_mode X
はネクストキーロックであることを表しています。無印がネクストキーロックです。
0: len 4; hex 80000002; asc ;; 1: len 4; hex 80000001; asc ;;
はロックしているレコードを表してます。
80000002
はcol1カラムの値が2、80000001
はidカラムの値です。
選択するレコードを変えてみます。
2つ目のレコードを選択
begin;SELECT id, col1 FROM mysqlcasual WHERE col1 = 4 FOR UPDATE;
RECORD LOCKS space id 173 page no 4 n bits 80 index idx_col1 of table `sandbox`.`mysqlcasual` trx id 7733 lock_mode X Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 4; hex 80000004; asc ;; 1: len 4; hex 80000002; asc ;;
80000004
と80000002
になりました。
次のロック情報を見てみましょう。
2つ目のロック情報
RECORD LOCKS space id 173 page no 3 n bits 80 index PRIMARY of table `sandbox`.`mysqlcasual` trx id 7733 lock_mode X locks rec but not gap Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 4; hex 80000002; asc ;; 1: len 6; hex 00000000162a; asc *;; 2: len 7; hex aa0000011e011d; asc ;; 3: len 4; hex 80000004; asc ;; 4: len 4; hex 80000000; asc ;;
index PRIMARY of table
とあるので、プライマリーインデックスへのロックです。セカンダリーインデックスをロックするとプライマリーインデックスもロックされるやつですね。
lock_mode X locks rec but not gap
は、レコードロックを表してます。ギャップロックでないものがレコードロックです。
0: len 4; hex 80000002; asc ;; 1: len 6; hex 00000000162a; asc *;; 2: len 7; hex aa0000011e011d; asc ;; 3: len 4; hex 80000004; asc ;; 4: len 4; hex 80000000; asc ;;
80000002
と80000004
と80000000
はレコードの値を表していそうです。
00000000162a
とaa0000011e011d
は謎です。プライマリーインデックスとidex_col1を表しているのかもしれません。
上は2つ目のレコードです。1つ目のレコードは下になります。
0: len 4; hex 80000001; asc ;; 1: len 6; hex 00000000162a; asc *;; 2: len 7; hex aa0000011e0110; asc ;; 3: len 4; hex 80000002; asc ;; 4: len 4; hex 80000000; asc ;;
00000000162a
は変わりません。
aa0000011e011d
はaa0000011e0110
になりました。
うーん、これはちょっとよくわかりません。
3つ目のロック情報
RECORD LOCKS space id 173 page no 4 n bits 80 index idx_col1 of table `sandbox`.`mysqlcasual` trx id 7733 lock_mode X locks gap before rec Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 4; hex 80000006; asc ;; 1: len 4; hex 80000003; asc ;;
index idx_col1 of table
なのでidx_col1へのロックです。
lock_mode X locks gap before rec
なので、ギャップロックです。
0: len 4; hex 80000006; asc ;; 1: len 4; hex 80000003; asc ;;
は、3つ目のレコードを表しています。 ギャップロックなので、3つ目のレコードの手前までをロックしているようです。
もしかして、1つ目のネクストキーロックを、2つ目のレコードロックと3つ目のギャップロックで実現していることを表現しているのでしょうか?