mysql> select c1 from test01 where c1=1 for update; +----+ | c1 | +----+ | 1 | +----+ 1 row in set (0.00 sec)
会话B mysql> update test01 set c1=6 where c1=1; --hang
c1=1上有record lock,所以会话B无法修改。 mysql> SHOW ENGINE INNODB STATUS/G ------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 24 page no 3 n bits 72 index PRIMARY of table `ming`.`test01` trx id 1807 lock_mode X locks rec but not gap waiting Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 0: len 8; hex 8000000000000001; asc ;; 1: len 6; hex 000000000708; asc ;; 2: len 7; hex a80000011c0110; asc ;; 3: len 4; hex 80000001; asc ;; 4: len 1; hex 61; asc a;;
gap lock: 在gap上加的锁,不包括记录本身。 需要建立一个非唯一性的索引,不能是主键或者唯一性索引,否则只有record lock。 mysql> create index idx_test01_c2 on test01(c2); Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 初始化数据: mysql> select * from test01; +----+------+------+ | c1 | c2 | c3 | +----+------+------+ | 1 | 1 | a | | 3 | 3 | c | | 5 | 5 | e | | 7 | 7 | e | +----+------+------+ 4 rows in set (0.00 sec)
mysql> select c2 from test01 where c2>3 and c2<5 for update; Empty set (0.00 sec)
会话B mysql> insert into test01 select 4,4,'e'; --hang (3,3)与(5,5)之间的gap被锁住了,所以无法插入(4,4)。 ------- TRX HAS BEEN WAITING 32 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 24 page no 4 n bits 72 index idx_test01_c2 of table `ming`.`test01` trx id 1925 lock_mode X locks gap before rec insert intention waiting Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 0: len 4; hex 80000005; asc ;; 1: len 8; hex 8000000000000005; asc ;;
此时c2=3和c2=5两行数据是可以更改的,但是改变后的值不能在现在的gap中。关于数据行的gap具体的可以参考下面的例子:、 next-key lock 对数据记录本身和gap都加锁,相当于record lock + gap lock。