InnoDB中的锁

article/2025/8/23 13:20:17

InnoDB中的锁机制是MySQL中实现事务隔离和数据一致性的核心部分。它通过多种锁类型和等级,控制多个事务对同一数据的并发访问,保证数据的完整性与一致性。

主要锁类型

  • 1.行锁(Row Lock)
    • 定义:锁定单个行记录。InnoDB采用多版本并发控制(MVCC)结合行锁,支持高并发。
    • 作用范围:单个行数据
    • 类型
      • 共享锁(S锁,共享锁):允许多个事务同时读取(select … lock in share mode),但不允许修改。
      • 排他锁(X锁,排他锁):事务可以修改行数据,其他事务既不能读取(除非使用更低隔离级别),也不能修改。
  • 2 表锁(Table Lock)
    • 比较少用,但在某些操作(如lock tables)会用到。
    • 作用范围:整张表
    • 作用:阻止其他事务对表的任何读写操作,确保完整一致性。

锁的粒度和等级

  • 粒度
    • 行级锁:锁定单个行,细粒度,支持高并发。
    • 表级锁:锁定全表,粗粒度,适用于大量DML操作。
  • 隔离级别对锁的影响

MySQL的事务隔离级别影响锁的行为:

  • Read Uncommitted:可能会读取未提交事务的行(脏读),锁较少。
  • Read Committed:只能读取已提交的行,使用行锁。
  • Repeatable Read(InnoDB默认):通过MVCC和行锁实现,支持一致性读。
  • Serializable:最严格,几乎类似表锁,保证完全隔离。

锁的应用场景

  • select… for update:获得行的排他锁,阻止其他事务修改,常用于更新前锁定。
  • select … lock in share mode:获得共享锁,允许读取但阻止其他事务取得排他锁。

不同类型锁的特点

锁类型作用范围并发支持特点
共享锁(S)行或表多事务可同时读允许读取,不允许修改
排他锁(X)行或表不能同时读写只允许自己操作,其他等待
意向锁(IS, IX)表锁的辅助手锁执行时帮助锁定层次关系通知其他事务锁定意向
自增锁(NEXT KEY)内部机制维护自增主键唯一性防止自增列出现重复

锁的兼容性与冲突

  • 兼容性:如果事务获取了某个数据的共享锁,其他事务可以立即获得该数据的共享锁,这种情况叫锁兼容。如果事务获取了某个数据的共享锁或排他锁,其他事务想要获取该数据的排他锁,必须要等到该行的锁释放掉。

在这里插入图片描述

  • 冲突:主要发生在:
    • 一个事务试图获得排他锁,而另一个事务已持有共享锁或排他锁。
    • 两个事务都试图获得互斥的锁。

死锁

  • 当多个事务相互等待对方释放锁时,会发生死锁。
  • InnoDB检测到死锁后,会选择中断其中一个事务(回滚)解决。

条件

  • 互斥条件:资源(锁)同时只能由一个事务使用。
  • 占有并等待:一个事务至少持有一个资源,同时等待获取其他被占用资源。
  • 非剥夺条件:已占有的资源不能强制收回,只能由持有事务主动释放。
  • 循环等待条件:多个事务形成环状等待关系。

示例流程:

  • 事务A:

锁住table1
等待锁住table2

  • 事务B:

锁住table2
等待锁住table1

  • 此时:

A等待B释放table2
B等待A释放table1

  • 两个事务都在等待对方释放资源,导致僵局(死锁)。

MVCC(多版本并发控制)

  • InnoDB通过MVCC实现非锁定读(一致性读),大幅提升并发性能。
  • 读操作不会等待写锁释放,而是读取数据的快照副本。
  • 核心思想:每个数据行都存储多个版本(快照),不同事务可以看到不同的版本。

工作原理

  • 版本控制:每次对数据的修改(INSERT、UPDATE、DELETE)都会生成一个新的版本。
  • 版本识别:每个事务都有一个事务ID(TS)或时间戳。
  • 读取数据
  • 读取操作根据事务的TS,只读取“版本号” ≤ 自己TS的最新版本。
  • 这样,读取的是事务开始时“的视图”,实现一致性。

在InnoDB中实现

  • 行版本存储:
    • 每行除了实际数据,还有两个隐藏字段:
      • 创建版本(XMIN):该版本由哪个事务创建。
      • 删除版本(XMAX)(可空):标记哪个事务删除了这个版本。
  • 事务管理:
    • 事务有一个事务ID(或时间戳)。
      • 读取时,只访问那些版本号≤自己事务ID的最新版本。
      • 写入时,创建新的版本。

总结

  • MVCC让数据库在进行多事务同时读写时:

    • 读操作不加锁(非锁定读)
    • 写操作仍通过锁控制
    • 不同事务可以“同时”访问不同版本的数据

这样极大提升了并发能力,并保证了事务的隔离性。

意向锁

  • InnoDB 允许事务在行锁和表锁同时存在。为支持在不同粒度上进行加锁,InnoDB 支持意向锁。
  • 意向锁,将锁定的对象分为多个层级,意向锁意味着事务有意向在更细粒度上加锁。如果需要对行加锁,需要先对表加意向锁再对行加锁。

作用和目的

  • 协调锁的层次关系:在InnoDB中,为了支持多粒度锁(表锁和行锁),需要用意向锁告诉其他事务:自己打算在某个部分(比如表的某个行)上加锁。

  • 减少锁冲突:其他事务在请求锁时,通过判断意向锁,可以快速知道表是否已被部分锁定,从而避免不必要的等待。

  • 避免死锁:通过表的意向锁协调不同粒度的锁请求,降低死锁风险。

  • 意向锁的作用:如果没有意向锁,想要给一个表加表锁必须要检查该表是否有表锁和每一行是否有锁。而如果在加行锁前给这个表加上了意向锁,这时只需要检查表锁和意向锁就可以了,不需要检查每一行的锁。

常见的意向锁类型

锁类型作用范围数据库层次描述
意向共享锁(IS,Intention Shared)表锁表明自己打算在某个或多个行上获取共享锁(S锁)
意向排他锁(IX,Intention Exclusive)表锁表明自己打算在某个或多个行上获取排他锁(X锁)

意向锁在 InnoDB 中就是表级别的锁,支持两种意向锁:

  • 意向共享锁(IS Lock),事务有意向对表中某些行加共享锁
  • 意向排他锁(IX Lock),事务有意向对表中某些行加排他锁

表级锁的兼容性在这里插入图片描述

  • 注意:意向锁不会和行级锁冲突,意向锁之间也不会冲突,意向锁只会和共享表锁和排他表锁冲突

用法和流程

  • 事务请求锁的流程
    • 当事务要在表中的某些行上加锁(S或X锁)时,必须先在表上加对应的意向锁(IS或IX)。
  • 这样做的好处
    • 其他事务可以通过意向锁快速得知表是否已有锁定意图,不会不必要地阻塞。
    • 维护锁的层次结构和一致性。
  • 实际操作中的表现
    • 如果一个事务想要在某行上加S锁:它会在该行加共享锁,同时在对应的表上加意向共享锁(IS)(如果没有的话)。
    • 如果一个事务想在行上加X锁:它会在该行加排他锁,同时在表上加意向排他锁(IX)。

示例

假设有两笔事务:

  • 事务A打算在某行加X锁(X相当于写锁)
  • 事务B想在该行加S锁(读取)

在加锁流程中:

  • 事务A会在表上加IX锁。
  • 事务A在目标行上加X锁。
  • 事务B想在该行获取S锁时,会检查表的锁状态,发现表上有IX锁(由A持有),这表示有人在该表上准备加排他锁
  • 根据规则,B会等待A释放锁。

类似的,如果B试图在某行加S锁,且没有冲突的话,也会在表上加IS锁。

总结

特点内容
作用表明事务在表中的某些行上打算加锁,是一种“计划性”锁,用于锁层次协调。
类型IS(意向共享锁)、IX(意向排他锁)
作用范围仅在表级别,用于锁的层次协调
重要性支持多粒度锁,避免锁冲突发生,提升系统并发能力

一致性非锁定读

特点

  • 一致性非锁定读,读取正在执行 delete 和 update 操作的行时,不会等待该行上锁的释放,而是读取该行的一个快照数据(该行之前的版本)。非锁定读极大的提高了数据库的并发性,InnoDB 默认时这种读取方式,也就是说默认普通的 select 语句是不会加锁的,而是通过读取快照实现数据一致性。
  • 上面提到的快照数据就是该行数据的历史版本,由此带来的并发控制称为多版本并发控制(MVCC)。
  • READ COMMITTED(以提交读)和 REPEATABLE READ(可重复读)在 InnoDB 中使用的是一致性非锁定读,但是读取的快照不同。提交读级别读取的是最新版本的快照,可重复读级别读取的是事务开始时数据的快照。

REPEATABLE READ(可重复读)

含义

  • 事务开始时的快照在整个事务期间保持不变。
  • 事务中多次读取同一数据,结果一致,即使其他事务也在修改。
  • InnoDB默认的隔离级别。

READ COMMITTED(已提交读)

含义

  • 每次读取都是“当前事务开始时的快照”,但每次读取都会重新扫描最新的提交版本。
  • 事务中多次读取相同数据,可能会得到不同的结果(如果其他事务提交了修改)。

区别

特性REPEATABLE READREAD COMMITTED
读取快照事务开始时的快照每次读取时最新提交状态
重复读一致性保持不保证(可能不同)
读到的值“快照”版本最新提交值

在这里插入图片描述
可重复读级别通过读快照,可以解决前面提到的幻读问题,但是有些情况需要锁定读

原理

  • InnoDB为每个行文档都维护了隐藏的系统列(如DB_TRX_ID和DB_ROLL_PTR和版本信息):

    • DB_TRX_ID:标识该行最后一次被修改的事务ID
    • DB_ROLL_PTR:指向旧版本的链表(多版本链)
  • 当进行一致性非锁定读时:

    • 读取只看自己事务开启时的“快照”中的版本,不会受其他未提交事务写操作的影响。
    • 允许多个事务同时读数据,而不发生阻塞。

工作流程图

假设有两个事务:

时间点操作描述
事务A开始事务A开始对数据进行读取,读取点为“快照”时间
事务B提交事务B对某行做了修改,提交成功
事务A继续读取事务A读取数据时,看到的版本仍是事务开始时的快照(没有事务B的修改)

如果事务A执行SELECT,它会通过MVCC机制:

  • 读取的是事务开始时的版本快照。
  • 不加锁,不会阻塞其他写操作,也不会被其他写操作阻塞。

实现细节-快照一致性

  • 事务开启时,系统会生成一个快照版本号(Snapshot Version)。
  • 读取数据时,只会显示在自己快照版本之前(或等于自己快照版本)的版本。
  • 即使其他事务修改数据,也不会影响正在读取的快照内容。

总结

特性内容
非锁定读操作不加锁,不阻塞其他事务,避免读写冲突。
一致性读到的是自己事务开始时(或某个时间点)的“快照”,保证读的一致性。
依赖MVCC通过维护多版本,实现多事务并发读写的高效隔离。
隔离级别REPEATABLE READREAD COMMITTED中均支持,一致性非锁定读是它的基础。

一致性锁定读

  • InnoDB 默认使用一致性非锁定读。某些情况用户需要显式加锁保证数据的一致性,支持两种一致性锁定读的操作
    • select … for update:对读取的行加一个排他锁
    • select … lock in share mode:对读取的行加一个共享锁
  • 如果只对读取的行加锁会有幻读问题:

在这里插入图片描述

  • 锁定读时使用键值间隙锁(Next-Key Lock),就是行锁加间歇锁,可以解决幻读问题。
    • Record Lock:单行记录的锁
    • Gap Lock:间歇锁,锁定一个范围,但不包含记录本身
    • Next-Key Lock:Gap Lock + Record Lock,锁定一个范围,并锁定记录本身
  • 非锁定读使用快照和锁定读使用间歇锁可以基本解决幻读问题,但是极特殊情况还是有可能发生幻读。

在这里插入图片描述

特点

  • 非锁定:读取操作不加锁,不阻塞其他事务。
  • 一致性:读取数据是事务开始时的快照,不会受到其他已提交事务的影响。
  • **基于MVCC(多版本并发控制)**实现。

简单例子:

  • 事务A开始,读取数据A,得到的版本是事务A开始时的快照。
  • 其他事务(如B)可以在这期间修改数据并提交,事务A的读取不会受到影响。

与锁定读的区别

功能一致性锁定读(快照读)锁定读(如SELECT ... FOR UPDATE
是否加锁不加锁,非锁定加锁(行锁或表锁)
阻塞情况不阻塞可能阻塞等待其他事务的释放
读到数据事务开始时的快照最新数据(可能被其他事务锁定阻塞)
适用场景高并发、只读操作、保证一致性更新、需要锁保证数据完整
  • 一致性锁定读 是锁定读中的一个类型
  • 在一个事务中,先读到某个数据,然后修改它,为了确保在修改前,没有其他事务修改过,需要用到锁定读,避免“脏读”或“不可重复读”。
需求方法是否需要特殊操作说明
一致性、非阻塞读使用普通select,不需要InnoDB的默认行为,保证读取时一致快照
需要锁定数据以防止其他修改select ... for updatelock in share mode需要用于控制并发读写,保证数据一致性

一致性锁(非锁定读)与其他锁的基本关系

类型作用是否加锁在什么场景使用与其他锁关系
一致性非锁定读(快照读)读到事务开始时的“快照”版本,不阻塞其他事务不加锁(MVCC实现)查询、统计、只读操作不阻塞,也不被阻塞,支持高并发,保证数据一致性
锁定读取(行锁、表锁)以锁定的方式读取,阻止其他事务读写加锁(排他或共享)更新数据、需要控制并发一致性锁定读会阻塞其他写操作,或者等待其他事务释放锁
意向锁(IS、IX)表层次上的“预备锁”,告诉其他事务你的计划加在表上支持多粒度锁、避免锁冲突表级意向锁用于协调实际锁(比如行锁),避免冲突和死锁

关系

  • 在实际操作中,当你用SELECT没有加任何锁时,InnoDB会选择使用快照读,这不是“锁”本身,而是用多版本机制保证数据一致。
  • 如果你用SELECT … FOR UPDATE或LOCK IN SHARE MODE,则会执行锁定读,在数据上加锁,阻止其他事务同时修改或读取(取决于锁类型)。
  • 意向锁是锁粒度的预备措施,帮助协调实际的行锁或表锁,不直接参与读操作,只是标明“我打算加锁”。
  • 一致性锁(快照读)不用加锁,但依赖MVCC保证读取的一致性。
  • 其他锁(行锁、表锁)会加锁,阻塞或等待,确保并发场景下数据的同步和一致。
  • 两者在实际环境中配合使用:快照读提供高效的只读快照,锁定读用在需要确保强一致性或同步更新的场景。

总结

InnoDB的锁机制:

  • 支持细粒度的行级锁,提升并发性能。
  • 利用锁和MVCC结合,平衡并发性和数据一致性。
  • 提供多种锁类型,适应不同的应用场景。
  • 配合事务隔离级别,确保数据的隔离性和一致性。
  • 但也需要注意死锁和锁等待,合理设计事务逻辑。

http://www.hkcw.cn/article/TNXVmSftOd.shtml

相关文章

2025年OE SCI2区TOP,进化麻雀搜索算法ESSA+海洋阻尼器迟滞建模与辨识,深度解析+性能实测

目录 1.摘要2.麻雀搜索算法SSA原理3.ESSA算法4.结果展示5.参考文献6.代码获取7.读者交流 1.摘要 海洋阻尼器的机械性能通常具有高度非线性,以适应动态和冲击环境。阻尼器经过动态和冲击测试,发现其滞回曲线具有速率依赖性且呈非对称性。为了能够描述动态…

贝锐蒲公英工业路由器R300A海外版:支持多国4G频段,全球组网

为更好地满足全球部署和企业出海项目的多样化需求,贝锐蒲公英异地组网工业路由器R300A海外版全新上市,并已正式上架速卖通!无论是跨国分支机构协同办公,还是海外工厂设备远程运维,R300A海外版都能为企业提供灵活、高性…

SQL的查询优化

1. 查询优化器 1.1. SQL语句执行需要经历的环节 解析阶段:语法分析和语义检查,确保语句正确;优化阶段:通过优化器生成查询计划;执行阶段:由执行器根据查询计划实际执行操作。 1.2. 查询优化器 查询优化器…

为什么在我的Flask里面有两个路由,但是在网页里有一个却不能正确访问到智能体

1. /zhoushibo 能访问,/chat 直接浏览器访问报 Method Not Allowed 原因: /zhoushibo 路由是你用 app.route(/zhoushibo) 定义的,返回的是一个HTML网页,浏览器访问没问题。 /chat 路由你用的是 app.route(/chat, methods[POST])…

【笔记】suna部署之获取 Tavily API key

#工作记录 Tavily 注册 Tavily 账号5: 打开浏览器,访问 Tavily 官网Tavily AI。点击页面上的 “注册” 按钮,按照提示填写注册信息,如邮箱地址、设置密码等,完成注册流程。也可以选择使用 Google 或 GitHub 账号授权登…

openbmc kvm vnc client connection

1. VNC 介绍: VNC(Virtual Network Computing,虚拟网络计算) 是一种远程桌面协议(RDP 的替代方案),允许用户通过网络控制另一台计算机的图形界面。其核心特点是 跨平台、开源、基于帧缓冲&…

OpenEuler 22.03 安装 nacos 2.5.1 集群

零:规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器,用于搭建 nacos 集群。这里使用 2.5.1版本 的原因,是因为它是2.x当前的稳定版本 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.15…

ES中must与filter的区别

在 Elasticsearch 的布尔查询(bool query)中,must 和 filter 是两个核心子句,它们的核心区别在于 是否影响相关性评分,这直接决定了它们在查询性能、使用场景和结果排序上的差异。以下是详细对比: 一、核心…

MATLAB源代码——基于Rao检验的自适应贝叶斯检测器

此代码适用于信号检测问题,如雷达信号检测、通信系统中的信号存在性检测等。需要根据实际应用调整噪声模型、信号模型以及检测门限的定义。文章目录 MATLAB源代码代码解释以下是基于 Rao 检验 的 自适应贝叶斯检测器 的一个 MATLAB 示例例程。这个例程假设检测问题为高斯分布下…

2025推客系统小程序开发:独立部署源码交付,高性价比裂变增长引擎

在私域流量争夺白热化的今天,源码独立部署的推客系统小程序已成为企业构建自主分销体系、降低获客成本的核心利器。基于成熟案例与技术沉淀,我们提供安全可控、高性价比的一站式解决方案,助力企业快速搭建专属推客生态,实现长效增…

多家医院回应药企向医生行贿 调查正在进行中

近日,一则关于某药企被举报向四川多家医院上百名医生行贿的消息引发广泛关注。举报材料提及四川省内包括成都市、绵阳市、广安市在内的多个城市的医疗机构,共计37家。达州市第一人民医院工作人员表示,举报信中提到的医生在院方员工名单中并不存在。成都医学院第一附属医院和…

The CTeX fontset “fandol“ is unavailable in the current mode.

完整报错如下 The error message says that the CTeX fontset "fandol" is unavailable in the current mode. This usually happens when using the ctex package with pdfLaTeX, but the Fandol fonts are not installed or not supported in this mode. A commo…

贵州一公路落石 汽车被砸中坠落高坎 地质灾害点雨后事故

贵州一公路落石 汽车被砸中坠落高坎 地质灾害点雨后事故!5月28日,贵州毕节市七星关区何官屯镇一条通村公路突发落石。一块约300斤重的巨石砸中一辆过路汽车,导致车辆从路边高坎坠落。司机受轻伤,送医检查后当日返家,车损由保险公司处理。落石还击碎了附近民房的玻璃门,但…

端午民航出行延续“量价齐升” 入境游火爆

端午民航出行延续“量价齐升” 入境游火爆。端午假期临近,位于五一旅游热潮与暑期旺季之间,今年的端午出行市场展现出独特节奏。受假期时长、高考临近等因素影响,旅客出行以周边游为主,同时出入境市场亮点频现,机票价格延续五一假期热度,同比增长。铁路方面,据上铁集团发…

[网页五子棋][匹配模块]处理开始匹配/停止匹配请求(匹配算法,匹配器的实现)

文章目录 处理开始匹配/停止匹配请求匹配算法实现匹配器(1)完善匹配器的 TODO 实现匹配器(2)实现 handlerMatch线程安全忙等问题 处理开始匹配/停止匹配请求 实现 handleTestMessage 先从会话中拿到当前玩家的信息解析客户端发来的请求判定请求的类型 如果是 startMatch&…

11.spark源码编译

1.构建环境 构建环境: ubuntu 22.04 jdk 11 scala 2.12 maven 3.9 spark 3.5 2.构建 获取代码 pull代码后,切换到对应分支。 git checkout branch-3.5编译 构建spark mvn -DskipTests clean package \-Dhadoop.version3.3.6 \-Phive -Phive-thrif…

前端必备——Grid布局详解

Grid布局,又称为CSS网格布局,是W3C提出的一个二维布局系统,它允许开发者以行和列的形式来布局网页内容。以下是Grid布局属性的详细解析: 一、容器属性 display grid:将元素设置为块级网格容器。inline-grid&#xff1…

基于Java Web和SSM框架的硕士研究生招生考试系统开发

本文还有配套的精品资源,点击获取 简介:本项目旨在构建一个硕士研究生招生考试专业报考查询及学习系统,使用Java Web技术并集成了Spring、SpringMVC和MyBatis(SSM)框架。系统通过模块化架构和分离关注点&#xff08…

MCP Web Research Server 安装与配置指南

MCP Web Research Server 安装与配置指南 mcp-webresearch MCP web research server (give Claude real-time info from the web) 项目地址: https://gitcode.com/gh_mirrors/mcpw/mcp-webresearch 1. 项目基础介绍 MCP Web Research Server 是一个基于 Model Context …

0基础入门前端到精通(一)

目录 一丶前端开发介绍 1. 网页的组成部分 2. 网页的本质是什么? 3. 前端代码如何变成网页? 4. 统一网页显示标准:Web 标准 二丶HTML & CSS 1. 什么是 HTML? 2. 什么是 CSS? ​3. HTML 快速入门&#xff0…