mysql中的的锁

mysql的事务

MySQL 锁分类详解

MySQL锁可以根据 锁的类型、加锁的范围(颗粒度)、锁的思想三大类。


一、按锁的类型分类

1. 共享锁(S Lock)

  • 作用:允许事务读取数据,其他事务可加共享锁,但不可加排他锁。
  • 场景SELECT ... FOR SHARELOCK TABLES ... READ

2. 排他锁(X Lock)

  • 作用:允许事务修改数据,其他事务不可加任何锁。
  • 场景SELECT ... FOR UPDATELOCK TABLES ... WRITE、写操作(INSERT/UPDATE/DELETE)。

二、按锁的粒度(范围)分类

1. 全局锁

  • 作用:锁定整个数据库实例,禁止所有写入操作(只读模式)。
  • 命令FLUSH TABLES WITH READ LOCK(需手动释放)。
  • 用途:全库逻辑备份时确保数据一致性。

2. 表级锁

  • 共享表锁(S Lock)
    • 添加方式LOCK TABLES table_name READ
    • 兼容性:允许其他事务加共享锁,禁止排他锁。
  • 排他表锁(X Lock)
    • 添加方式LOCK TABLES table_name WRITE
    • 兼容性:禁止其他事务加任何锁。
  • 意向锁(IS/IX)
    • 意向共享锁(IS):事务准备在行级加共享锁时,自动在表级添加 IS。
    • 意向排他锁(IX):事务准备在行级加排他锁时,自动在表级添加 IX。
    • 作用:快速判断表内是否有行级锁,避免全表扫描。
    • 兼容性:IS 与 IX 兼容,但 IS/IX 与表级 S/X 锁互斥。

3. 行级锁(InnoDB 特有)

  • 记录锁(Record Lock)

    • 作用:锁定具体某一行(共享或排他)。
    • 触发方式
      • 显式:SELECT ... FOR SHARE(S 锁)或 FOR UPDATE(X 锁)。
      • 隐式:所有写操作(INSERT/UPDATE/DELETE)自动对受影响行加 X 锁。
  • 间隙锁(Gap Lock)

    • 作用 :锁定索引记录之间的间隙(如 id BETWEEN 5 AND 10),防止其他事务插入新数据,解决幻读。

    • 触发条件 :仅在 REPEATABLE READ 隔离级别下生效。

    • 查询条件与索引唯一性

      是否加间隙锁不仅取决于查询范围,还受 索引唯一性查询结果确定性 影响:

      查询类型 命中索引类型 是否加间隙锁 备注
      精确查询 唯一索引 不加间隙锁 唯一索引数据一定记录唯一,不会涉及到记录之间的间隙
      非精确查询 非唯一索引 加间隙锁 范围查询 非唯一索引 InnoDB 认为可能存在幻读的风险 一定加间隙锁
      精确查询 非唯一索引 取决于查询的数据是否唯一 如果数据唯一,不加间隙锁;如果数据不唯一,可能加间隙锁
      非精确查询 唯一索引 取决于查询的数据是否唯一 就算是唯一索引但是查询的范围包含多个可能的插入位置,InnoDB 认为可能存在幻读的风险(如where statistics_date > '2022-08-01' 可能影响多行数据。),除非查询范围内的数据仍然是唯一的 (如根据主键in删除)

      核心规则

      InnoDB 仅在 无法确定查询结果唯一性 时加间隙锁。唯一索引的精确命中查询可直接锁定记录,无需间隙锁。

  • Next-Key Lock

    • 组成:记录锁 + 间隙锁,锁定行及其前面的间隙。
    • 场景 :范围查询(如 SELECT * FROM t WHERE id > 100)。
  • 插入意向锁(Insert Intention Lock)

    • 作用:标记事务准备插入的位置,是一种特殊的间隙锁。
    • 兼容性:多个插入意向锁在相同间隙可共存,但与间隙锁冲突。
    • 触发方式INSERT 操作前自动添加。

三、按锁的思想分类

1. 悲观锁

  • 核心:假设并发冲突必然发生,主动加锁控制。
  • 实现SELECT ... FOR UPDATE、写操作自动加锁。

2. 乐观锁

  • 核心:假设无冲突,提交时检测版本是否变化(如 CAS)。
  • 实现:通过版本号字段或时间戳判断数据是否被修改。
  • 场景:高并发读多写少场景(如库存扣减)。

四、关键细节与常见误区

1. 间隙锁的概念

间隙锁​ 是一种范围锁,用于锁定 ​数据记录之间的间隙​(例如两个已有记录之间的区间),而不是锁定事务操作的时间间隔。它的主要作用是防止其他事务在这些数据间隙中插入新记录,从而避免幻读问题。

2. 间隙锁的触发条件

  • 仅在 REPEATABLE READ 级别生效,READ COMMITTED 下不生效。

3. 插入意向锁的特殊性

  • 与间隙锁的关系:插入意向锁会等待间隙锁释放,但允许其他插入意向锁共存。
  • 示例:事务 A 对间隙 (5,10) 加间隙锁,事务 B 试图在该间隙插入时,会先加插入意向锁并等待。

4. Next-Key Lock 的幻读解决

  • REPEATABLE READ 下,通过锁定索引记录及间隙,确保范围内数据不被插入新值。

5. 表级锁与存储引擎的关系

  • LOCK TABLES 是 MySQL Server 层实现的表锁,与存储引擎无关。
  • InnoDB 通常使用行级锁,避免显式表锁(LOCK TABLES 会破坏行锁的并发优势)。

五、锁的兼容性分析

5.1 表级锁与意向锁的兼容性矩阵

当前锁 \ 请求锁 S(表) X(表) IS IX
S(表) ✔️
X(表)
IS ✔️ ✔️
IX ✔️ ✔️
  • 说明
    • 表级 共享锁(S Lock)排他锁(X Lock) 与意向锁(IS/IX)互斥。
    • 意向锁之间(IS 与 IX)是兼容的。

5.2 插入意向锁的兼容性分析

锁类型 是否兼容 是否等待 详细说明
插入意向锁 兼容 不需要等待 多个事务可在同一间隙加插入意向锁(允许并发插入同一间隙)。
共享锁(S Lock) 兼容 不需要等待 共享锁是行级记录锁,作用于具体行;插入意向锁作用于间隙,二者无直接冲突。
排他锁(X Lock) 不兼容 需要等待 排他锁是行级记录锁,若插入意向锁的间隙包含被 X 锁锁定的行,则需等待。
间隙锁(Gap Lock) 不兼容 需要等待 间隙锁直接锁定区间,插入意向锁需等待间隙锁释放才能插入。
  • 说明
    • 插入意向锁是一种特殊的间隙锁,主要用于标记插入意图。
    • 与共享锁兼容,但与排他锁和间隙锁冲突,需等待锁释放。
    • 允许多个事务在同一间隙加插入意向锁,但实际插入时需通过行锁(记录锁)竞争确保唯一性。
相关推荐
0xDevNull20 分钟前
MySQL数据冷热分离详解
后端·mysql
科技小花36 分钟前
数据治理平台架构演进观察:AI原生设计如何重构企业数据管理范式
数据库·重构·架构·数据治理·ai-native·ai原生
一江寒逸38 分钟前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
D4c-lovetrain40 分钟前
linux个人心得22 (mysql)
数据库·mysql
阿里小阿希1 小时前
CentOS7 PostgreSQL 9.2 升级到 15 完整教程
数据库·postgresql
荒川之神1 小时前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle
做个文艺程序员2 小时前
MySQL安全加固十大硬核操作
数据库·mysql·安全
不吃香菜学java2 小时前
Redis简单应用
数据库·spring boot·tomcat·maven
一个天蝎座 白勺 程序猿2 小时前
Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南
数据库·apache·etl·iotdb
不知名的老吴2 小时前
Redis的延迟瓶颈:TCP栈开销无法避免
数据库·redis·缓存