innodb锁机制探究(三)---插入意向锁
之前的文章中,提到了插入意向锁,今天来说说这种类型的锁。
先来看官方文档中对于这个锁是怎么介绍的。
An insert intention lock is a type of gap lock set by INSERT
operations prior to row insertion. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap. Suppose that there are index records with values of 4 and 7. Separate transactions that attempt to insert values of 5 and 6, respectively, each lock the gap between 4 and 7 with insert intention locks prior to obtaining the exclusive lock on the inserted row, but do not block each other because the rows are nonconflicting.
意思是插入意向锁是一种间隙锁,专门针对的是数据行的插入操作,多个事务插入相同的索引间隙时,只要不是插入到相同的位置,则不需要进行锁等待。
假设有索引记录的值分别是4和7,单独的事务分别尝试插入5和6,在获得插入行的排它锁之前,每个事务都是用插入意图锁来锁定4和7之间的空间,但是不会相互阻塞。因为行级别是没有冲突的。
简单理解就是插入意向锁锁定了索引之间的间隙,但是插入意向锁之间没有互相阻塞。
下面我们通过一个例子展示一下上面红色部分的内容,首先创建一张表lock_test4,这种表中id是主键,但是没有自增,所以这里在概念上要和自增锁分开。
mysql :yeyztest 10:28:01>>show create table lock_test4\G
*************************** 1. row ***************************
Table: lock_test4
Create Table: CREATE TABLE `lock_test4` (
`id` int(11) NOT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql :yeyztest 10:28:15>>insert into lock_test4 values (5,5);
Query OK, 1 row affected (0.01 sec)
接着来看看加锁的情况:
这个过程中我们可以看出,会话2中插入4和3的值都没有得到响应,其本质是事务还没有获取当前范围的排它锁,那么按照上面的叙述,应该会用插入意向锁来锁定相关的范围,我们使用show engine innodb status来看锁的情况:
---TRANSACTION 3106058, ACTIVE 30 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 1585, OS thread handle 140406919059200, query id 8170 127.0.0.1 dba_admin update
insert into lock_test4 values (4,4)
------- TRX HAS BEEN WAITING 30 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 558 page no 3 n bits 72 index PRIMARY of table `yeyztest`.`lock_test4`
trx id 3106058 lock_mode X locks gap before rec insert intention waiting
------------------
---TRANSACTION 3106057, ACTIVE 96 sec
2 lock struct(s), heap size 1136, 2 row lock(s)
从信息中我们可以看到,为了获取间隙锁,该事务已经等待了30s,并在区间内设定了插入意向锁。
上面的例子只是展示了插入意向锁的存在,现在我们来看插入意向锁之间,关于不同的记录,他们没有相互影响,首先看表中的记录:
mysql :yeyztest 12:00:29>>select * from lock_test4;
+----+------+
| id | age |
+----+------+
| 5 | 5 |
| 9 | 9 |
+----+------+
2 rows in set (0.00 sec)
再来看整个测试过程。
可以看到,虽然事务隔离级别是RR,虽然是同一个索引,虽然是同一个区间,但插入的记录并不冲突,会话1中的insert提交之前,并没有影响会话2中的insert操作提交。
相关文章: