您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

MySQL精准打击之间隙锁

时间:2022-09-18 13:43:06  来源:今日头条  作者:代码生活圈

时隔很久,又开始码字了,在最近这段时间将会给大家带来MySQL相关的面试知识点分享,从原理面试考察点全面剖析、浓缩、提炼面试表达点。

 

前言

本次分享MySQL间隙锁及RR隔离级别情况下常见的加锁分析,那么废话不多讲直接撸起袖子干。

什么是间隙锁

间隙锁

OK如上图所示,MySQL中的间隙锁(next-key lock)由间隙锁(gap lock)和行锁(row lock)组成在使用过程中,会把查询范围的整个区间进行锁定,咱们可以先这样理解,后面慢慢剖析。

为什么有间隙锁

在RR隔离级别下,则有可能出现幻读(强调新增,前后两次查询结果不一致)的情况。所以在MySQL中,加入了间隙锁对当前读下的幻读进行解决

为什么会出现幻读

我们来分析一下此时RC隔离级别+b普通索引的加锁情况:

RC隔离级别下的幻读

可以看到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隔离级别+无索引

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隔离级别+普通索引

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
  • 分析了三种常见情况的加锁情况操作。


Tags:间隙锁   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MySQL:逃不掉的锁事,间隙锁
我们知道在MySQL中存在幻读的情况,也就是一个事务在读取某个范围内的记录时,发现了另一个事务在该范围内新增了记录(或者删除了记录),导致两次读取的记录数量不一致,进而产生了“...【详细内容】
2023-12-06  Search: 间隙锁  点击:(151)  评论:(0)  加入收藏
select...for update,表锁?行锁?间隙锁?
对于这个问题,我 4 年前就专门研究过,最近看到网上很多相关的文章,要么总结得不全,要么存在很多问题。感觉有必要自己写一篇,一方面对网上的知识进行纠偏,另一方面也想全面总结一...【详细内容】
2023-11-06  Search: 间隙锁  点击:(232)  评论:(0)  加入收藏
MySQL精准打击之间隙锁
时隔很久,又开始码字了,在最近这段时间将会给大家带来MySQL相关的面试知识点分享,从原理及面试考察点全面剖析、浓缩、提炼面试表达点。 前言本次分享MySQL间隙锁及RR隔离级别...【详细内容】
2022-09-18  Search: 间隙锁  点击:(415)  评论:(0)  加入收藏
分享MySQL记录锁、间隙锁、临键锁小案例演示,你学废了吗
生成间隙(gap)锁、临键(next-key)锁的前提条件 是在 RR 隔离级别下。有关Mysql记录锁、间隙(gap)锁、临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文章...【详细内容】
2021-12-14  Search: 间隙锁  点击:(430)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(7)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(11)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(10)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(25)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(9)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(28)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(49)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(53)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(54)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(85)  评论:(0)  加入收藏
站内最新
站内热门
站内头条