MySQL间隙锁是什么鬼?
一. 写在前面的话
当下各行各业都卷到飞起,IT行业更是如此。对很多程序员来说,面试的难度、深度、广度,都让你承受着 "你这个年纪不该承受的一切"。以MySQL为例,我大学刚毕业那会,面试时也就问一下 "MySQL查询怎么去重?"、"MySQL组函数有哪些?";而现在刚毕业的学生去面试,上来就是 "聊聊MySQL的架构吧"、"你看过MySQL的源码没有?"。现在想想还真是庆幸自己毕业的早,以那时大学毕业的水平拿到现在找工作,估计得饿死。
存储(数据库存储或者内存存储)是所有系统中最最重要的一个部分,它们提供了任何系统运行所需要的所有数据,程序员几乎每日的工作都是直接或者间接地与各种存储打交道。正因如此,存储必然更是面试时的 "重灾区"。
二. MySQL间隙锁
我第一次听到MySQL的间隙锁,还是在2016年去一家公司面试的时候,整个过程还是非常愉快与顺利的。但面试那哥们儿突然问了一句, "你知道MySQL的间隙锁吗?",我脑子中迅速提取各种锁:"悲观锁"、"乐观锁"、"行锁"、"表锁"、"悲观锁"、"乐观锁"......阿xi吧,间隙锁是个什么鬼?!
然后我只能无奈地回答道:"这个我不是很清楚了",然后面试就结束了.......从那个公司出来后,我就坐的花坛边,用手机各种查,各种搜,才对间隙锁有了初步的了解,在未来几天里我就一直花时间来深入地理解间隙锁。
笔者认为,要想深入理解某个概念,必须得搞明白这个东西它出现的意义在哪里?它到底是为了解决什么问题而产生的?然后带着这些疑问去寻找答案,当谜底一层层的解开,你会觉得神清气爽,整个人都会觉得精神抖擞。
我在给大家在解答什么是间隙锁,及其能够解决什么问题之前,会先带各位捋清一些相关知识:事务的隔离级别以及快照读和当前读。
2.1 事务的隔离级别
事务的隔离级别有四种,以及每种隔离级别会产生的问题,都如下表所示:
有些人可能会问了,间隙锁与隔离级别有什么关系呢?其实间隙锁的出现,就是为了解决InnoDB存储引擎中,可重复读在当前读中产生的幻读问题!
2.2 快照读与当前读
2.2.1 快照读
在讲解快照读之前,我们先来看看笔者的一段SQL操作。
我们知道,MySQL的默认隔离级别是可重复读。按照红色标注的序号,并没有出现幻读问题,这是什么原因呢?这是因为MySQL通过快照读,解决了可重复读这种隔离级别情况下的幻读问题!那什么又是快照读呢?
快照读,简单点来说就是数据有很多个版本,事务在并发执行的时候,某个事务读取到的是其中一个快照。笔者再用一个可能不是很贴切但比较好理解的例子来给大家说明,就是事务或者查询开始的时候,针对要查询的数据生成一些副本,然后在后续的查询中获取的是该副本的数据。
2.2.2 当前读
当前读的意思是,查询到的永远是数据库中最新的数据,没有快照。适用如下这些语句:
select ... from table_name in share mode;
select ... from table_name for update;
insert;
update;
delete
2.3 间隙锁
在 2.1 事务的隔离级别 章节中我们提过,间隙锁是为了解决InnoDB存储引擎中可重复读导致的幻读问题,那么到底什么是间隙锁呢?我们先看如下的操作:
针对图中的第二条查询SQL语句:
select * from foo where id < 10 and id > 5 for update;
笔者提出两个问题:
该SQL很明显是当前读,而当前读读取的是数据库中最新的数据。那么现在有个问题,此时如果另外有一个事务插入一条id为8的数据,再执行相同的SQL语句,是否就不会出现幻读了吗?
如果问题1的结果是没有出现幻读,肯定是通过锁机制,那么这又是如何上锁的?那么如果插入的id分别为8、12、17的数据,又会出现什么现象呢?id为12、17并不会让查询结果产生幻读吗?
针对问题一,如下图所示:
我们知道,当前读读取的是数据库中最新的数据。右侧的数据如果能提交的话,左侧的查询必然会产生幻读问题,所以会通过上锁的方式阻止事务的提交,而这个锁就是间隙锁。当你理解了问题二,我深信你一定会明白什么是间隙锁。
针对问题一,依次观察如下两张图:
出现上面两图结果的原因在于,因为 foo表中的数据id为1、4、7、9、15、18,当查询id在(5,10)之间的时候,锁的并不是整个数据库表,而是查找离下限(5)最大的id值和上限(10)最小的id值,分别为4和15;然后锁的区间范围为(4,15],也就是说处于这个区间的id是无法插入进去的,所以导致了上面两张图的结果。
现在你知道间隙锁是怎么回事了吗?如果还有不明白的,可以在评论区留言讨论哦。当然,你也可以加入到我们的学习交流群,和大家一起来互动学习哦。
猜你喜欢LIKE
相关推荐HOT
更多>>javabean是什么?
在Java中,JavaBean是一种符合特定规范的普通Java类,用于封装数据和提供操作数据的方法。JavaBean是一种重要的设计模式,用于实现面向对象编程...详情>>
2023-06-06 16:27:20java零基础入门到精通怎么学?
Java是一门广泛应用于企业级开发和大型应用程序的编程语言。要从零基础入门到精通Java,需要以下步骤和建议:1.学习基础知识:开始学习Java编程...详情>>
2023-06-05 17:02:00token是什么意思
Token是“令牌”的意思,它通常被用于身份验证和授权。在计算机系统中,当用户通过身份验证后,系统会颁发一个Token给用户,用于标识用户身份和...详情>>
2023-04-20 10:57:41虚函数的作用和实现原理
在父类中声明虚函数:在父类中通过在函数声明前加上 virtual 关键字来声明一个虚函数。需要注意的是,虚函数的使用需要谨慎,因为虚函数的调用...详情>>
2023-04-14 14:20:27