MySQL教程:插入意向锁介绍。

Insert Intention Lock,中文大家也被称作插入意向锁。

这个算得上是对之前我所说的GapLock的一个补充,

1.为何需要插入意向锁

我们之前已经有GapLock了,GapLock可以帮助我们在某种程度上处理幻读难题,可是,以前的似乎有点难题。

假定我有以下一张表:

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

id是主键自增;age是一个普通索引,如今表中有以下数据:

假定我想执行如下的插入SQL:

begin;
insert into user(username,age) values('wangwu',95);

注意,这个SQL执行了可是事务还没有递交。

依照我们之前学习关于GapLock的知识分析一下,这时间隙锁的范围是(89,99),意思是这个范围的age都不可以插入。

如果是这样的话,朋友们会发现数据插入的效率可就太低了,很容易引发锁矛盾,那么怎么办?

我们今天要介绍的插入意向锁就是用来解决这个问题的。

2.什么叫插入意向锁

插入意向锁是一种在INSERT操作以前设定的一种间隙锁,插入意向锁表示了一种插入意图,即当多个不同的事务,同时往同一个检索的同一个间隙中插入数据的时候,它们互相之间无需等待,即不会阻塞(如果单纯依照以前间隙锁的理论,一定要等一个间隙锁释放了,下一个事务才能够往同样的间隙处插入数据)。假定有值为4和7的检索记录,现在有2个事务,各自试着插入值为5和6记录,在取得插入行的排他锁以前,每个事务使用插入意向锁锁住4和7之间的间隙,可是这俩事务不会彼此阻塞,由于行是不冲突的。

这便是插入意向锁。

3.实践

朋友们注意,松哥之前和大家聊GapLock,说过这个是可重复读(REPEA TABLE READ)这个隔离级别下独有的产物,那么现在Insert Intention Lock是一种特殊的GapLock,当然也是在可重复读这个隔离级别下起效。

接下来我们通过两个个简单的案例来演示一下插入意向锁。

3.1案例一

我们的表结构以及数据与第一小节一致。

首先大家在会话A中,执行如下代码:

如今会话A里的事务没有递交。

接下来我们在会话B中,也执行一个插入操作:

我们发现会话B也能正常执行,没有出现阻塞。

这表明,2个插入意向锁之间是适配的,能够并存的。

3.2案例二

我们再来看一个不兼容的事例。

首先在会话A中执行如下SQL查询age大于80记录,并添加排他锁:

接下来在会话B中,执行如下代码插入一行数据:

朋友们看到,这个操作会被阻塞!阻塞的原因在于,插入意向锁和排他锁之间是互斥的。

借着发生阻塞的这会,在会话C中,我们通过在前文中所使用的show engine innodb status\G命令,来查看下上锁的情况,重点看TRANSACTION节点:

在输出内容中,红色框选中的地方,清楚的表明了插入意向锁的出现。

4.总结

MySQL教程之插入意向锁总结一下:

插入意向锁尽管名字中有意向二字,可事实上是一个特殊的间隙锁。

插入意向锁之间不互斥。

插入意向锁和排他锁之间互斥。