MySQL 锁机制详解
死锁是怎么发生的?
SELECT ... FOR UPDATE到底锁了什么?本文系统梳理 MySQL 的锁体系。
一、锁的分类总览
- 1.1 按粒度——全局锁、表级锁、行级锁
- 1.2 按模式——共享锁(S)、排他锁(X)、意向锁(IS/IX)
- 1.3 按算法——记录锁、间隙锁、临键锁
二、全局锁
- 2.1
FLUSH TABLES WITH READ LOCK——全库只读 - 2.2 使用场景——全库备份(mysqldump
--master-data) - 2.3 风险——业务停摆
三、表级锁
- 3.1 表锁——
LOCK TABLES ... READ/WRITE - 3.2 元数据锁(MDL)——DDL 操作自动加锁
- 3.3 MDL 的坑——
ALTER TABLE阻塞所有查询 - 3.4 自增锁(AUTO-INC)——
innodb_autoinc_lock_mode
四、行级锁
- 4.1 记录锁(Record Lock)——锁定索引记录
- 4.2 间隙锁(Gap Lock)——锁定记录之间的间隙
- 4.3 临键锁(Next-Key Lock)——记录锁 + 间隙锁
- 4.4 插入意向锁(Insert Intention Lock)
五、意向锁
- 5.1 为什么需要意向锁——表锁和行锁的冲突检测
- 5.2 加行锁前先加意向锁——IS / IX
- 5.3 意向锁之间不冲突
六、死锁排查
- 6.1
SHOW ENGINE INNODB STATUS——死锁日志分析 - 6.2 死锁的四个必要条件
- 6.3 常见死锁场景——两个事务以不同顺序加锁
- 6.4 死锁避免——统一加锁顺序、缩短事务
七、乐观锁与悲观锁
- 7.1 悲观锁——
SELECT ... FOR UPDATE - 7.2 乐观锁——版本号 CAS
- 7.3 适用场景——冲突多的用悲观锁,冲突少的用乐观锁
八、总结
- MySQL 锁体系全景图
- 锁等待超时——
innodb_lock_wait_timeout
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!