当前位置: 首页 > news >正文

InnoDB中的锁

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结合,平衡并发性和数据一致性。
  • 提供多种锁类型,适应不同的应用场景。
  • 配合事务隔离级别,确保数据的隔离性和一致性。
  • 但也需要注意死锁和锁等待,合理设计事务逻辑。

相关文章:

  • 第三章:地下三层的技术遗产
  • MySQL ALTER TABLE 组合操作时导致的错误
  • LoadRunner 是什么
  • 打卡day39
  • Shell 脚本基础笔记
  • 车载通信网络 --- CAN FD与CAN XL
  • 计算机毕业设计酒店后台管理系统(vue+springboot+mysql+开题+论文)
  • 切片器导航-大量报告页查看的更好方式
  • 免费开源批量图片格式转换工具
  • STM32F407VET6学习笔记7:Bootloader跳转APP程序
  • 数据可视化(第4、5、6次课)
  • 亚远景-ASPICE与ISO 26262:适用范围与应用场景的差异分析
  • 嵌入式鸿蒙系统中水平和垂直以及图片调用方法
  • 玛哈特校平机:金属板材加工的精整专家
  • 计算机网络之差错控制中的 CRC(循环冗余校验码)
  • 大模型调用数据库表实践:基于自然语言的SQL生成与数据查询系统
  • SSH免密登录其它用户脚本
  • 微小店推客系统开发:技术赋能流量裂变,SEO驱动精准获客
  • [网页五子棋][匹配模块]用户管理器可能存在的问题以及解决办法(线程安全、多开问题)
  • EMQX将社区版和企业版统一到一个强大的 EMQX 平台
  • 青海网站开发建设/社区营销
  • friday wordpress/广州搜索seo网站优化
  • 电子商务网站建设教程pdf/互联网广告投放代理公司
  • 网站域名设计方案/成都网站建设团队
  • 网站服务器有哪些种类/推广代理平台登录
  • 网站闭关保护怎么做/嘉兴seo网络推广