《MySQL 技术内幕(第5版)》逐章精华笔记第五章

发布于:2025-06-25 ⋅ 阅读:(15) ⋅ 点赞:(0)

第5章:锁机制(完整版)

🎯 本章目标

  • 弄懂 MySQL 的各种锁类型及作用

  • 理解 InnoDB 如何实现高并发控制

  • 掌握死锁场景、排查与解决方案

  • 弄清楚 MVCC 与锁的关系


一、锁的分类总览

🔒 1. 粒度分类

锁类型 粒度 说明
表锁 表级别 一次锁整张表
行锁 行级别 精细到某一行
意向锁 表级别元信息 标识是否打算加行锁

🔀 2. 模式分类

锁模式 含义
共享锁 (S) 多个事务可读
排它锁 (X) 只有一个事务可写

📌 InnoDB 默认使用行级锁 + 意向锁组合来实现高并发。


二、意向锁的作用

意向锁不是业务加的,而是 InnoDB 自动加的表级锁

🔍 目的:

  • 解决“表锁 vs 行锁”冲突判断的问题

举例:

  • 若事务 T1 想对某行加排它锁,InnoDB 会先加“意向排它锁 (IX)”到表上

  • 这样其他事务想加表锁就能快速判断是否有冲突


三、行锁实现与加锁范围

📌 行锁是通过 索引加锁实现的

SELECT * FROM user WHERE id = 5 FOR UPDATE;

✅ 会加锁成功(id 是主键)

SELECT * FROM user WHERE name = '张三' FOR UPDATE;

❌ name 无索引,会退化为表锁

锁的种类(InnoDB 内部)

类型 说明
Record Lock 行锁,锁定某一行数据
Gap Lock 间隙锁,锁定两个记录间的空隙
Next-Key Lock 行 + 间隙,用于防止幻读

四、死锁与检测机制

死锁是两个或多个事务互相持有资源,形成循环等待。

常见死锁场景:

-- T1:
BEGIN;
UPDATE user SET age = 30 WHERE id = 1;

-- T2:
BEGIN;
UPDATE user SET age = 40 WHERE id = 2;

-- T1:
UPDATE user SET age = 40 WHERE id = 2; -- 阻塞
-- T2:
UPDATE user SET age = 30 WHERE id = 1; -- 死锁发生!

InnoDB 的解决方案:

  • 默认启用 死锁检测(选择牺牲一个事务)

  • 可通过:

SHOW ENGINE INNODB STATUS\G

查看最近一次死锁信息。

避免死锁建议:

  • 避免不同事务更新同一张表的不同顺序

  • 一次性加锁(批量更新)

  • 保持事务短小


五、MVCC 与锁的关系

MVCC(多版本并发控制)是 InnoDB 提高并发性能的核心机制。

它的作用:

  • 避免读操作加锁 → 快速返回数据

📘 两种读方式:

类型 是否加锁 说明
快照读 SELECT 不加锁,读取旧版本(多版本)
当前读 SELECT ... FOR UPDATE / UPDATE / DELETE

实现方式:

  • 每行记录维护两个隐藏字段:trx_idroll_pointer

  • undo log 存历史版本

  • SELECT 判断版本可见性:只能看到自己“开始时”已经提交的事务版本

📌 快照读 = 无锁读取一致性视图;当前读 = 加锁读当前数据


六、实验与练习题

🧪 实验:验证 FOR UPDATE 是否加锁

-- 会加锁
SELECT * FROM user WHERE id = 1 FOR UPDATE;

-- 无索引字段:可能退化为表锁!
SELECT * FROM user WHERE name = '张三' FOR UPDATE;

✅ 自测题

  1. 表锁和行锁谁并发性能更好?

    • ✅ 行锁

  2. 什么是 next-key lock?

    • ✅ 行锁 + 间隙锁,用于防幻读

  3. InnoDB 如何避免幻读?

    • ✅ 使用 next-key lock

  4. 快照读是否加锁?MVCC 是如何实现的?

    • ✅ 不加锁,基于 undo log + 版本判断


七、图解锁结构与事务并发控制

[InnoDB 锁体系结构]

 表级:意向锁(IS/IX)
   ↑
 行级:Record Lock(精确)
       Gap Lock(防止插入)
       Next-Key Lock(复合)

 事务并发:
   - MVCC 快照读提升性能
   - 当前读强一致性控制
   - 死锁检测避免系统卡死

📣 下一章我们将深入 第6章:事务与日志系统,包括:

  • undo log / redo log / binlog 的区别和用途

  • 两阶段提交协议原理

  • MySQL 如何保证事务的 ACID 特性


网站公告

今日签到

点亮在社区的每一天
去签到