本文中心思想来源于官方文档
Insert Intention Locks意为插入意向锁,插入意向锁是Innodb gap锁的一种类型,这种锁表示要以这样一种方式插入:如果多个事务插入到相同的索引间隙中,如果它们不在间隙中的相同位置插入,则无需等待其他事务。比如说有索引记录4和7,有两个事务想要分别插入5,6,在获取插入行上的独占锁之前,每个锁都使用插入意图锁锁定4和7之间的间隙,但是不要互相阻塞,因为行是不冲突的,意向锁的涉及是为了插入的正确和高效。
下面以一个例子来说明插入意向锁。
表结构
CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
初始化数据
INSERT INTO child (id) values (90),(102);
事务1
START TRANSACTION;
SELECT * FROM child WHERE id > 100 FOR UPDATE;
事务2
START TRANSACTION;
INSERT INTO child (id) VALUES (101);
我们知道,在RR隔离级别下,事务2是一定会被阻塞的,但是这种阻塞是如何实现的呢?
通过show engine innodb status
查看锁等待情况
------------
TRANSACTIONS
------------
Trx id counter 323995
Purge done for trx's n:o < 323988 undo n:o < 0 state: running but idle
History list length 98
Total number of lock structs in row lock hash table 2
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 281479664518496, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 281479664515232, not started
0 lock struct(s), heap size 1160, 0 row lock(s)
---TRANSACTION 323994, ACTIVE 8 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1160, 1 row lock(s)
MySQL thread id 4, OS thread handle 123145450004480, query id 175 localhost root update
INSERT INTO child (id) VALUES (101)
------- TRX HAS BEEN WAITING 8 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 167 page no 3 n bits 72 index PRIMARY of table `ashe`.`child` trx id 323994 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000066; asc f;;
1: len 6; hex 00000004f198; asc ;;
2: len 7; hex fb000001ad011c; asc ;;
------------------
---TRANSACTION 323993, ACTIVE 30 sec
2 lock struct(s), heap size 1160, 2 row lock(s)
MySQL thread id 3, OS thread handle 123145449725952, query id 176 localhost root starting
show engine innodb status
--------
其中事务1的加锁情况如下:
heap_no=3的next key lock(x)(90,102]
2018-09-03T15:25:24.619339+08:00 3 [Note] InnoDB: trx_id: 323993 create a record lock and add it to lock hash table,
space_id: 167
page_no: 3
heap_no: 3
n_bits: 72
primary key: 1
is record lock: 1
is waiting: 0
is gap: 0
is record not gap: 0
is insert intention: 0
lock_mode: 3 (0:LOCK_IS, 1:LOCK_IX, 2:LOCK_S, 3:LOCK_X, 4:LOCK_AUTO_INC, 5:LOCK_NONE)
事务2的加锁情况如下:
heap_no=3的gap锁,插入意向类型。(90,102)
2018-09-03T15:25:46.056265+08:00 4 [Note] InnoDB: trx_id: 323994 create a record lock and add it to lock hash table,
space_id: 167
page_no: 3
heap_no: 3
n_bits: 72
primary key: 1
is record lock: 1
is waiting: 1
is gap: 1
is record not gap: 0
is insert intention: 1
lock_mode: 3 (0:LOCK_IS, 1:LOCK_IX, 2:LOCK_S, 3:LOCK_X, 4:LOCK_AUTO_INC, 5:LOCK_NONE)
插入意向锁与gap锁是不兼容的,所以,事务2的插入操作会被阻塞。