锁机制
锁的基本概念
什么是锁?
为什么需要锁?
-- 场景:两个事务同时给账户加 100 元
-- 初始余额:1000 元
-- 事务 A 事务 B
BEGIN; BEGIN;
SELECT balance FROM account
WHERE id = 1; -- 读到 1000
SELECT balance FROM account
WHERE id = 1; -- 读到 1000
UPDATE account SET balance = 1100
WHERE id = 1; -- 1000 + 100
UPDATE account SET balance = 1100
WHERE id = 1; -- 1000 + 100
COMMIT; COMMIT;
-- 结果:余额是 1100,而不是 1200!(丢失更新)锁的分类
1. 按锁的粒度分类
1.1 全局锁(Global Lock)
1.2 表级锁
读锁
写锁
MDL 读锁
MDL 写锁
IS
IX
S
X
2. 按锁的模式分类
2.1 共享锁(Shared Lock,S 锁)
2.2 排他锁(Exclusive Lock,X 锁)
S 锁
X 锁
3. 按锁的算法分类(InnoDB 行锁)
3.1 记录锁(Record Lock)
3.2 间隙锁(Gap Lock)
3.3 临键锁(Next-Key Lock)
3.4 插入意向锁(Insert Intention Lock)
InnoDB 行锁详解
行锁的本质
不同索引类型的加锁
1. 主键索引(聚簇索引)
2. 唯一索引
3. 普通索引
4. 无索引
加锁规则分析
加锁规则总结
场景 1:唯一索引等值查询(记录存在)
场景 2:唯一索引等值查询(记录不存在)
场景 3:唯一索引范围查询
场景 4:非唯一索引等值查询
场景 5:非唯一索引范围查询
场景 6:无索引条件
加锁规则速查表
索引类型
查询类型
记录是否存在
加锁情况
死锁
什么是死锁?
死锁的四个必要条件
死锁案例 1:简单的两个事务
死锁案例 2:间隙锁与插入意向锁
死锁检测与处理
1. 死锁检测
2. 超时机制
3. 死锁处理策略
4. 查看死锁信息
如何避免死锁
1. 按相同顺序访问资源
2. 尽量使用索引访问数据
3. 减小事务粒度,缩短事务时间
4. 使用较低的隔离级别
5. 为表添加合理的索引
6. 避免大事务
7. 使用 SELECT ... FOR UPDATE 要慎重
锁的监控与诊断
1. 查看当前锁等待
MySQL 5.7
MySQL 8.0+
2. 查看详细的锁信息
3. 分析锁等待时间
4. 杀死阻塞的会话
面试高频问题
Q1: MySQL 有哪些锁?
Q2: 什么是间隙锁和临键锁?
Q3: 不同 SQL 语句如何加锁?
Q4: 如何避免死锁?
Q5: 为什么 InnoDB 的锁是加在索引上的?
Q6: 意向锁的作用是什么?
Q7: RC 和 RR 隔离级别的锁有什么区别?
总结
核心要点
学习建议
记住这些关键点
Last updated