大家好,我是小林。
在前一篇文章我讲了下 MySQL 的全局锁、表记锁和行级别锁,其中行级锁只提了概念,并没有具体说。
因为行级锁加锁规则比较复杂,不同的场景,加锁的形式还不同,所以这次就来好好介绍下行级锁。
对记录加锁时,加锁的基本单位是 next-key lock,它是由记录锁和间隙锁组合而成的,next-key lock 是前开后闭区间,而间隙锁是前开后开区间。
但是,next-key lock 在一些场景下会退化成记录锁或间隙锁。
那到底是什么场景呢?今天,我们就以下面这个表来进行实验说明。
其中,id 是主键索引(唯一索引),b 是普通索引(非唯一索引),a 是普通的列。
注意,我的 MySQL 的版本是 8.0.26,不同版本的加锁规则可能是不同的。
当我们用唯一索引进行等值查询的时候,查询的记录存不存在,加锁的规则也会不同:
- 当查询的记录是存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「记录锁」。
- 当查询的记录是不存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「间隙锁」。
接下里用两个案例来说明。
先看看记录是存在的。
来看下面这个例子:
会话1加锁变化过程如下:
- 加锁的基本单位是 next-key lock,因此会话1的加锁范围是(8, 16];
- 但是由于是用唯一索引进行等值查询,且查询的记录存在,所以 next-key lock 退化成记录锁,因此最终加锁的范围是 id = 16 这一行。
所以,会话 2 在修改 id=16 的记录时会被锁住,而会话 3 插入 id=9 的记录可以被正常执行。
接下来,看看记录不存在的情况
来看看,下面这个例子:
会话1加锁变化过程如下:
- 加锁的基本单位是 next-key lock,因此主键索引 id 的加锁范围是(8, 16];
- 但是由于查询记录不存在,next-key lock 退化成间隙锁,因此最终加锁的范围是 (8,16)。
所以,会话 2 要往这个间隙里面插入 id=9 的记录会被锁住,但是会话 3 修改 id =16 是可以正常执行的,因为 id = 16 这条记录并没有加锁。
唯一索引范围查询范围查询和等值查询的加锁规则是不同的。
举个例子,下面这两条查询语句,查询的结果虽然是一样的,但是加锁的范围是不一样的。
select * from t_test where id=8 for update;
select * from t_test where id>=8 and id
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?