MySQL加锁分析
参考:MySQL 加锁处理分析。该文已经讲的很详尽了,也易懂,下面仅仅是个人做的总结。
一、 背景
1.1 隔离级别
1.2 加锁过程
逐条处理,逐条加锁。
1.3 两阶段锁2PL
1.4 gap锁
gap锁是间隙锁,即相邻两条有效记录间隙的锁(锁的是间隙),它是针对insert的,用来解决幻读的发生。它会阻塞insert,但不会阻塞delete/update等(记录本来也不存在)。
RC与RR的重要区别就是幻读。所以RR才需要引入gap锁。
二、加锁组合分析
说加什么锁,首先要了解两个前提:1)隔离级别;2)用到的索引。不同的隔离级别,不同的索引都会影响加锁。
2.1 可提交读RC
主键/唯一键 | 二级索引 | 无索引 | |
select | 无 | 无 | 无 |
insert | 行锁 | 行锁 | 行锁 |
select...for update/update/delete | 行锁 | 有效行的行锁 | 全表锁聚簇索引 |
2.2 可重复读RR
主键/唯一键 | 二级索引 | 无索引 | |
select | 无 | 无 | 无 |
insert | 行锁 | 行锁 | 行锁 |
select...for update/update/delete | 行锁 | 有效行的行锁+gap锁 | 全表锁聚簇索引 |
2.3 可序列化S
主键/唯一键 | 二级索引 | 无索引 | |
select(快照读) | S | S | S |
其他(当前读) | X | X | X |
注意:无索引时,select...for update/update/delete是需要锁全表的,但mysql_server可以做优化,在逐条加锁时,如果发现不是目标记录,可以释放掉锁。但这会违背2PL的原则。
2.4 结论
死锁的发生与否,并不在于事务中有多少条SQL语句,死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
加锁过程是逐条处理,逐条加锁(最终都反映在聚簇索引上)的。
- 主键,加在聚簇索引上;
- 二级索引,加在二级索引+聚簇索引上;
- 无索引,加在聚簇索引上。
所以如果两个session用到不同的二级索引,那么对聚簇索引的加锁顺序是不一致的,从而导致session间锁的持有与竞争,很容易产生死锁。
- 作者:水岩
- 出处:http://www.cnblogs.com/waterystone
- 本博客中未标明转载的文章归作者水岩和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如果您觉得本文对您的学习有所帮助,可通过支付宝(左) 或者 微信(右) 来打赏博主,增加博主的写作动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话