关键字:
mysql事物
mysql锁的算法
LBCC
正文
基于算法划分,mysql有如下三种锁
记录锁 record lock
间隙锁 gap lock
临键锁 next-key lock
准备实验数据
建表如下:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `index_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4
数据如下:
001-表数据
什么是记录锁
对于实验数据中的age列,现有的数据为1,5,9,11,那么针对age列将会有1,5,9,11这4个锁,当筛选条件中的column被精准命中时,也就是说sql中写成where age = x时,这是被操作的记录,将会被锁定。举个例子:
开启2个事物session1,session2
session1:
session1
如上图,执行行1,行3,这时age=5的记录会被锁住,但是age!=5的记录不被锁住。请看下图操作:
image.png
直接执行行3,箭头指向的位置一直在转圈,无法对age=5的记录加排它锁。
image.png
也无法加共享锁
什么是间隙锁
现有的数据为1,5,9,11,那么对于age列,将会有以下几个开区间
(-∞, 1), (1, 5), (5, 9), (9, 11), (11, +∞)。
当where条件里有age的范围查找时,范围区间只落在以上开区间中的一个时。间隙锁将会生效,生效会将会对被落在的开区间内的所有符合的条件进行锁定。看例子:
image.png
执行行1,行3,再去session里操作
image.png
直接执行行4,能看到一直在转圈。因为age > 6 and age < 8落在了(9, 11)这个开区间内,那么(9, 11)这个开区间内的与age列相关的dml语句都会被锁。这里演示的是insert,那么update的?没有update,因为既然有(9, 11)这个开区间,那么就说明(9, 11)的间隙里没有数据。
什么是临键锁
与间隙锁的区别:查询条件落只在间其中一个开区间内,将会进行锁定。临键锁则是,当查询条件跨越了超过一个开区间,比如:where age > 6 and age < 10,这个条件落在了(5, 9), (9, 11)这2个区间内,它让存在的记录锁里的age=9也被包含在了符合的条件里。这是就会有如下临键锁了
(-∞, 1], (1, 5], (5, 9], (9, 11], (11, +∞),可以看到临键锁就是记录锁与间隙锁的并集,是一个左开右必的区间。这是,将会对被落到的区间内的符合条件的记录进行锁定,(5, 9], (9, 11]被锁定,也就是(5, 11]这个区间内的记录被锁定了。下面来操作:
执行行1,行3,可以看到有符合条件的记录。
image.png
再去session2里操作
插入age=7的记录,被锁,转圈。
image.png
插入age=10的记录,被锁,转圈。
image.png
插入记录age=11成功。按理来说,11在锁定区间的最右端,而且是闭区间,那么11应该是被锁定的,可是插入的时候,11是不被锁定的。因为插入时,与已有的age值相等的记录,都不会被锁定。
image.png
修改记录age = 9,转圈。
image.png
修改数据age = 11,转圈。
image.png
修改数据age = 8,不锁,不转圈。
image.png为什么呢?因为age = 8的记录不存在,没法锁。