网站首页 > 文章精选 正文
时隔很久,又开始码字了,在最近这段时间将会给大家带来MySQL相关的面试知识点分享,从原理及面试考察点全面剖析、浓缩、提炼面试表达点。
前言
本次分享MySQL间隙锁及RR隔离级别情况下常见的加锁分析,那么废话不多讲直接撸起袖子干。
什么是间隙锁
OK如上图所示,MySQL中的间隙锁(next-key lock)由间隙锁(gap lock)和行锁(row lock)组成。在使用过程中,会把查询范围的整个区间进行锁定,咱们可以先这样理解,后面慢慢剖析。
为什么有间隙锁
在RR隔离级别下,则有可能出现幻读(强调新增,前后两次查询结果不一致)的情况。所以在MySQL中,加入了间隙锁对当前读下的幻读进行解决。
为什么会出现幻读
我们来分析一下此时RC隔离级别+b普通索引的加锁情况:
可以看到RC隔离级别下,b=5的记录加上了X锁,但是(0,5)还有(5,10)的间隙没有锁的情况,所以在这个间隙中可以插入新的数据。
现在我就可以回答出为什么会产生幻读了。产生幻读的原因是,行锁只能锁住行,但是新插入记录的这个动作,要更新的是记录之间的“间隙”。因此,为了解决幻读的问题,InnoDB在RR隔离级别引入了新的锁,它就是间隙锁(Gap Lock)。
RC隔离级别下的加锁情况
下面进行测试表结构创建:
create table `test`(
`id` int(11) NOT NULL,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY(`id`),
UNIQUE KEY unix_key('a'),
KEY ix_key(`b`)
)ENGINE=InnoDB;
insert into test values(0,0,0,0),(5,5,5,5),(10,10,10,10),(20,20,20,20);
创建一张test表,id是主键,a是唯一索引,b是普通索引,c是没有索引。
现在假设是在RC隔离级别下,我们来做一个实验看看:
事务A | 事务B |
set session transaction_isolation='READ-COMMITTED'; | set session transation_isolation='READ-COMMITTED'; |
begin; | |
select * from test where b=5 for update; 返回:(5,5,5,5) | |
begin; | |
insert into test values(6,6,5,5); | |
commit; | |
select * from test where b=5 for update; 返回:(5,5,5,5),(6,6,5,5) | |
commit; |
由上面实验得出,在RC隔离级别下,事务A对b=5这一行记录加了X锁,但是事务B插入一条新的记录的b字段也是为5,然后在事务A中可以查出b=5有两条记录,这个就产生了“幻读”。
也就是说,幻读是指一个事务前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行记录。
RR隔离级别下的加锁情况
加锁分析(以下默认都是RR隔离级别并且都是当前读)
这里我挑选出RR隔离级别下三种常见的情况进行SQL加锁分析:
- RR隔离级别,where字段没有索引
- RR隔离级别,where字段有普通索引
- RR隔离级别,where字段有唯一索引
(1)RR隔离级别+无索引
上图所示,GAP锁加在c字段的(负无穷,0),(0,5),(5,10),(10,20),(20,正无穷)。但是在RR隔离级别下,我们都是默认是用next-key Lock(行锁+间隙锁),所以我们都是默认是左开右闭,同时也得知了所有的记录都加上了X锁及GAP锁(可以理解成表锁)。因此这张表在执行该SQL期间并未commit的话,除了不加锁的快照读事务,其他任何加锁的操作都将堵塞,如果是线上环境,将会是件非常有意思的事。
总结一下:RR隔离级别下,无索引的条件字段的当前读不仅会把每条记录都加上X锁,还会加上GAP锁。
(2)RR隔离级别+唯一索引
唯一索引的情况是最简单的,因为不管是RC隔离级别或者是RR隔离级别,唯一索引都只能查出一条记录,只会在对应的行记录加上X锁就没了。
为什么会这样?
因为GAP锁的目的是为了防止同一事务被连续两次当前读,然后两次读的情况不一致。如果能够保证字段是唯一的(唯一索引),其实就是最多只有一条记录满足条件,所以查询唯一索引的时候绝对不会出现GAP锁。
可以理解为RR+唯一索引和RC+唯一索引的加锁情况是一样的就好了。
(3)RR隔离级别+普通索引
如上图所示,普通索引字段b=10给两条记录加了X锁,并且把聚集索引树的两条记录也加了X锁。GAP锁的是b的范围(5,10),(10,正无穷)。所以next-key Lock锁的是(5,10],(10,10],(10,正无穷]。期间只要是b在next-key Lock的范围内就更新全部阻塞。
举例:insert into test values(6,6,6,6)就会被阻塞,原因就是RR隔离级别的间隙锁锁住了记录之间的“间隙”,所以会阻塞
总结
- 这次分享了RC隔离级别下出现幻读的情况,然后分析了为什么会出现幻读。
- InnoDB为了解决幻读,在RR下引入了GAP锁,和行锁组成next-key Lock
- 分析了三种常见情况的加锁情况操作。
猜你喜欢
- 2025-05-09 面试必问的 MySQL 四种隔离级别,看完吊打面试官
- 2025-05-09 面试官:mysql自增长id用完了怎么办?这是我见过最中肯的答案了
- 2025-05-09 阿里面试:MySQL Binlog有哪些格式?底层原理?优缺点?
- 2025-05-09 1.5万字+30张图盘点程序员面试必会MySQL索引常见的11个知识点
- 2025-05-09 面试中的老大难-mysql事务和锁,一次性讲清楚
- 2025-05-09 手把手指导Linux系统centos7安装数据库MySQL5.7
- 2025-05-09 面试官问我MySQL索引为啥用B+树?我让他去问作者
- 2025-05-09 MySQL面试题:自增ID达到上限了会出现什么问题?
- 2025-05-09 MySQL索引失效问题,看完手撕面试官
- 2025-05-09 阿里面试:MySQL死锁的原因?解决方案有哪些?
- 最近发表
-
- 如何提高PyTorch“炼丹”速度?这位小哥总结了17种方法
- 显存告急?微调资源优化的三大法宝
- 大模型训练成本降低近一半!新加坡国立大学最新优化器已投入使用
- Pytorch 入门-day13: 调试与可视化
- 基于昇腾用PyTorch实现CTR模型DIN(Deep interest Netwok)网络
- 神经网络训练全解析:从理论到实战的开发者指南及超参数优化法则
- BattProDeep——深度学习赋能电池老化概率精准预测
- 让AI自己调整超参数,谷歌大脑新优化器火了,自适应多种不同任务
- 神经辐射场(NeRF)实战指南:基于PyTorch的端到端实现
- Pytorch学习-day8: 损失函数与优化器
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)