当前位置: 首页 > news >正文

Java面试: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是无法插入进去的,所以导致了上面两张图的结果。

现在你知道间隙锁是怎么回事了吗?如果还有不明白的,可以在评论区留言讨论哦。

 *威哥Java学习交流Q群:691533824
加群备注:CSDN推荐
     

相关文章:

  • Android 不允许在子线程中更新 UI ,你有想过这是为什么吗?
  • Numpy数组中的运算与拼接,看这篇就够了
  • Docker网络模型
  • U9二次开发之补丁制作
  • 数字孪生与元宇宙相比有何区别?
  • java计算机毕业设计计算机散件报价系统源码+数据库+系统+lw文档+mybatis+运行部署
  • Qt Quick/QML入门到精通_专栏demo对应文章目录(目前27个demo/长期更新)
  • Java并发 | 17.[锁机制] 重量级锁(Monitor+自旋锁)
  • 【我拥有的书】
  • MSP432P 汇编,C语言点灯
  • Tomcat部署及优化
  • Kubernetes中Pod容器的使用
  • BERT模型解析
  • Springboot整合dubbozookeeper为注册中心
  • Spark的部署与使用
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • Angular2开发踩坑系列-生产环境编译
  • css选择器
  • exif信息对照
  • express如何解决request entity too large问题
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • java多线程
  • TypeScript迭代器
  • WebSocket使用
  • 大主子表关联的性能优化方法
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 利用jquery编写加法运算验证码
  • 微信开放平台全网发布【失败】的几点排查方法
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 小而合理的前端理论:rscss和rsjs
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • (145)光线追踪距离场柔和阴影
  • (二)fiber的基本认识
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • .gitattributes 文件
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .Net6 Api Swagger配置
  • [2016.7 day.5] T2
  • [AAuto]给百宝箱增加娱乐功能
  • [CSS]浮动
  • [Docker]十二.Docker consul集群搭建、微服务部署,Consul集群+Swarm集群部署微服务实战
  • [Excel] vlookup函数
  • [GDMEC-无人机遥感研究小组]无人机遥感小组-000-数据集制备
  • [IE技巧] 让IE 以全屏模式启动
  • [iOS]-NSTimer与循环引用的理解
  • [JDK工具-2] javap 类文件解析工具-帮助理解class文件,了解Java编译器机制
  • [linux] git lfs install 安装lfs
  • [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞
  • [Mac软件]Goldie App v2.2 Mac黄金比例设计工具
  • [python]mysqlclient常用命令
  • [uart]3.tty驱动分析