Innodb加锁机制(Insert Intention Locks)

本文中心思想来源于官方文档
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的插入操作会被阻塞。

你可能感兴趣的:(MySQL,InnoDB-锁)