MySQL当中的Lock

news2025/3/1 19:17:48

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只是这里输出显示有问题,内部还是严格控制锁的范围。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2308043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

electron-builder打包时github包下载失败【解决办法】

各位朋友们&#xff0c;在使用electron开发时&#xff0c;选择了electron-builder作为编译打包工具时&#xff0c;是否经常遇到无法从github上下载依赖包问题&#xff0c;如下报错&#xff1a; Get "https://github.com/electron/electron/releases/download/v6.1.12/ele…

【免费】YOLO[笑容]目标检测全过程(yolo环境配置+labelimg数据集标注+目标检测训练测试)

一、yolo环境配置 这篇帖子是我试过的&#xff0c;非常全&#xff0c;很详细【cudaanacondapytorchyolo(ultralytics)】 yolo环境配置 二、labelimg数据集标注 可以参考下面的帖子&#xff0c;不过可能会出现闪退的问题&#xff0c;安装我的流程来吧 2.1 labelimg安装 label…

服务器IPMI用户名、密码批量检查

背景 大规模服务器部署的时候&#xff0c;少不了较多的网管和监测平台&#xff0c;这些平台会去监控服务器的性能、硬件等指标参数&#xff0c;为了便于管理和控制&#xff0c;则需要给服务器IPMI带外管理添加较多的用户&#xff0c;这就需要对较多的服务器检查所对应的IPMI用…

小红书湖仓架构的跃迁之路

作者&#xff1a;李鹏霖(丁典)&#xff0c;小红书-研发工程师&#xff0c;StarRocks Contributor & Apache Impala Committer 本文整理自小红书工程师在 StarRocks 年度峰会上的分享&#xff0c;介绍了小红书自助分析平台中&#xff0c;StarRocks 与 Iceberg 结合后&#x…

C++-第十七章:包装器

目录 第一节&#xff1a;std::function 第二节&#xff1a;std::bind 2-1.基本介绍 2-2.调整顺序(不常用) 2-3.调整个数 2-4.std::bind与std::function 下期预告&#xff1a; C中有3种可调用对象&#xff1a;函数指针、仿函数对象、lambda函数&#xff0c;经过包装器包装后屏…

TCP的三次握手与四次挥手:建立与终止连接的关键步骤

引言 ‌TCP&#xff08;传输控制协议&#xff09;工作在OSI模型的传输层‌。OSI模型将计算机网络功能划分为七个层级&#xff0c;从底层到顶层依次是&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。传输层负责在网络节点之间提供可靠的端到端通信&a…

2025计算机考研复试资料(附:网课+历年复试真题+140所高校真题+机试)

目录 2025 计算机考研复试经验全攻略&#xff0c;附超全资源&#x1f381; &#xff08;一&#xff09;网课资源 &#xff08;二&#xff09;历年复试真题 &#xff08;三&#xff09;140 所高校真题 二、专业知识复习篇 &#xff08;一&#xff09;复试专业课程 二&…

Milvus高性能向量数据库与大模型结合

Milvus | 高性能向量数据库&#xff0c;为规模而构建Milvus 是一个为 GenAI 应用构建的开源向量数据库。使用 pip 安装&#xff0c;执行高速搜索&#xff0c;并扩展到数十亿个向量。https://milvus.io/zh Milvus 是什么&#xff1f; Milvus 是一种高性能、高扩展性的向量数据…

腾讯游戏完成架构调整 IEG新设五大产品事业部

易采游戏网2月28日独家消息&#xff1a;继1月份腾讯天美工作室群完成内部组织架构调整后&#xff0c;腾讯旗下互动娱乐事业群&#xff08;IEG&#xff09;再次宣布对组织架构进行优化调整。此次调整的核心在于新设立了五大产品事业部&#xff0c;包括体育产品部、音舞产品部、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系列产品…

java jar包内的jar包如何打补丁

问题描述&#xff1a; 主包&#xff1a;hisca.jar&#xff0c;解压后 BOOT-INFO/lib下有其他jar包 因为一个小bug&#xff0c;需要修改这个hisca包下BOOT-INF/lib下的子jar包service-hisca-impl-1.0.0.jar中的一个service类及xml文件 操作步骤&#xff1a; 1、主包jar -xvf …

【企业场景】上线的项目如何进行限流

一、常见的四种速率限流算法 对于限流&#xff0c;最为直接的就是速率限流了 固定窗口算法 比如 10r/s 就是把时间线分为 1s 一段&#xff0c;也就是周期为 1s&#xff0c;对一个时间段的请求进行计数&#xff0c;超过 10 则舍弃&#xff0c;未超过则直接处理经过 1s 后&…

git - study

文章目录 git - study概述可以用 git gui工具来添加快捷命令工具如果要在提交日志中搜索&#xff0c;可以用gitk的view编辑功能实验环境直接用git自带环境进行git操作的好处查看git所有配置配置全局数据配置项目专用的数据查询配置数据的原始值配置git使用的文本编辑器获取某个…

FPGA之硬件设计笔记-持续更新中

目录 1、说在前面2、FPGA硬件设计总计说明3、 原理图详解 - ARITX - 7 系列3.1 顶层框图介绍3.2 FPGA 电源sheet介绍&#xff1a;3.2.1 bank 14 和 bank 15的供电3.2.2 bank 0的供电3.2.3 Bank34 35 的供电 3.3 核电压和RAM电压以及辅助电压 4 原理图详解-- Ultrascale ARTIX4.…

嵌入式开发:傅里叶变换(5):STM32和Matlab联调验证FFT

目录 1. MATLAB获取 STM32 的原始数据 2. 将数据上传到电脑 3. MATLAB 接收数据并验证 STM32进行傅里叶代码 结果分析 STM32 和 MATLAB 联调是嵌入式开发中常见的工作流程&#xff0c;通常目的是将 STM32 采集的数据或控制信号传输到 MATLAB 中进行实时处理、分析和可视化…

Cursor AI编程-详细教程

一点准备工作 Cursor方法论&#xff1a;简单到没有方法 Cursor能做什么 Cursor官网&#xff1a;https://www.cursor.com/ja Cursor文档&#xff1a;Cursor – Welcome to Cursor Cursor论坛&#xff1a;Weekly - Cursor - Community Forum 写程序代码 举例&#xff1a; 设…

(十 三)趣学设计模式 之 模版方法模式!

目录 一、 啥是模板方法模式&#xff1f;二、 为什么要用模板方法模式&#xff1f;三、 模板方法模式的实现方式四、 模板方法模式的优缺点五、 模板方法模式的应用场景六、 总结 &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&a…

泛型编程、函数模板、类模板

目录 一、泛型编程 1.泛型编程提出背景 1.1.代码复用案例解析 案例1&#xff1a;实现一个交换函数&#xff0c;并对不同类型参数进行函数重载 (1)调试 (2)代码解析 ①代码复用问题 ②泛型编程的解决方案 ③上面泛型Swap函数模版的优点 1.2.泛型编程提出背景 2.泛型编…

【Vue3】浅谈setup语法糖

Vue3 的 setup 语法糖是通过 <script setup> 标签启用的特性&#xff0c;它是对 Composition API 的进一步封装&#xff0c;旨在简化组件的声明式写法&#xff0c;同时保留 Composition API 的逻辑组织能力。以下是其核心概念和原理分析&#xff1a; 一、<script setu…

简洁的个人地址发布页HTML源码

源码介绍 简洁的个人地址发布页HTML源码,源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果 效果预览 源码获取 简洁的个人地址发布页HTML源码