mysql InnoDB 行锁,间隙锁,下一键锁是什么?

这里简单先说一下,大家可以边看边理解

  • Record Lock:单个行记录上的锁
  • Gap Lock :锁定一个范围,但不包含记录本身
  • Next-Key Lock ( Gap Lock + Record Lock):锁定一个范围,并且锁定记录本身

说明

  • 实验版本:mysql 5.7.31

  • 事务隔离级别:REPEATABLE-READGap LockNext-Key LockREAD-COMMITEDREAD-UNCOMMITTED两种隔离级别下是不存在的,所以我们将事务隔离级别设置为REPEATABLE-READ

  • 为了更好的说明什么是行锁,间隙锁,下一键锁,我们先创建一张player表,这张表之后将用作分析。

在这里插入图片描述

  • 查看锁将使用show engine innodb status\G命令,为了在结果中看到锁的信息,需要更改两个参数

在这里插入图片描述

  • 注意:InnoDB所有的行锁算法都是基于索引实现的,锁定的也都是索引或者索引区间。
  • 注意:不同的事务隔离级别,不同的索引类型,是否为等值查询,使用的行锁算法也不同。

初步概念 - 简单理解

一.行锁

行锁在官方文档的原文就是Record Locks,总是加在索引上,即使一个表并没有设置任何索引,这种时候 innoDB 会创建一个隐式的聚集索引,然后锁定一个记录。

比如当我们执行

select * from player where player_id=1;

行锁会对索引列锁定,锁住的范围就是player_id∈[1,1]的数据行

二.间隙锁(Gap Locks)

2.1 什么是Gap,Gap指什么?

间隙锁的英文是Gap Locks,要理解间隙锁,首先要好好理解Gap这个单词的意思,百度翻译一下Gap直译出来是个什么意思。

在这里插入图片描述

红框框起来了的内容是间隔和间隙,那么结合到数据库的某张表,我们又该怎么理解Gap的意思呢?

我们一张正常的表如下图所示:

在这里插入图片描述

当我们希望插入一条数据的时候,我们可以插入的范围是哪一些呢?

在这里插入图片描述

2.2 间隙锁的作用

间隙锁主要的目的是防止幻读。

幻读:在一个事务中,执行两次相同的SQL,得到了不同的结果集(新增了部分记录或者缺失了部分记录)

---------------------------------幻读 - 例子-分割线-------------------------------

  • 老板说,小叶,给你一个任务(也就是一个事务),查一下player_id<=3的球员信息,这些球员的信息可能要更改,查完告诉我。

  • 我接到任务,开始查询,查询的结果只能查出科比林书豪,此时我离开工位去吃午饭,此时还没给老板汇报,任务没结束。

  • 在我们吃饭的时候,突然有一位同事增加了一个新的球员信息,比如说id=2,11,姚明,火箭

  • 我吃完午饭回来,只记得有player_id<=3的球员有两位,忘记了其他信息,所以我需要再次查询。

  • 结果查出来有了3位球员,和我们吃午饭前查询出来的结果不一样(也就是幻读)

  • 此时要给老板汇报任务结果了,这时候两次不一致的查询结果可能会导致此次任务工作失败。

---------------------------------幻读 - 例子-分割线-------------------------------

看了上面的例子相信大家对间隙锁的作用,自己也有一定的想法了。如果我从我开始查询球员信息这一刻开始就不允许其他事务插入player_id<=3的新球员的话,那么吃完饭后的查询结果,依然也就只有科比林书豪

2.3 间隙锁再理解

这时候我们再来理解下面这一句sql,他会产生怎样的间隙锁呢?

select * from player where player_id <=3;

对于上方的语句,锁住的索引值也就是:(-∞,1)(1,3)(3,5),也就是说,player_id在上述三个间隙内的新球员信息暂时就不能新增了。

至于为什么要锁(3,5),因为在RR的隔离级别下,需要对比到第一个比3大的值(player_id),也就是5,才会终止。

但真实情况下,实际锁的范围是(-∞,1](1,3](3,5],为什么是这样,也就是接下来我们要说的下一键锁(Next-Key Locks

三.下一键锁(Next-Key Locks)

3.1 什么是下一键锁

当我们理解行锁和间隙锁之后,此时理解下一键锁就很简单了:

Next-Key Locks = Record Locks + Gap Locks,下一键锁就是行锁和间隙锁的组合!

这也是为什么在上方间隙锁的解释中,(-∞,1)(1,3)(3,5) 变成了(-∞,1](1,3](3,5]

select * from player where player_id <=3; -- 这条SQL不仅仅锁住了间隙,也需要锁住id=1,3,5的行
3.2 下一键锁的范围

这个时候我们再来巩固一次下一键锁的范围,就以本文中的player表为例,我们一共有哪些下一键锁的范围?

(-∞,1]
(1,3]
(3,5]
(5,+∞)

例子展示 - 更好的理解

一.行锁演示

执行下方sql

在这里插入图片描述

锁算法查看(通过show innodb status\G 可以查看)

绿框所框起来的:locks rec but not gap就表示此时的X锁模式是行锁

在这里插入图片描述

二.Next-Key Locks演示

执行下方sql,下方的SQL按照上文的介绍,在RR事务隔离级别下应该产生(-∞,1];(1,3];(3,5]三个下一键锁

在这里插入图片描述

锁查看,此时可以发现有3个行锁已经出现了,锁住l了id=1,3,5的记录,下一键锁中的行锁已经验证存在了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tev8TkvM-1600335163000)(C:\Users\YCKJ3681\AppData\Roaming\Typora\typora-user-images\image-20200917145613324.png)]

我们现在试着在间隙范围内插入一条数据,看是不是真的有间隙锁,发现敲击回车后,光标停在左下角,无法立即插入,间隙锁存在!

这里只验证了(1,3)范围,其他间隙锁范围同理可证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0orgSufE-1600335163001)(C:\Users\YCKJ3681\AppData\Roaming\Typora\typora-user-images\image-20200917145846942.png)]

我们现在再来看一下表上的锁信息(截图不全,只截取了新生成的信息)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-liAe6pI6-1600335163002)(C:\Users\YCKJ3681\AppData\Roaming\Typora\typora-user-images\image-20200917150540135.png)]

不同情况的锁定情况

针对不同的索引,是否是等值查询不同的情况,不同的事务隔离级别,锁定的内容可能不同,下面汇总展示:

所有的查询都是针对同一张表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-To3MYQmM-1600335163003)(C:\Users\YCKJ3681\AppData\Roaming\Typora\typora-user-images\image-20200917165840576.png)]

锁定情况展示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t7Khsj5u-1600335163003)(C:\Users\YCKJ3681\AppData\Roaming\Typora\typora-user-images\image-20200917170453266.png)]
这张图借鉴了:
https://www.cnblogs.com/rjzheng/p/9950951.html
这篇博文的最后 好像有两处错误
在这里插入图片描述
欢迎大家指出本博文的错误,互相学习。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值