别院牧志知识库 别院牧志知识库
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • Python 面试题
  • 2025 面试记录
  • 2022 面试记录
  • 2021 面试记录
  • 2020 面试记录
  • 2019 面试记录
  • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • Python 面试题
  • 2025 面试记录
  • 2022 面试记录
  • 2021 面试记录
  • 2020 面试记录
  • 2019 面试记录
  • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 工作
  • 规范

  • Linux

  • 数据库

    • MySQL

      • 推荐几本学习 MySQL 的好书
      • MySQL 索引原理
      • MySQL 事务
      • 聚集索引与非聚集索引的总结
      • Linux 安装 MySQL(包含源码安装和 yum 安装)
      • 为什么数据库不应该使用外键
      • MySQL 为什么要使用 B+树索引
      • MySQL 的 MVCC(多版本并发控制)机制
      • MySQL 锁机制
      • MySQL 的 MVCC 与锁机制的关联和区别
        • 一、MVCC 与锁的关联
          • 1. 协同实现事务隔离级别
          • 2. MVCC 依赖锁实现写安全
        • 二、MVCC 与锁的核心区别
        • 三、MVCC 的工作原理(以 InnoDB 为例)
          • 1. 核心组件
          • 2. 可见性判断规则
        • 四、锁机制的关键类型
          • 1. 行级锁(Record Locks)
          • 2. 间隙锁(Gap Locks)
          • 3. 临键锁(Next-Key Locks)
        • 五、MVCC 与锁在不同隔离级别的应用
        • 六、实战案例:库存扣减场景
          • 1. 并发更新问题
          • 2. 解决方案
        • 七、总结
      • MySQL 日志:undo log、redo log、binlog 有什么用?
      • MySQL 知识总结
      • MySQL 分表分库知识整理
      • 常用 SQL 整理
    • redis

    • 数据库操作记录
    • 数据库设计
    • SQLAlchemy 2.0 教程
  • Git

  • 👨‍💻Web

  • 英语

  • Docker

  • 编辑器

  • 网络

  • 前端

  • 存储

  • 备忘录

  • 如何开始你的单元测试
  • 以程序员的视角看中国——西安篇
  • 💻工作
  • 数据库
  • MySQL
佚名
2025-05-28
目录

MySQL 的 MVCC 与锁机制的关联和区别

MySQL 的 MVCC(多版本并发控制) 和 锁机制 是两种互补的并发控制策略,共同保障数据的一致性和隔离性,但两者的设计目标和实现方式存在显著差异。以下是两者的核心关联、区别及应用场景的深度解析:


# 一、MVCC 与锁的关联

# 1. 协同实现事务隔离级别

  • MVCC:通过 版本链(Undo Log) 实现 非阻塞读,解决读-写冲突。
  • 锁机制:通过 临键锁(行锁+间隙锁) 解决 写-写冲突,确保数据修改的互斥性。
    示例:在 REPEATABLE READ 级别下:
    • 事务 A 查询数据时,MVCC 基于 ReadView 读取历史版本(不阻塞其他事务读)。
    • 事务 B 修改同一行时,需获取行锁(X 锁),阻塞其他事务的写操作。

# 2. MVCC 依赖锁实现写安全

  • 写操作(如 UPDATE)需先加锁(X 锁),再修改数据并生成新版本(写入 Undo Log)。
  • 关键流程:
    1. 加锁 → 2. 拷贝当前数据到 Undo Log → 3. 修改数据 → 4. 释放锁。

# 二、MVCC 与锁的核心区别

特性 MVCC 锁机制
目标 解决 读-写冲突,提高读并发 解决 写-写冲突,保证数据一致性
阻塞行为 读操作 不阻塞 写操作 写操作 阻塞 其他写操作
实现方式 基于 Undo Log 版本链 + ReadView 基于锁(行锁、间隙锁、表锁)
资源消耗 额外存储历史版本(可能增加 Undo Log) 锁竞争可能引起线程阻塞
适用场景 高并发读场景(如报表查询) 高并发写场景(如库存扣减)

# 三、MVCC 的工作原理(以 InnoDB 为例)

# 1. 核心组件

  • 隐藏字段:
    每行数据包含 DB_TRX_ID(最近修改的事务 ID)和 DB_ROLL_PTR(指向 Undo Log 的指针)。
  • Undo Log:
    存储数据的历史版本,形成版本链。
  • ReadView:
    事务启动时生成,包含:
    • m_ids:活跃事务 ID 列表
    • min_trx_id:最小活跃事务 ID
    • max_trx_id:预分配的下一个事务 ID
    • creator_trx_id:创建 ReadView 的事务 ID

# 2. 可见性判断规则

事务根据 ReadView 判断数据版本是否可见:

  1. 若 DB_TRX_ID < min_trx_id → 版本已提交,可见。
  2. 若 DB_TRX_ID > max_trx_id → 版本属于未来事务,不可见。
  3. 若 min_trx_id ≤ DB_TRX_ID ≤ max_trx_id:
    • DB_TRX_ID 在 m_ids 中 → 事务未提交,不可见。
    • 不在 m_ids 中 → 事务已提交,可见。

示例:事务 A(ID=100)启动时生成 ReadView(活跃事务:[100, 102])。

  • 若某行 DB_TRX_ID=90(小于 min_trx_id=100)→ 可见。
  • 若 DB_TRX_ID=101(在活跃事务中)→ 不可见,需沿版本链查找更早版本。

# 四、锁机制的关键类型

# 1. 行级锁(Record Locks)

  • 共享锁(S 锁):允许其他事务读,阻塞写操作。

    SELECT * FROM table WHERE id = 1 LOCK IN SHARE MODE;
    
    1
  • 排他锁(X 锁):阻塞其他事务的读写操作。

    SELECT * FROM table WHERE id = 1 FOR UPDATE;
    
    1

# 2. 间隙锁(Gap Locks)

  • 锁定索引记录之间的间隙(防止幻读)。
    示例:锁定 (5, 10) 区间,禁止插入 id=7 的新记录。

    -- 在 id=5 和 id=10 之间加间隙锁
    SELECT * FROM table WHERE id BETWEEN 5 AND 10 FOR UPDATE;
    
    1
    2

# 3. 临键锁(Next-Key Locks)

  • 行锁 + 间隙锁 的组合(InnoDB 默认锁)。
    示例:锁定 (5, 10] 区间(包含 id=10 的行及之前的间隙)。

# 五、MVCC 与锁在不同隔离级别的应用

隔离级别 MVCC 的作用 锁机制的作用
READ UNCOMMITTED ❌ 不使用 MVCC ❌ 不加锁(可能脏读)
READ COMMITTED ✅ 每次读生成新 ReadView ✅ 写操作加行锁(无间隙锁)
REPEATABLE READ ✅ 事务内首次读生成 ReadView ✅ 写操作加行锁 + 间隙锁
SERIALIZABLE ❌ 退化到锁控制 ✅ 所有读操作隐式加 S 锁

重点说明:

  • REPEATABLE READ 下,MVCC 保证事务内一致性读,间隙锁防止幻读。
  • READ COMMITTED 下,MVCC 每次读获取最新快照,可能不可重复读。

# 六、实战案例:库存扣减场景

# 1. 并发更新问题

-- 事务 A:扣减库存
BEGIN;
SELECT stock FROM products WHERE id = 1; -- 假设 stock=10
UPDATE products SET stock = 9 WHERE id = 1;
COMMIT;
1
2
3
4
5

若事务 B 同时扣减,可能发生超卖。

# 2. 解决方案

  • 锁机制(写-写冲突):

    BEGIN;
    SELECT stock FROM products WHERE id = 1 FOR UPDATE; -- 加 X 锁
    UPDATE products SET stock = stock - 1 WHERE id = 1;
    COMMIT;
    
    1
    2
    3
    4
  • MVCC(读-写分离):
    其他事务查询库存时,通过 ReadView 读取旧版本数据(不阻塞扣减操作)。


# 七、总结

  • MVCC:
    • 核心价值:非阻塞读,提高并发性。
    • 实现依赖:Undo Log 版本链 + ReadView 可见性判断。
  • 锁机制:
    • 核心价值:解决写冲突,保证数据一致性。
    • 关键类型:行锁、间隙锁、临键锁。
  • 协作关系:
    • 读操作:优先使用 MVCC(避免锁竞争)。
    • 写操作:必须加锁(确保原子性)。
  • 隔离级别:
    • 低级别(如 RC)依赖 MVCC 实现读提交。
    • 高级别(如 RR)结合 MVCC 和间隙锁解决幻读。

通过 MVCC 和锁的协同,MySQL 在保证数据一致性的同时,实现了高并发读写能力。实际开发中,需根据业务场景选择合适的隔离级别和锁策略。

编辑 (opens new window)
#MySQL#MVCC#锁机制
上次更新: 2025-06-06, 02:48:08
MySQL 锁机制
MySQL 日志:undo log、redo log、binlog 有什么用?

← MySQL 锁机制 MySQL 日志:undo log、redo log、binlog 有什么用?→

最近更新
01
Flask 运行周期及工作原理
06-05
02
支付系统策略模式实现代码
06-04
03
Python 中 OOM(内存泄漏)问题的定位与分析
05-30
更多文章>
Theme by Vdoing | Copyright © 2019-2025 IMOYAO | 别院牧志
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式