MySQL --- 读书笔记 --- 锁
2. 并发事务访问相同记录的情况
2.1 读-读情况
读取操作并不会对记录有任何影响,所以允许这种情况的发生
2.2 写-写情况
对相同记录做出改动,在这种情况下会出现脏写
情况,任何一种隔离级别都不允许这种情况的发生,所以多个未提交事务对一条记录做改动时,都需要排队执行
,排队的过程是通过锁
实现的。
这个所谓锁
是一个内存中的结构
,在事务执行之前本来是没有锁的,当一个事务想对记录做改动时,首先看看内存有没有与这条记录相关联的锁结构
,当没有的时候,就会生成一个与之关联的锁
结构,这称为获取锁成功
。
然后在这个事务提交之前,另一个事务也想对这条记录改动时,也会想查看与之关联的锁
结构,当发现有锁时,也会生成一个锁结构与之关联,但是需要等待,这称为获取锁失败
当第一个事务结束后,就会把相应的锁结构释放,并查看是否别的事务在等待,如果有,就会唤醒该事务
2.3 读-写或写-读情况
当一个事务读取记录,另一个事务改动记录,这种情况下就会出现脏读
、不可重复读
和幻读
问题
- 读写都加锁
- 读取记录采用
MVCC
,改动记录采用锁
锁的不同角度分类
3.1 从数据操作的类型划分
对于InnoDB来说,读锁/写锁可以加在表上,也可以在行上
1. 读锁/共享锁
英文S
表示,针对同一份数据,多个事务的读操作同时进行,相互不阻塞
SELECT ... FOR SHARE;
2. 写锁/排他锁
英文X
表示,在当前操作未完成前,阻断其他写锁或读锁
SELECT ... FOR UPDATE;
3.2 从数据操作的粒度划分
1. 表锁
该锁会锁定这个张表的记录,是MySQL中最基本的锁策略,并不依赖于存储引擎,它的开销最小
,可以很好的避免死锁
问题,但是随之而来的锁竞争发生的概率也会提高,导致并发率大打折扣
- 表级别的S、X锁
- 意向锁
InnoDB支持多粒度锁
,允许行级锁与表级锁共存
- 意向锁是为了协调行锁和表锁的关系
- 意向锁是一种
不与行级锁冲突的表级锁
- 表明“某个事务正在某些行持有锁或该事务准备去持有锁”
- 自增锁
- 元数据锁
意向锁是由存储引擎维护,用户无法手动操作,在为数据行加S/X锁时,会先获取该数据行所在数据表的意向锁
意向锁解决的问题:假设有两个事务t1和t2,当t2想要给表加上S/X锁,那么它需要检查表中每一行记录是否存在锁,但是如果我们有意向锁,当t1给表中某些记录加锁时,首先给表添加意向锁,然后当t2想要进行表级锁时,就可以直接知道表中某些记录被其他事务锁定了
2. 行锁
- 优点:粒度小,发生锁冲突概率低,并发度高
- 缺点:开销大,加锁慢,容易出现死锁
- 记录锁
- 间隙锁
在解决幻读问题上,当使用锁
的方案时,事务读取记录时,幻影记录还没添加,我们无法给幻影记录加上记录锁,这时就要用到间隙锁
假设给一条记录加上间隙锁,那么这条记录的前边就不允许插入记录,或者说当主键3和主键8之间没有其他记录,当给主键8这条记录加上间隙锁,那么不允许插入主键是3-8之间的记录
无论是共享间隙锁或者排他间隙锁,并不限制其他事务对这条记录加记录锁或者间隙锁
- 临键锁
当既想锁定某条记录,又阻止其他事务在该记录的前边间隙插入新记录,这时就用到临键锁,它只在InnoDB中的可重复读的隔离级别下使用,InnoDB的默认锁就是临键锁
本质是一个记录锁和间隙锁的合体
- 插入意向锁
InnoDB规定事务在等待的时候也需要在内存中生成一个锁结构
当事务希望插入新记录时,但是遇到间隙锁需要等待时,生成一个插入意向锁,它是一种Gap锁
不是意向锁
它是一种特殊的间隙锁,当插入记录之间不同时,互相不排斥
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?