@ledsun blog

無味の味は佳境に入らざればすなわち知れず

MySQLのロックに関する調査メモ その4

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     ;;

8000000480000002になりました。

次のロック情報を見てみましょう。

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     ;;

800000028000000480000000はレコードの値を表していそうです。 00000000162aaa0000011e011dは謎です。プライマリーインデックスと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は変わりません。 aa0000011e011daa0000011e0110になりました。 うーん、これはちょっとよくわかりません。

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つ目のギャップロックで実現していることを表現しているのでしょうか?