12|数据库锁:明明有行锁,怎么突然就加了表锁?
前置知识
锁与索引
- 深入了解
- 翻译
- 解释
- 总结
MySQL中的锁机制是数据库面试中的难点之一。本文详细介绍了锁与索引的关系、释放锁时机、乐观锁与悲观锁、行锁与表锁、共享锁与排它锁、意向锁以及记录锁、间隙锁和临键锁等多个方面。通过深入浅出的解释,帮助读者全面了解了MySQL中锁的原理和应用。文章还提供了面试准备建议,包括收集公司内部锁使用案例和基本面试问题的回答建议。读者可以通过本文快速了解MySQL锁机制,为面试做好准备。文章内容丰富,涵盖了MySQL锁的各个方面,对于想要深入了解数据库锁优化的读者来说是一份宝贵的资料。 文章还提供了两个复杂的亮点方案:临键锁引发的死锁和弃用悲观锁。通过这些案例,读者可以更深入地了解锁机制的复杂性和优化方法。最后,文章提出了两个思考题,鼓励读者分享自己在公司优化锁的案例以及使用乐观锁的经验,为读者提供了思考和交流的机会。 总之,本文通过详细解释MySQL中的锁机制和提供实际案例,为读者提供了全面了解和深入学习数据库锁优化的机会。读者可以通过本文快速了解MySQL锁机制,为面试做好准备,并且可以深入学习锁机制的复杂性和优化方法。
《后端工程师的高阶面经》,新⼈⾸单¥59
全部留言(31)
- 最新
- 精选
- 子休研究过一段时间锁的机制。举几个点,来分享一下如何理解临键锁。 首先这个名词“临键”非常拗口难记,但是大家仔细观察它的英文“next-key lock”,就可以发现一些名堂,我个人认为,所谓next-key的意思就是下一个索引的意思,也就是锁住查询结果中的最大索引值与下一个索引值之间的区域。这就意味着,临键锁锁住的最后的那个区间,是当前命中的索引最大值到下一个索引的区间,如果没有下一个索引,那就是锁住了剩下所有区间。结合本文的例子,大家就容易理解了。 例子1:如果 id 只有(1,4,7)三条记录,你查的是where id = 3,虽然没有查到记录,但是由于innodb中RR级别会使用临键锁,于是临键锁要开始锁区间了,但是锁哪里呢?这时候就要理解“临键”了,就是“next-key”,那么"next-key"是谁呢,根据查询条件ID=3,那么3后面的下一个索引是几呢?是4!! 那么临键锁就将(1,4]锁住了。 另外要额外提一句,由于查询条件可能是区间查询,所以临键锁会锁住多个区间。 比如查询条件 id>1 and id <6 它就会把(1, 4],(4,7]这两个区间都锁住。 又比如查询条件是id >1 and id<9 它就会把(1, 4],(4,7],(7, +∞]这三个区间都锁住,换句话说,这种查询也就导致了你根本插入不了任何一条记录,因为它把 id从1到无穷的范围都给锁住了。 为什么要锁住区间?因为要防止幻读出现(幻读就是同一事务里面,同一个sql查询查出来的记录行数不一样。为什么会不一样?因为有别的事务在你执行sql的时候进行了插入,插入到了你的查询条件范围内了,导致你上一次查还好好的,下一次查就莫名奇妙多出来记录了。)。 所以,你想,临键锁把你查询条件范围的区间锁住了,其它事务想往区间里面插数据是不是就不行了?临键锁是根据你的查询条件来锁区间的,这样你在同一事务里反复执行同一条sql查询,是不是就不会出现幻读了。 以上是个人浅见,欢迎指正。
作者回复: 赞!我也无力吐槽临键锁这个翻译,但是大家都用我也跟着用。
2023-07-19归属地:上海39 - penbox《乐观锁与悲观锁》部分是不是有个BUG? “悲观锁是指在写入数据时直接加锁”,我觉得应该是“悲观锁是指在获取数据时直接加锁”
作者回复: 可能是我这里因为要突出和上一条乐观锁的对比,让你产生了误解。应该是,悲观锁不管读写都要直接加锁。
2023-07-12归属地:四川4 - 陈斌意向锁除了变更表结构的例子,还是有其他的例子吗?毕竟意向锁有这么多的好处:使用意向锁能够提高数据库的并发性能,并且避免死锁问题。 SQL语句中怎么手动使用意向锁?
作者回复: 遗憾的是,你并不能手动指定用意向锁,这个是 MySQL 来控制的。
2023-07-19归属地:广东21 - humor举个例子,如果数据库中只有 id 为(1,4,7)的三条记录,也就是 id= 3 这个条件没有命中任何数据,那么这条语句会加上间隙锁,而且是在 (-∞,1)、(1,4)、(7,+∞) 这些地方都加上间隙锁。所以你可以看到,在生产环境里面遇到了未命中索引的情况,对性能影响极大。 这个查询只会扫描到记录1和4吧,为什么7以后也加了间隙锁呢
作者回复: 写错了,我修正一下!感谢指正!
2023-07-12归属地:浙江21 - rrbbt之前写代码,事物里面,select语句从来不在后面加for update结尾。这样会有什么问题吗?
作者回复: 如果你不加 for update 的话,正常来说是根据隔离级别,用 MVCC 的机制来读取数据。
2023-07-12归属地:山东31 - 我好像一点都不像程序员默默翻出尘封已久的高性能MYSQL...
作者回复: 哈哈哈,看了又忘,忘了又看,我也是。经典咏流传
2023-07-12归属地:广东21 - 起风了老师 是怎么记忆这些锁知识的
作者回复: 每次面试之前背,背了赶紧去面试,面完就忘了。DEBUG 要用的时候再掏出来=。=
2024-01-03归属地:浙江 - Geek_035c60当线程 1 想要执行插入的时候,它想要获得 id = 79 的行锁。当线程 2 想要执行插入的时候,它想要获得 id = 80 的行锁,这个时候就会出现死锁。因为线程 1 和线程 2 同时还在等着对方释放掉持有的间隙锁。 这里的图中,临时键 ==> 临键锁。
作者回复: 感谢,比心!
2023-11-15归属地:北京 - Geek_035c60“临键锁和数据库隔离级别的联系最为紧密,它可以解决在可重复读隔离级别之下的幻读问题。” 解决幻读问题,应该是间隙锁吧。
作者回复: 你这样说也可以,临键锁本身也包含了间隙锁。
2023-11-15归属地:北京 - Geek_035c60记录锁,是不是就是行锁呀?如果是的话,为什么这里需要使用两个概念?如果不是的话,记录锁与行锁的区别是什么呢?
作者回复: 我觉得这些概念就是从不同的角度来说。行锁相对应的是表锁,记录锁的话,我觉得应该可以看成是行锁,没太大的区别。
2023-11-15归属地:北京