MySQL当中的Lock
1. 总览锁的类型
锁的类型:
| 锁类型 | 符号/缩写 | 描述 |
| 全局锁 | FTWRL | 锁定整个数据库(FLUSH TABLES WITH READ LOCK),用于全库备份。 |
| 表级锁 | ||
| - 表锁 | S/X | LOCK TABLES ... READ(共享锁)或 WRITE(排他锁)。 |
| - 元数据锁 | MDL | 隐式锁,保护表结构(如 ALTER TABLE 时自动加锁)。 |
| - 意向锁 | IS/IX | IS(意向共享锁)、IX(意向排他锁),协调表级与行级锁。 |
| 行级锁 | ||
| - 记录锁 | X,REC_NOT_GAP | 仅锁定单条记录(如主键精确查询)。 |
| - 间隙锁 | X,GAP | 锁定记录间的间隙(如 WHERE id > 10)。 |
| - 临键锁 | X(无后缀) | 锁定记录+间隙(左开右闭区间,如 (5,10])。 |
//对读取的记录加共享锁(S型锁)
select ... lock in share mode;//对读取的记录加独占锁(X型锁)
select ... for update;
1.1.1. 锁兼容性矩阵
| 当前锁 \ 请求锁 | IS | IX | S | X |
| IS(意向读) | ✅ | ✅ | ✅ | ❌ |
| IX(意向写) | ✅ | ✅ | ❌ | ❌ |
| S(读锁) | ✅ | ❌ | ✅ | ❌ |
| X(写锁) | ❌ | ❌ | ❌ | ❌ |
- 规则:意向锁(IS/IX)之间兼容,但与行级锁(S/X)存在互斥。
2. 全局锁
全局锁就是对整个数据库实例加锁。MySQL提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
全局锁的典型使用场景是,做全库逻辑备份。
3. 表锁
表锁的语法是 lock tables … read/write。与FTWRL类似,可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
- MDL(元数据锁)
另一类表级的锁是MDL(metadata lock)。MDL不需要显式使用,在访问一个表的时候会被自动加上。MDL的作用是,保证读写的正确性。你可以想象一下,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个表结构做变更,删了一列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。
- IS/IX(意向锁)
还有就是意向锁。
- 在使用 InnoDB 引擎的表里对某些记录加上共享锁之前,需要先在表级别加上一个意向共享锁【IS】;
- 在使用 InnoDB 引擎的表里对某些纪录加上独占锁之前,需要先在表级别加上一个意向独占锁【IX】;
也就是,当执行插入、更新、删除操作,需要先对表加上意向独占锁,然后对该记录加独占锁。
意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)发生冲突。
4. 行级锁
通过下面这条语句可以查看当前mysql所有的锁
SELECT * FROM performance_schema.data_locks;
表中数据

4.1. 记录锁(X,REC_NOT_GAP)
当你的执行语句在唯一索引时,仅仅只会锁住当前记录.(一定是唯一索引,主键当然也是).因为能确定唯一一条记录所以只需要锁住一条。控制锁的最小粒度来提高性能。
例如查询时:
select * from user where uid = 3 for update;
更新时
update user set username = 'zhangsan' where uid = 3;
插入时
insert into user(uid,username,password) values(3,'zhangsan','123456');
删除同样的,这样都是仅仅会锁住当前记录.这只会锁住uid=3这一行

当然上述情况是当你锁住的值是存在的时候,如果不存在的时候。
4.2. 间隙锁
如果使用未加索引的列查询,例如
select * from user where username = 'zhangsan' for update;
将会锁住所有列,任何DML操作均被阻塞(性能极差). 不过这里区分细一点

当数据存在的时候,例如uid= 1,2,3等实际存在的数据,update与delete都会阻塞。
当数据不存在的时候,对于任何插入操作来说,他都会阻塞。但是对于delete与update来操作一条不存在的记录时,不会阻塞,因为没有影响到任意一条数据。执行情况为(没有任何记录影响)

原因:无索引时走全表扫描,所有数据间隙均被锁定.很容易理解,你找这个记录没有索引那就得找完一张表的记录才确认。所以就得锁完整张表的记录。一定要记住的是,行级锁存在于索引处,没有索引就是所有。
如果是锁住有索引的列,例如(表中9到12之间是没有数据的)
select * from user where uid > 9 and uid < 12 for update;
此时将会加上X,GAP锁,这个锁的范围是在(9,12),不包括9与12.

如果是以下sql
select * from user where uid > 9 and uid <= 12 for update;

加上的是X(临键锁)。此时你应该对临键锁与间隙锁之间的差别有点感觉啦。
4.2.1. 普通索引的等值匹配
还有一种特殊情况,这个索引是普通索引而不是唯一索引。此时执行以下sql
select * from user where username = 'test15' for update;

他锁住了这行记录的主键id,因为主键id是唯一的,来标记这行记录已经锁住(其实就是加了记录锁)。但是普通索引并不是唯一的,所以还有可能存在其他的记录,还得锁住与其他记录的间隙。
这里其实还是有点不容易理解的,为什么等值匹配还有间隙锁?
注意:普通索引他并不是唯一索引,所以这个值是可以重复的。如果你仅仅使用REC_NOT_GAP(记录锁),锁住的只是对应的一条记录,例如你想锁住username = test15的记录。
采用记录锁:
- 其他事务还是可以插入username = test15的值,因为你是记录锁,你锁住仅仅只是当你查询那一刻表中存在的test15的行数据。
- 那么此时就会出现幻读问题,因为此时此刻你在当前事务查到的test15只有两条数据,但是由于另一个事务的insert,那么test15便有了三条数据。产生了幻读现象。
所以我们得采用间隙锁,来避免其他的事务插入相同的索引值。
验证记录锁:另一个事务修改uid=15的数据,阻塞。

验证间隙锁:
username = test12 左区间临界值。阻塞

username = test13 中间不存在的值。阻塞

username = test15 右区间临界值。阻塞

而对于普通索引或者唯一索引的范围锁定基本都是一致的。例如
select * from user where uid > 17 for update;
将会锁住uid [主键/唯一索引](15,20), [20,+∞)这个间隙。
select * from user where username > 'test17' for update;
将会锁住username [普通索引](test15,test20), [test20,+∞)这个间隙。
4.3. 临键锁
如果查询语句为
select * from user where uid > 15 for update;
如果uid在15之后没有数据,那么将会呈现

这里出现了supremum pseudo-record。这是什么意思呢?
supremum pseudo-record: 代表表示当前事务对索引中 最大值之后的所有间隙施加了锁,当前uid最大为15,那么他将会在(15,+∞)这个区间加上间隙锁。你可以理解为他就是+∞
再举一个例子
select * from user where uid > 9 for update;
此时锁的记录为

每一个为临键值的数据,他的范围都是自身到自身左边第一个比他小的范围。与间隙锁唯一不同的是他会包括自身。例如此时的情况,uid=15这条记录会向前找14,那么他锁住的就是(14,15]这个间隙。其实这种多个间隙的情况,我们要找到间隙的左区间最小值,首先就是找到lock data最小值,这里就是12.然后顺着12再找到比他小的第一个值,也就是9.
所以锁住的范围为(9,12] , [12,15] , (15,+∞)。
4.4. 三者的区别
记录锁只会锁住具有唯一索引的行数据,所以记录锁只存在于唯一索引或者主键。
而对于间隙锁与临键锁两者只不过是右区间的临界值的开闭关系罢了
5. 彩蛋
5.1. 锁资源的处理
在我去尝试上锁和DML的尝试之后,发现啦MySQL的一些特点。
例如:当一条记录被上锁后,另一个事务来修改的时候会阻塞等待。会经历一段时间后超时而取消执行,同样我们使用ctrl+c也能终止掉这个操作,但是,此时我去查看锁的状态时,发现事务修改时他持有的锁并没有释放,也就是说在一个大事务操作里面,一个小事务中可能由于一些原因失效了,没有执行,但是他持有的锁的资源并没有被释放,只有当commit与rollback的时候才会去释放锁资源。
5.2. 一点问题
当对于普通索引执行以下语句
select * from user where username > 'test15'
and username < 'test20' for update;
锁的情况为

这里显示的是X临键锁,依照我们的经验锁的范围应该是(test15,test20],此时应该是不可以修改添加test20的值。但是是可以的,理论也是应该可以的,因为我们并没有去锁住test20这条记录,是严格小于符号。
而我执行小于等于时
select * from user where username > 'test15'
and username <= 'test20' for update;

此时依旧时X间隙锁,这是没问题的。是不可以修改添加test20以及test20之后的值的(普通索引等值匹配规则)。
所以猜测MySQL只是这里输出显示有问题,内部还是严格控制锁的范围。
相关文章:
MySQL当中的Lock
1. 总览锁的类型 锁的类型: 锁类型 符号/缩写 描述 全局锁 FTWRL 锁定整个数据库(FLUSH TABLES WITH READ LOCK),用于全库备份。 表级锁 - 表锁 S/X LOCK TABLES ... READ(共享锁)或 WRITE&#…...
electron-builder打包时github包下载失败【解决办法】
各位朋友们,在使用electron开发时,选择了electron-builder作为编译打包工具时,是否经常遇到无法从github上下载依赖包问题,如下报错: Get "https://github.com/electron/electron/releases/download/v6.1.12/ele…...
【免费】YOLO[笑容]目标检测全过程(yolo环境配置+labelimg数据集标注+目标检测训练测试)
一、yolo环境配置 这篇帖子是我试过的,非常全,很详细【cudaanacondapytorchyolo(ultralytics)】 yolo环境配置 二、labelimg数据集标注 可以参考下面的帖子,不过可能会出现闪退的问题,安装我的流程来吧 2.1 labelimg安装 label…...
服务器禁止操作汇总(Server Prohibits 0peration Summary)
服务器禁止操作汇总 一、禁忌操作TOP10 1. 直接断电关机 💥 血泪案例:某物流公司运维拔电源强制关机,导致数据库事务中断,20万订单状态丢失。 📌 技术解析: • 直接断电可能引发: ✅ 文件系统…...
UE5 Slate类的基础创建
创建一个slate类的基础代码 #pragma onceclass SCustomDetailPlane : public SCompoundWidget {SLATE_BEGIN_ARGS(SCustomDetailPlane){}SLATE_END_ARGS()public:SCustomDetailPlane();~SCustomDetailPlane();void Construct(const FArguments& InArgs);};***************…...
springboot2.7.18升级springboot3.3.0遇到的坑
druid的警告,警告如下: 运行警告2025-02-28T09:20:31.28508:00 WARN 18800 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean com.alibaba.druid.spring.boot3.autoconfigure.stat.DruidSpringAopConfiguration of type [com.a…...
服务器IPMI用户名、密码批量检查
背景 大规模服务器部署的时候,少不了较多的网管和监测平台,这些平台会去监控服务器的性能、硬件等指标参数,为了便于管理和控制,则需要给服务器IPMI带外管理添加较多的用户,这就需要对较多的服务器检查所对应的IPMI用…...
JAVA面试_进阶部分_netty面试题
1.BIO、NIO 和 AIO 的区别? BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。线程开销大。 伪异步 IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源。 NIO&#x…...
小红书湖仓架构的跃迁之路
作者:李鹏霖(丁典),小红书-研发工程师,StarRocks Contributor & Apache Impala Committer 本文整理自小红书工程师在 StarRocks 年度峰会上的分享,介绍了小红书自助分析平台中,StarRocks 与 Iceberg 结合后&#x…...
C++-第十七章:包装器
目录 第一节:std::function 第二节:std::bind 2-1.基本介绍 2-2.调整顺序(不常用) 2-3.调整个数 2-4.std::bind与std::function 下期预告: C中有3种可调用对象:函数指针、仿函数对象、lambda函数,经过包装器包装后屏…...
如何判断邮件列表中邮箱地址的有效性?
判断邮件列表中邮箱地址的有效性,对于提高邮件送达率、避免资源浪费和维护发件人信誉至关重要。以下是一些实用的判断方法: 一、使用专业的邮箱验证工具 市面上有许多专业的邮箱验证工具,如 Geeksend邮箱验证工具 等。这些工具通过与邮件服…...
翻译: 深入分析LLMs like ChatGPT 二
监督微调(SFT) 使用人工标注的对话数据集(如1M条"用户-助手"对话)继续训练模型。 标注员遵循指导原则编写理想回答,使模型学习助手的回应风格。 示例对话格式: [系统] 你是一个有帮助的AI助手……...
conda怎么迁移之前下载的环境包,把python从3.9升级到3.10
克隆旧环境(保留旧环境作为备份) conda create -n cloned_env --clone old_env 在克隆环境中直接升级 Python conda activate cloned_env conda install python3.10 升级 Python 后出现 所有包导入失败 的问题,通常是因为依赖包与新 Pyth…...
k8s之pod的调度之污点与容忍污点,什么是污点? 如何容忍污点
在 Kubernetes 中,污点(Taint) 和 容忍(Toleration) 是用于控制 Pod 调度到特定节点的重要机制。污点允许节点拒绝某些 Pod 的调度,而容忍则允许 Pod 忽略节点的污点,从而调度到特定节点上。 1.…...
Linux切换Python版本
1、更新apt sudo apt update2、查询python安装路径 which python 或者which python33、查询安装版本 # 查看所有以 "python" 开头的命令(包括版本号) ls -l 安装路径* 例如 ls -l /usr/bin/python*4、修改软连接 udo unlink /usr/bin/pyt…...
TCP的三次握手与四次挥手:建立与终止连接的关键步骤
引言 TCP(传输控制协议)工作在OSI模型的传输层。OSI模型将计算机网络功能划分为七个层级,从底层到顶层依次是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。传输层负责在网络节点之间提供可靠的端到端通信&a…...
2025计算机考研复试资料(附:网课+历年复试真题+140所高校真题+机试)
目录 2025 计算机考研复试经验全攻略,附超全资源🎁 (一)网课资源 (二)历年复试真题 (三)140 所高校真题 二、专业知识复习篇 (一)复试专业课程 二&…...
Milvus高性能向量数据库与大模型结合
Milvus | 高性能向量数据库,为规模而构建Milvus 是一个为 GenAI 应用构建的开源向量数据库。使用 pip 安装,执行高速搜索,并扩展到数十亿个向量。https://milvus.io/zh Milvus 是什么? Milvus 是一种高性能、高扩展性的向量数据…...
【Groovy】流程控制
1 选择结构 Groovy 中选择结构主要包含 if -else、switch 语句,并且可以返回结果。 1.1 if-else def score 85 if (score > 90) {println("优秀") } else if (score > 80) {println("良好") } else if (score > 60) {println("…...
腾讯游戏完成架构调整 IEG新设五大产品事业部
易采游戏网2月28日独家消息:继1月份腾讯天美工作室群完成内部组织架构调整后,腾讯旗下互动娱乐事业群(IEG)再次宣布对组织架构进行优化调整。此次调整的核心在于新设立了五大产品事业部,包括体育产品部、音舞产品部、V…...
达梦数据库系列之安装及Mysql数据迁移
达梦数据库系列之安装及Mysql数据迁移 1. 达梦数据库1.1 简介1.2 Docker安装达梦1.2.1 默认密码查询1.2.2 docker启动指定密码 1.3 达梦数据库连接工具1.3.1 快捷键 2 Mysql数据库迁移至达梦2.1 使用SQLark进行数据迁移 1. 达梦数据库 1.1 简介 DM8是达梦公司在总结DM系列产品…...
什么是 MGX:MetaGPT
什么是 MGX:MetaGPT MetaGPT是由思码逸(OpenDILab)团队开发的一款专注于生成式AI驱动的软件开发框架,MGX可能是其衍生或升级的相关成果,它创新性地将大语言模型引入软件开发流程,模拟人类软件团队的协作方式,能让用户通过自然语言描述需求,即可自动生成完整的软件项目,…...
java jar包内的jar包如何打补丁
问题描述: 主包:hisca.jar,解压后 BOOT-INFO/lib下有其他jar包 因为一个小bug,需要修改这个hisca包下BOOT-INF/lib下的子jar包service-hisca-impl-1.0.0.jar中的一个service类及xml文件 操作步骤: 1、主包jar -xvf …...
一个借助ai分析市场交易数据的流程方法
回答和代码借助 AI 生成,仅供参考,不构成任何专业建议。 如有投资损失请自负盈亏。 一个提取比特币的不同周期数据,并进行文本的初步分析的程序。 用途:把文本提供给ai,进行深度思考,从而达到一个相对比较…...
安装electron 提示RequestError: certificate has expired
最近需要开发electron,遇到了一个生产问题,使用了很多办法都不生效。 现在记录下具体情况 一执行 yarn add electron 就开始报错 [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 B…...
Flutter状态管理框架GetX最新版详解与实践指南
一、GetX框架概述 GetX是Flutter生态中轻量级、高性能的全能开发框架,集成了状态管理、路由导航、依赖注入等核心功能,同时提供国际化、主题切换等实用工具。其优势在于代码简洁性(减少模板代码约70%)和高性能(基于观…...
详细对比所有开源许可及其不同版本
qwen 以下是基于知识库内容对常见开源许可证及其不同版本的详细对比,重点突出版本间差异和核心条款变化: 1. GPL(GNU General Public License) 版本: v2 vs v3 GPLv2(1991): 要求衍生代码开源,…...
【企业场景】上线的项目如何进行限流
一、常见的四种速率限流算法 对于限流,最为直接的就是速率限流了 固定窗口算法 比如 10r/s 就是把时间线分为 1s 一段,也就是周期为 1s,对一个时间段的请求进行计数,超过 10 则舍弃,未超过则直接处理经过 1s 后&…...
git - study
文章目录 git - study概述可以用 git gui工具来添加快捷命令工具如果要在提交日志中搜索,可以用gitk的view编辑功能实验环境直接用git自带环境进行git操作的好处查看git所有配置配置全局数据配置项目专用的数据查询配置数据的原始值配置git使用的文本编辑器获取某个…...
编写一个程序,输出1到100的所有质数(Python版)
编写一个程序,输出1到100的所有质数 以下是一个用 Python 编写的程序,用于输出 1 到 100 的所有质数: def is_prime(n):# 检查 n 是否为质数if n < 1: # 如果 n 小于等于 1,则不是质数return False# 遍历从 2 到 n 的平方根的…...
