10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

QT使用高精度定时器 精度相对第二种方法高许多。 阅读详情

在MySQL数据库中,为了解决并发问题,引入了很多的锁机制,很多时候,数据库的锁是在有数据库操作的过程中自动添加的。

所以,这就导致很多程序员经常会忽略数据库的锁机制的真正的原理。比如,我经常在面试中会问候选人,你知道MySQL Innodb的锁,到底锁的是什么吗?

关于这个问题的回答,我听到过很多种,但是很少有人可以把他回答的很完美。因为想要回答好这个问题,需要对数据库的隔离级别、索引等都有一定的了解才行。

MySQL Innodb的锁的相关介绍,在MySQL的官方文档(https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-insert-intention-locks )中有一定的介绍,本文的介绍也是基于这篇官方文档的。

Record Lock

Record Lock,翻译成记录锁,是加在索引记录上的锁。例如,SELECT c1 FROM t WHERE c1 = 10 For UPDATE;会对c1=10这条记录加锁,为了防止任何其他事务插入、更新或删除c1值为10的行。

10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

需要特别注意的是,记录锁锁定的是索引记录。即使表没有定义索引,InnoDB也会创建一个隐藏的聚集索引,并使用这个索引来锁定记录。

Gap Lock

Gap Lock,翻译成间隙锁,他指的是在索引记录之间的间隙上的锁,或者在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。

那么,这里所谓的Gap(间隙)又怎么理解呢?

Gap指的是InnoDB的索引数据结构中可以插入新值的位置。

当你用语句SELECT…FOR UPDATE锁定一组行时。InnoDB可以创建锁,应用于索引中的实际值以及他们之间的间隙。例如,如果选择所有大于10的值进行更新,间隙锁将阻止另一个事务插入大于10的新值。

10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

既然是锁,那么就可能会影响到数据库的并发性,所以,间隙锁只有在Repeatable Reads这种隔离级别中才会起作用。

在Repeatable Reads这种隔离下,对于锁定的读操作(select … for update 、 lock in share mode)、update操作、delete操作时,会进行如下的加锁:

  • 对于具有唯一搜索条件的唯一索引,InnoDB只锁定找到的索引记录,而不会锁定间隙。
  • 对于其他搜索条件,InnoDB锁定扫描的索引范围,使用gap lock或next-key lock来阻塞其他事务插入范围覆盖的间隙。

也就是说,对于SELECT FOR UPDATE、LOCK IN SHARE MODE、UPDATE和DELETE等语句处理时,除了对唯一索引的唯一搜索外都会获取gap锁或next-key锁,即锁住其扫描的范围。

Next-Key Lock

Next-Key锁是索引记录上的记录锁和索引记录之前间隙上的间隙锁的组合。

10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

假设一个索引包含值10、11、13和20。此索引可能的next-key锁包括以下区间:

(-∞, 10]

(10, 11]

(11, 13]

(13, 20]

(20, ∞ ]

对于最后一个间隙,∞不是一个真正的索引记录,因此,实际上,这个next-key锁只锁定最大索引值之后的间隙。

所以,Next-Key 的锁的范围都是左开右闭的。

Next-Key Lock和Gap Lock一样,只有在InnoDB的RR隔离级别中才会生效。

Repeatable Reads能解决幻读

很多人看过网上的关于数据库事务级别的介绍,会认为MySQL中Repeatable Reads能解决不可重复读的问题,但是不能解决幻读,只有Serializable才能解决。但其实,这种想法是不对的。

因为MySQL跟标准RR不一样,标准的Repeatable Reads确实存在幻读问题,但InnoDB中的Repeatable Reads是通过next-key lock解决了RR的幻读问题的。

因为我们知道,因为有了next-key lock,所以在需要加行锁的时候,会同时在索引的间隙中加锁,这就使得其他事务无法在这些间隙中插入记录,这就解决了幻读的问题。

关于这个问题,引起过广泛的讨论,可以参考:https://github.com/Yhzhtk/note/issues/42 ,这里有很多大神发表过自己的看法。

MySQL的加锁原则

前面介绍过了Record Lock、Gap Lock和Next-Key Lock,但是并没有说明加锁规则。关于加锁规则,我是看了丁奇大佬的《MySQL实战45讲》中的文章之后理解的,他总结的加锁规则里面,包含了两个“原则”、两个“优化”和一个“bug”:

原则 1:加锁的基本单位是 next-key lock。是一个前开后闭区间。原则 2:查找过程中访问到的对象才会加锁。优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

假如,数据库表中当前有以下记录:

10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

当我们执行update t set d=d+1 where id = 7的时候,由于表 t 中没有 id=7 的记录,所以:

  • 根据原则 1,加锁单位是 next-key lock,session A 加锁范围就是 (5,10];
  • 根据优化 2,这是一个等值查询 (id=7),而 id=10 不满足查询条件,next-key lock 退化成间隙锁,因此最终加锁的范围是 (5,10)。

当我们执行select * from t where id>=10 and id<11 for update的时候:

  • 根据原则 1,加锁单位是 next-key lock,会给 (5,10]加上 next-key lock,范围查找就往后继续找,找到 id=15 这一行停下来
  • 根据优化 1,主键 id 上的等值条件,退化成行锁,只加了 id=10 这一行的行锁。
  • 根据原则 2,访问到的都要加锁,因此需要加 next-key lock(10,15]。因此最终加的是行锁 id=10 和 next-key lock(10,15]。

当我们执行select * from t where id>10 and id<=15 for update的时候:* 根据原则 1,加锁单位是 next-key lock,会给 (10,15]加上 next-key lock,并且因为 id 是唯一键,所以循环判断到 id=15 这一行就应该停止了。* 但是,InnoDB 会往前扫描到第一个不满足条件的行为止,也就是 id=20。而且由于这是个范围扫描,因此索引 id 上的 (15,20]这个 next-key lock 也会被锁上。

假如,数据库表中当前有以下记录:

10个人9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

当我们执行select id from t where c=5 lock in share mode的时候:

  • 根据原则 1,加锁单位是 next-key lock,因此会给 (0,5]加上 next-key lock。要注意 c 是普通索引,因此仅访问 c=5 这一条记录是不能马上停下来的,需要向右遍历,查到 c=10 才放弃。
  • 根据原则 2,访问到的都要加锁,因此要给 (5,10]加 next-key lock。
  • 根据优化 2:等值判断,向右遍历,最后一个值不满足 c=5 这个等值条件,因此退化成间隙锁 (5,10)。
  • 根据原则 2 ,只有访问到的对象才会加锁,这个查询使用覆盖索引,并不需要访问主键索引,所以主键索引上没有加任何锁。

当我们执行select * from t where c>=10 and c<11 for update的时候:

  • 根据原则 1,加锁单位是 next-key lock,会给 (5,10]加上 next-key lock,范围查找就往后继续找,找到 id=15 这一行停下来
  • 根据原则 2,访问到的都要加锁,因此需要加 next-key lock(10,15]。
  • 由于索引 c 是非唯一索引,没有优化规则,也就是说不会蜕变为行锁,因此最终 sesion A 加的锁是,索引 c 上的 (5,10] 和 (10,15] 这两个 next-key lock。

总结

以上,我们介绍了InnoDB中的锁机制,一共有三种锁,分别是Record Lock、Gap Lock和Next-Key Lock。

Record Lock表示记录锁,锁的是索引记录。Gap Lock是间隙锁,说的是索引记录之间的间隙。Next-Key Lock是Record Lock和Gap Lock的组合,同时锁索引记录和间隙。他的范围是左开右闭的。

InnoDB的RR级别中,加锁的基本单位是 next-key lock,只要扫描到的数据都会加锁。唯一索引上的范围查询会访问到不满足条件的第一个值为止。

同时,为了提升性能和并发度,也有两个优化点:

  • 索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。

关于锁的介绍,就是这么多了,但是其实,RR的隔离级别引入的这些锁,虽然一定程度上可解决很多如幻读这样的问题,但是也会带来一些副作用,比如并发度降低、容易导致死锁等。

后面我们再来单独介绍一下为什么RR作为InnoDB的默认级别,却"不受待见",很多大厂都会把数据库默认级别修改为RC。

LeRobot — 基于 PyTorch 的真实世界机器人学习框架(一)- 核心框架模块解析 LeRobot 是一个开源的机器人学习框架,由 Hugging Face 开发,旨在降低机器人学的准入门槛。该框架提供完整的机器学习流程支持,包括数据采集、训练、评估和部署。核心模块涵盖数据集标准化、策略算法、硬件抽象和强化学习组件,采用模块化设计实现灵活扩展。通过集成 Hugging Face Hub,用户可以轻松共享数据集和预训练模型。LeRobot 特别注重真实世界的机器人应用,支持多种前沿算法如模仿学习、视觉语言动作模型等,并提供统一的硬件接口和仿真环境适配。 阅读详情

相关推荐

【C++PTA】6-1 Point类的运算 (10 分)

定义Point类,有坐标x,y两个私有成员变量;对Point类重载“+”(相加)、“-”(相减)和“==”(相等)运算符,实现对坐标的改变,要求用友元函数和成员函数两种方法实现。对Point类重载<<运算符,以使得代码 Point p; cout<<p<<endl;可以输出该点对象的坐标。 函数接口定义: 实现Point类。 裁判测试程序样例: /* 请在这里填写答案 */ int main(int argc, char const *argv[]) { P

libertye的博客 2367

什么是数据库锁(Lock)?有哪些类型的锁

数据库锁是一种机制,用于协调多个并发事务对数据库中数据的访问。当多个事务同时尝试对相同的数据进行读取或写入操作时,可能会引发数据一致性问题。数据库锁通过限制并发事务的操作,以确保数据的完整性和一致性。共享锁(Shared Lock):也称为读锁。允许多个事务同时获取共享锁,以进行读取操作。共享锁之间不会互斥,允许并发读取。但是,共享锁与排他锁之间互斥,一个事务持有共享锁时,其他事务无法获得排他锁。排他锁(Exclusive Lock):也称为写锁。排他锁是互斥的,只允许一个事务持有。

stormjun的博客 6737

GitLab教程(四):分支(branch)和合并(merge)

命令进行合并时,Git具备一定的智能自动化处理能力:如果一个分支仅修改了文件A,而另一个分支独立地修改了文件B,Git能够无缝整合这些更改,自动完成合并过程——即最终的代码既包含了对A文件的修改也包含了对B文件的修改。同样地,若两个分支虽然都修改了同一个文件,但涉及的是文件中互不重叠的部分,比如一个改动发生在第一行,另一个则在第二行,Git同样能巧妙地自动合并这些非冲突性修改。获取了远程分支的最新变化,或者当你想要合并本地的一个分支到当前分支时,就会用到这个命令。,默认会尝试合并远程分支到当前分支。

TracyCoder的博客 7885

什么是数据库的锁?怎么实现?

什么是数据库的锁?怎么实现?

weixin_63791423的博客 1430

spring-ai学习(四)-MCP

创建一个springai项目1.依赖。

zql1455890112的博客 1384

区块链入门:用账本、乐高和三台旧电脑讲懂分布式账本

区块链是一种去中心化的分布式账本技术,其核心原理是通过密码学哈希、共识机制和链式结构实现数据不可篡改与多方共同验证。它不依赖单一中心,而是将交易记录同步复制到多个节点,依靠数学规则而非人工信任达成一致,从而在数字世界构建可验证的信用基础设施。这种‘集体见证’模式显著提升了系统抗单点故障与人为干预的能力,广泛应用于供应链溯源、数字身份、教育管理及公益透明等需强信任保障的场景。本文以账本类比、乐高拆解和Ganache实操为线索,面向零基础读者通俗解析哈希值、挖矿与智能合约等关键概念。

weixin_30517215的博客 274

数据库锁介绍

锁是计算机协调多个进程或纯线程并发访问某一资源的机制。在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

生而为人我很抱歉 3086

RT-Thread与ROS2通信:micro-ROS在STM32上的移植实践

本文详细介绍了在STM32平台上使用RT-Thread实时操作系统移植micro-ROS实现与ROS2通信的实践方案。通过对比rosserial方案,重点阐述了micro-ROS基于XRCE-DDS协议栈在数据可靠性(丢包率低于1%)、双模式通信(UDP/串口)以及C/C++混合编程方面的优势,为嵌入式设备与ROS2的高效通信提供了完整解决方案。

emacs5lisp的博客 327

数据库中的锁

暂无

ZackNing的博客 1528

156、手机摄像头模组结构拆解:从保护盖到 FPC 连接器的完整装配剖面

本文深入解析手机摄像头模组结构设计要点。作者结合项目经验,指出保护盖密封胶在低温收缩会导致边缘漏光问题,强调结构细节比算法参数更关键。文章逐层拆解模组组件:保护盖厚度需平衡抗冲击与光学性能;镜筒内镜片组装配顺序和公差控制直接影响成像质量;IR滤光片厚度公差±0.02mm会改变红外截止波长;CSP封装需注意金线加固;FPC连接器的信号完整性和机械可靠性设计。最后给出5条实用建议,包括密封胶选型、镜片对位检测等,强调模组结构设计是"一票否决制"的基础工程。(149字)

sundong_81的博客 104

不会精准对比前人研究写“讨论与对比”段落?教你用ChatGPT辅助,直接让这部分提升一个档次(附提示词指令)

一个我觉得很有效的做法是,选取几篇具有代表性的文献,从研究方法、变量设置或结论方面进行对照分析,并指出本研究在哪些方面进行了补充或修正。除了简单说“提出了新的方法”或“首次应用某模型”,更需要说明这一做法在结果解读、研究设计或理论拓展上的具体意义,最好能够与现有研究进行比较,形成明确的差异化描述。段落应包含:研究结果解释、与前人研究对比、研究贡献、局限性反思,并在结尾提出未来研究的可能方向。讨论与对比部分一般位于文献综述、研究讨论或结果分析的后面,目的是对比已有研究,突出自己研究的价值与新意。

智能AI让学术科研更容易 170

数据库锁概述

目录锁的分类悲观锁和乐观锁共享锁和排他锁表锁和行锁更新锁(避免更新产生死锁)意向锁锁与数据库隔离级别死锁(Deadlock)产生死锁的四个必要条件死锁预防死锁检测与恢复参考 确保事务隔离性的方法之一是要求对数据项以互斥的方式进行访问。也就是说,当一个事务访问某个数据项时,其他任何事务都不能修改该数据项。实现该需求最常用的方法是只允许事务访问当前该事务持有锁(lock)的数据项。 锁的分类 根据不同的分类标准,可以实现不同的锁划分。如根据使用的加锁策略是悲观策略还是乐观策略,可划分为悲观锁和乐观锁;根据加锁的

云原生Java Web领域技术博客 4323

用 ABAP CDS View 把数据稳定抽到 SAP BW/4HANA:从 ODP 架构到增量机制的落地实践

本文探讨了SAP数据仓库中从业务系统抽取数据到SAP BW/4HANA的最佳实践,重点分析了基于ABAP CDS视图的抽取方法。文章指出CDS视图通过注解可实现元数据描述、增量机制的统一管理,替代传统抽取器。详细介绍了ODP架构如何作为抽取基础设施,以及从CDS到BW的完整链路。同时比较了三种增量抽取方式(BW管理时间戳、ODP通用增量、CDC触发器)的适用场景和注意事项,并强调版本兼容性和云环境连接差异对实施的影响。通过实际案例说明合理选择增量策略对数据仓库稳定性的重要性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 330

10个人有9个答错,另外1个只对一半:数据库的锁,到底锁的是什么?

△Hollis, 一个对Coding有着独特追求的人△这是Hollis的第373篇原创分享作者 l Hollis来源 l Hollis(ID:hollischuang)在MySQL数据...

HollisChuang's Blog 862

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

10个人9个答错,另外1个只对一半:数据库的锁,阿里java开发面试

需要特别注意的是,记录锁锁定的是索引记录。即使表没有定义索引,InnoDB也会创建一个隐藏的聚集索引,并使用这个索引来锁定记录。 Gap Lock ======== Gap Lock,翻译成间隙锁,他指的是在索引记录之间的间隙上的锁,或者在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。 那么,这里所谓的Gap(间隙)又怎么理解呢? Gap指的是InnoDB的索引数据结构中可以插入新值的位置。 当你用语句SELECT…FOR UPDATE锁定一组行时。InnoDB可以创建锁,应用于索引中的实际值以及.

m0_63102527的博客 799

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

问一个答错一个:数据库的锁,到底锁的是什么?

在 MySQL 数据库中,为了解决并发问题,引入了很多的锁机制,很多时候,数据库的锁是在有数据库操作的过程中自动添加的。 所以,这就导致很多程序员经常会忽略数据库的锁机制的真正的原理。比如,我经常在面试中会问候选人,你知道 MySQL Innodb 的锁,到底锁的是什么吗? 关于这个问题的回答,我听到过很多种,但是很少有人可以把他回答的很完美。因为想要回答好这个问题,需要对数据库的隔离级别、索引等都有一定的了解才行。 MySQL Innodb 的锁的相关介绍,在 MySQL 的官方文档(MySQL..

gu1857035894的博客 443

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: MyBaits中#{}和${}的真正区别,${}的使用场景,#{}如何防止注入
下一篇: Netty究竟是怎么运行的-连接流程的深入剖析
superjava_
博客等级 码龄5年 254粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值