【强烈建议收藏:MySQL面试必问系列之并发事务锁专题】
一.知识回顾
上节课我们一起学习了MySQL面试必问系列之事务,没有学习的同学可以看一下上一篇文章,肯定对你会有帮助,学习过的同学肯定知道,上节课我们留了一个小尾巴,这个小尾巴是什么呢?就是没有详细展开学习的MySQL事务并发锁的专题相关内容。那么这篇文章我们就一起来学习关于这方面的的内容,把我们整个知识框架搭建起来,话不多说,盘它。
二.什么是锁?锁的基本概念你知道吗?
2.1 锁的背景
再讲锁基本概念之前,我们先看这样一个例子,目的就是为了更好的理解锁的基本概念。
电商想必大家都知道,那么双十一肯定也是非常清楚的,活动当天的人流量是千万、亿级别的,但是商家的库存是有限的,不可能保证我们所有需要的用户都能抢到。所以,系统为了保证商家的商品库存不发生超卖现象,会对商品的库存进行锁控制。每次进行秒杀的时候都会锁住我们的库存,进行减库存的操作,当有用户正在下单某款商品最后一件时,系统会立马对该件商品进行锁定,防止其他用户也重复下单,直到支付动作完成才会释放,如果支付成功则立即减库存售罄,但是如果用户放弃支付,那么支付失败,我们会放出该库存,留给其他用户进行抢购。
上述过程是所有电商以及一些高并发场景以及系统开发过程中必须解决的一个问题,解决这个问题的关键就在于锁
。
2.2 锁的基本概念
在大致了解了锁的由来之后,接下来我们来了解一写关于锁的基本概念。
- 锁是计算机用以协调多个进程间并发访问同一共享资源的一种机制。MySQL中为了保证数据访问的一致性与有效性等功能,实现了锁机制,MySQL中的锁是在服务器层或者存储引擎层实现的。
- 在数据库中,除传统计算资源(CPU、RAM、I\O等)的争抢,数据也是一种供多用户共享的资源。如何保证数据并发访问的一致性,有效性,是所有数据库必须要解决的问题。锁冲突也是影响数据库并发访问性能的一个重要因素,因此锁对数据库尤其重要。
- 加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否已解除、释放锁等 ,都会增加系统的开销。
三.MySQL中锁的类型
3.1 行锁
3.1.1 行锁的基本概念
行锁MySQL的官方文档给出的定义
英文版
- A record lock is a lock on an index record. Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking.
中文版
- 记录锁是索引记录上的锁。记录锁始终锁定索引记录,即使表的定义没有索引也是如此。对于这种情况,InnoDB 会创建一个隐藏的聚集索引,并使用此索引进行记录锁定。
从官方文档我们可以看出,行锁是作用在索引上的,即使我们在建表的时候没有定义一个索引,InnoDB也会创建一个聚簇索引并将其作为锁作用的索引。这个地方就必须在补充一下关于聚簇索引相关的知识。
拓展:
聚簇索引:
1.每一个InnoDB表都需要一个聚簇索引,有且只有一个。
2.如果我们在定义表的时候定义了主键,那么MySQL将使用主键作为聚簇索引;如果没有定义主键,那么MySQL将会把第一个唯一索引(而且要求NOT NULL)作为聚簇索引;如果上诉两种情况都没有满足,那么MySQL将自动创建一个名字为GEN_CLUST_INDEX的隐藏聚簇索引。
因为是聚簇索引,所以B+树上的叶子节点都存储了数据行,那么如果现在是二级索引呢?InnoDB中的二级索引的叶节点存储的是主键值(或者说聚簇索引的值),所以通过二级索引查询数据时,还需要将对应的主键去聚簇索引中再次进行查询。
3.1.2 行锁的种类
-
读锁(read lock),也叫共享锁(shared lock):加了锁的记录,所有事务都能去读取但不能修改,同时阻止其他事务获得相同数据集的排他锁;
-
写锁(write lock),也叫排他锁(exclusive lock):允许已经获得排他锁的事务去更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁;
-
意向锁(InnoDB表锁)
知识补充:
问题1:什么是意向锁呢?
意向锁也是表级锁,分为读意向锁(IS锁)和写意向锁(IX锁)。当事务要在记录上加上行锁时,要首先在表上加上意向锁。这样判断表中是否有记录正在加锁就很简单了,只要看下表上是否有意向锁就行了,从而就能提高效率。
问题2:为什么要引入意向锁呢?
由于表锁和行锁虽然锁定范围不同,但是会相互冲突。当你要加表锁时,势必要先遍历该表的所有记录,判断是否有排他锁。这种遍历检查的方式显然是一种低效的方式,MySQL引入了意向锁,来检测表锁和行锁的冲突。
问题3:意向锁的分类
意向共享锁(IS):一个事务给一个数据行加共享锁时,必须先获得表的IS锁;
意向排它锁(IX):一个事务给一个数据行加排他锁时,必须先获得该表的IX锁。
问题4:意向锁之间存在并发安全的问题吗?
意向锁之间是不会产生冲突的,它只会阻塞表级读锁或写锁。意向锁不于行级锁发生冲突。
3.1.3 行锁如何上锁
- 意向锁是 InnoDB 自动加的,不需要用户干预;
- 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及的数据集加上排他锁;
- 对于普通的SELECT语句,InnoDB不会加任何锁;
- 事务可以通过以下语句显示给记录集添加共享锁或排他锁:
共享锁(S):此时其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。但是如果当前事务需要对该记录进行更新操作,则很有可能造成死锁。
select * from table_name where ... lock in share mode# 1. 相关说明:in share mode 子句的作用就是将查找的数据加上一个share锁,这个就是表示其他的事务只能对这些数据进行简单的 select 操作,而不能进行 DML 操作。
# 2. 使用场景:为了确保自己查询的数据不会被其他事务正在修改,也就是确保自己查询到的数据是最新的数据,并且不允许其他事务来修改数据。与select for update不同的是,本事务在查找完之后不一定能去更新数据,因为有可能其他事务也对同数据集使用了 in share mode 的方式加上了S锁;
# 3. 性能分析:select lock in share mode 语句是一个给查找的数据上一个共享锁(S 锁)的功能,它允许其他的事务也对该数据上S锁,但是不能够允许对该数据进行修改。如果不及时的commit 或者rollback 也可能会造成大量的事务等待。
排他锁(X):其他session可以查询记录,但是不能对该记录加共享锁或排他锁,只能等待锁释放后在加锁。
select * from table_name where ... for update# 1. 相关说明:在执行这个 select 查询语句的时候,会将对应的索引访问条目加上排他锁(X锁),也就是说这个语句对应的锁就相当于update带来的效果;
# 2. 使用场景:为了让确保自己查找到的数据一定是最新数据,并且查找到后的数据值允许自己来修改,此时就需要用到select for update语句;
# 3. 性能分析:select for update语句相当于一个update语句。在业务繁忙的情况下,如果事务没有及时地commit或者rollback可能会造成事务长时间的等待,从而影响数据库的并发使用效率。
行锁如何上锁,看图更直观,如下图所示:
3.1.4 锁模式的兼容矩阵
下面表显示了了各种锁之间的兼容情况:
注意:
- 下面的X与S是说表级的X锁和S锁,意向锁不和行级锁发生冲突;
- 如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;
- 如果两者不兼容,那么该事务就需要等待锁的释放。
X | IX | S | IS | |
---|---|---|---|---|
X | ||||
IX | 兼容 | 兼容 | ||
S | 兼容 | 兼容 | ||
IS | 兼容 | 兼容 | 兼容 |
3.1.5 行锁的类型
3.1.5.1 记录锁(Record Lock)
- 记录锁最简单的一种行锁形式。
- 行锁是加在索引上的,如果当你的查询语句不走索引的话,那么它就会升级到表锁,最终造成效率低下,所以在写SQL语句时需要特别注意。
3.1.5.2 间隙锁(Gap Lock)
- 当我们使用范围条件而不是相等条件去检索,并请求锁时,InnoDB就会给符合条件的记录的索引项加上锁;
- 键值在条件范围内但并不存在的记录,就叫做间隙,InnoDB在此时也会对间隙加锁
- 间隙锁是可以共存的,共享间隙锁与独占间隙锁之间是没有区别的,两者之间并不冲突。其存在的目的都是防止其他事务往间隙中插入新的纪录,故而一个事务所采取的间隙锁是不会去阻止另外一个事务在同一个间隙中加锁的。
- 当然也不是在什么时候都会去加间隙锁的。在 RU 和 RC 两种隔离级别下,即使你使用 select in share mode 或 select for update,也无法防止幻读(读后写的场景)。因为这两种隔离级别下只会有行锁,而不会有间隙锁。而如果是 RR 隔离级别的话,就会在间隙上加上间隙锁。
3.1.5.3 临键锁(Next-key Lock)
- 临键锁是记录锁与与间隙锁的结合,所以临键锁与间隙锁是一个同时存在的概念,并且临键锁是个左开有闭的区间。
- MySQL 默认隔离级别是RR,在这种级别下,如果你使用 select in share mode 或者 select for update 语句,那么InnoDB会使用临键锁(记录锁 + 间隙锁),因而可以防止幻读;
3.1.5.4 插入意向锁(Insert Intention Lock)
- 插入意向锁不影响其他事务加其他任何锁。也就是说,一个事务已经获取了插入意向锁,对其他事务是没有任何影响的;
- 插入意向锁与间隙锁和 Next-key 锁冲突。也就是说,一个事务想要获取插入意向锁,如果有其他事务已经加了间隙锁或 Next-key 锁,则会阻塞。
- 插入意图锁是一种间隙锁,在行执行 INSERT 之前的插入操作设置。如果多个事务 INSERT 到同一个索引间隙之间,但没有在同一位置上插入,则不会产生任何的冲突。假设有值为4和7的索引记录,现在有两事务分别尝试插入值为 5 和 6 的记录,在获得插入行的排他锁之前,都使用插入意向锁锁住 4 和 7 之间的间隙,但两者之间并不会相互阻塞,因为这两行并不冲突。
- 插入意向锁只会和 间隙或者 Next-key 锁冲突,正如上面所说,间隙锁作用就是防止其他事务插入记录造成幻读,正是由于在执行 INSERT 语句时需要加插入意向锁,而插入意向锁和间隙锁冲突,从而阻止了插入操作的执行。
3.1.6 不同类型锁之间的兼容
RECORED | GAP | NEXT-KEY | II GAP(插入意向锁) | |
---|---|---|---|---|
RECORED | 兼容 | 兼容 | ||
GAP | 兼容 | 兼容 | 兼容 | 兼容 |
NEXT-KEY | 兼容 | 兼容 | ||
II GAP | 兼容 | 兼容 |
3.1.7 行锁默认存储引擎
行锁默认的存储引擎InnoDB,但是也支持表锁。
3.1.8 行锁加锁的特点
- 对数据库表中一行数据进行加锁
- 开销大
- 加锁效率慢
- 会出现死锁
- 锁粒度小,发生锁冲突概率最低,并发性高
3.1.8 行锁事务并发带来的问题
- 更新丢失
解决:让事务变成串行操作,而不是并发的操作,即对每个事务开始—对读取记录加排他锁 - 脏读
解决:发生在隔离级别为Read uncommitted,设置为其它隔离级别 - 不可重读
解决:使用Next-Key Lock算法来避免 - 幻读
解决:间隙锁(Gap Lock)
3.2 表锁
3.2.1 表锁的基本概念
表锁,顾名思义,就是直接给我们数据库的表加锁,在会话开始的地方使用 lock 命令将后续需要用到的表都加上锁,在表释放前,只能访问这些加锁的表,不能访问其他表,直到最后通过 unlock tables 释放所有表锁。
除了使用 unlock tables 显示释放锁之外,会话持有其他表锁时执行lock table 语句会释放会话之前持有的锁;会话持有其他表锁时执行 start transaction 或者 begin 开启事务时,也会释放之前持有的锁。
3.2.2 表锁种类
- 读锁(read lock),也叫共享锁(shared lock)针对同一份数据,多个读操作可以同时进行而不会互相影响(select)
- 写锁(write lock),也叫排他锁(exclusive lock)当前操作没完成之前,会阻塞其它读和写操作(update、insert、delete)
3.2.3 表锁如何上锁
表锁如何上锁,看图更直观,如下图所示:
3.2.4 表锁默认存储引擎
表锁默认的存储引擎MyISAM
3.2.5 表锁加锁的特点
- 对整张表加锁
- 开销小
- 加锁快
- 无死锁
- 锁粒度大,发生锁冲突概率大,并发性低
3.2.6 结论
- 读锁会阻塞写操作,不会阻塞读操作
- 写锁会阻塞读和写操作
- MyISAM的读写锁调度是写优先,这也是MyISAM不适合做写为主表的引擎,因为写锁以后,其它线程不能做任何操作,大量的更新使查询很难得到锁,从而造成永远阻塞。
四.什么是快照读和当前读?
4.1 快照读
快照读就是读取的是快照数据,读取的是历史数据,不加锁的简单Select 都属于快照读。
SELECT * FROM user WHERE ...
4.2 当前读
当前读就是读的是最新数据,而不是历史的数据。加锁的 SELECT,或者对数据进行增删改都会进行当前读。
SELECT * FROM user LOCK IN SHARE MODE;
SELECT FROM user FOR UPDATE;
INSERT INTO user values ...
DELETE FROM user WHERE ...
UPDATE user SET ...
五.MySQL如何解决幻读和不可重复度?
MySQL如何解决幻读和不可重复读?
深入学习MySQL事务:ACID特性的实现原理
六.行锁和表锁排查锁问题
参考图片的地址放到了最下面,感兴趣的同学可以看看该内容
七.死锁
参考图片的地址放到了最下面,感兴趣的同学可以看看该内容
总结
MySQL系列的文章也是面试官最喜欢问的一个点,所以大家一定要好好准备,是你拿下理想offer、理想薪资必备的点。
特别感谢
参考文章地址
一张图彻底搞懂 MySQL 的锁机制
【MySQL】MySQL中的锁机制
相关文章:

【强烈建议收藏:MySQL面试必问系列之并发事务锁专题】
一.知识回顾 上节课我们一起学习了MySQL面试必问系列之事务,没有学习的同学可以看一下上一篇文章,肯定对你会有帮助,学习过的同学肯定知道,上节课我们留了一个小尾巴,这个小尾巴是什么呢?就是没有详细展开…...

Linux下使用Makefile实现条件编译
在Linux系统下Makefile和C/C语言都有提供条件选择编译的语法,就是在编译源码的时候,可以选择性地编译指定的代码。这种条件选择编译的使用场合有好多,例如我们开发一个兼容标准版本与定制版本兼容的项目,那么,一些与需…...

java 应用cpu飙升(超过100%)故障排查
前言害。。。昨天刚写完一份关于jvm问题排查相关的博客,今天线上项目就遇到了一个突发问题。现象是用户反映系统非常卡,无法操作。然后登录服务器查看发现cpu 一直100%以上。具体排查步骤:1,首先top命令查看服务器cpu等情况&#…...

光学设计软件Ansys的Lumerical 2023版本下载与安装使用
文章目录前言一、许可管理工具安装二、许可管理器配置三、Lumerical安装四、工具使用配置总结前言 Lumerical是一款功能强大的软件,用于设计和分析从组件到系统阶段的光子学和电磁学。这个版本的Lumerical改进了电子和光子学设计工具,用于复杂光子学&am…...

Java 异常
文章目录1. 异常概述2. JVM 的默认处理方案3. 异常处理之 try...catch4. Throwable 的成员方法5. 编译异常和运行异常的区别6. 异常处理之 throws7. 自定义异常8. throws 和 throw 的区别1. 异常概述 异常就是程序出现了不正常的情况。 ① Error:严重问题ÿ…...

JavaSE学习笔记day17
零、 复习昨日 File: 通过路径代表一个文件或目录 方法: 创建型,查找类,判断类,其他 IO 输入& 输出字节&字符 try-catch代码 一、作业 给定路径删除该文件夹 public static void main(String[] args) {deleteDir(new File("E:\\A"));}// 删除文件夹public s…...

【项目】Vue3+TS 动态路由 面包屑 查询重置 列表
💭💭 ✨:【项目】Vue3TS 动态路由 面包屑 查询重置 列表 💟:东非不开森的主页 💜: 热烈的不是青春,而是我们💜💜 🌸: 如有错误或不足之处࿰…...
前脚背完这些接口自动化测试面试题,后脚就进了字节测试岗
1、请结合你熟悉的项目,介绍一下你是怎么做测试的? -首先要自己熟悉项目,熟悉项目的需求、项目组织架构、项目研发接口等 -功能 接口 自动化 性能 是怎么处理的? -第一步: 进行需求分析,需求评审&#…...
termux 安装centos
相关链接 centos官网rootfs制作其他人提供的安装脚本centos镜像列表其他人提供的安装脚本的说明 如果想使用老版本的centos7跟着上面链接5走就行 如果想用新系统比如centos9 stream,就跟我来 Q:为什么要装新系统? A:旧系统太多软件已过时,升级费时费…...

从菜鸟程序员到高级架构师,竟然是因为这个字final
final实现原理 简介 final关键字,实际的含义就一句话,不可改变。什么是不可改变?就是初始化完成之后就不能再做任何的修改,修饰成员变量的时候,成员变量变成一个常数;修饰方法的时候,方法不允…...

【vulhub漏洞复现】CVE-2018-2894 Weblogic任意文件上传漏洞
一、漏洞详情影响版本weblogic 10.3.6.0、weblogic 12.1.3.0、weblogic 12.2.1.2、weblogic 12.2.1.3WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应…...

函数栈帧详解
写在前面 这个模块临近C语言的边界,学起来需要一定的时间,不过当我们知道这些知识后,在C语言函数这块我们看到的不仅仅是表象了,可以真正了解函数是怎么调用的。不过我的能力有限,下面的的知识若是不当,还…...

Spring 事务(编程式事务、声明式事务@Transactional、事务隔离级别、事务传播机制)
文章目录1. 事务的定义2. Spring 中事务的实现2.1 MySQL 中使用事务2.2 Spring 中编程式事务的实现2.3 Spring 中声明式事务2.3.1 声明式事务的实现 Transactional2.3.2 Transactional 作用域2.3.3Transactional 参数设置2.3.4 Transactional 异常情况2.3.5 Transactional 工作…...

车载技术——Window Display之surface的绘制过程与原理
一、Surface 概述 OpenGL ES/Skia定义了一组绘制接口的规范,为什么能够跨平台? 本质上需要与对应平台上的本地窗口建立连接。也就是说OpenGL ES负责输入了绘制的命令,但是需要一个 “画布” 来承载输出结果,最终展示到屏幕。这个…...
2023年全国最新工会考试精选真题及答案10
百分百题库提供工会考试试题、工会考试预测题、工会考试真题、工会证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 51.()是企业工会的权力机关,每年召开一至两次会议。 A.会员大会 B.会…...

pytorch-复现经典深度学习模型-LeNet5
Neural Networks 使用torch.nn包来构建神经网络。nn包依赖autograd包来定义模型并求导。 一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。 一个简单的前馈神经网络,它接受一个输入,然后一层接着一层地传递,…...

【C++】类和对象(上)
文章目录对象的介绍类的介绍类的两种定义方式类的访问限定符及封装访问限定符封装类的作用域类的实例化类的对象模型对象的介绍 C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题; C是基于面向…...

工作中责任链模式用法及其使用场景?
前言 笔者是金融保险行业,有这么一种场景,业务员录完单后提交核保,这时候系统会对保单数据进行校验,如不允许手续费超限校验,客户真实性校验、费率限额校验等等,当校验一多时,维护起来特别麻烦…...

三八女神节有哪些数码好物?2023年三八女神节数码好物清单
2023年的三八女神节就快到了,大家还在烦恼,不知道有哪些数码好物?在此,我来给大家分享几款三八女神节实用性强的数码好物,一起来看看吧。 一、蓝牙耳机:南卡小音舱 参考价:239 推荐理由&…...

FairGuard-Windows加固工具版本更新日志
FairGuard-Windows加固工具1.2.2版本更新日志: ■ 增加Unity Resources资源加密的支持; ■ 增加单独Assetbundle资源加密,并同时支持压缩包和文件夹作为输入的方式; ■ 增加对游戏原文件夹加固的支持; Windows加固方案介绍 FairGuard专为游戏量身定…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...