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) 不兼容 需要等待 间隙锁直接锁定区间,插入意向锁需等待间隙锁释放才能插入。
  • 说明
    • 插入意向锁是一种特殊的间隙锁,主要用于标记插入意图。
    • 与共享锁兼容,但与排他锁和间隙锁冲突,需等待锁释放。
    • 允许多个事务在同一间隙加插入意向锁,但实际插入时需通过行锁(记录锁)竞争确保唯一性。
相关推荐
m0_672656546 分钟前
如何把图片或者图片地址存到 MySQL 数据库中以及如何将这些图片数据通过 JSP 显示在网页中
java·数据库·mysql
mengweijin28 分钟前
华为 Open Gauss 数据库在 Spring Boot 中使用 Flyway
数据库·spring boot·华为·flyway·gauss
Dav_209936 分钟前
DAV_postgresql_3-schema
数据库
裁二尺秋风1 小时前
MongoDB—(一主、一从、一仲裁)副本集搭建
数据库·mongodb
"Wild dream"1 小时前
正则表达式
java·数据库·mysql·正则表达式
奥顺1 小时前
PHP函数与类:面向对象编程实践指南
android·开发语言·mysql·开源·php
安 当 加 密2 小时前
安当全栈式MySQL安全解决方案:透明加密、动态凭据与勒索防护一体化实践
数据库·mysql·安全
web150850966412 小时前
如何将 Excel 数据转换为 SQL 脚本:从入门到实战
数据库·sql·excel
zhyhgx2 小时前
【Spring】Spring事务管理
数据库·mysql·spring
yqcoder2 小时前
Express + MongoDB 实现 VOD 视频点播
数据库·mongodb·express