MySQL核心知识学习之路(7)
作为一个后端工程师,想必没有人没用过数据库,跟我一起复习一下MySQL吧,本文是我学习《MySQL实战45讲》的总结笔记的第七篇,总结了MySQL是如何解决幻读的。
上一篇:MySQL核心知识学习之路(6)
1 关于幻读
我们都知道MySQL的默认隔离级别是可重复读(点此复习MySQL的事务隔离),它仍然存在一个问题:幻读。

啥是幻读?
幻读指在同一个事务中,存在前后两次查询同一个范围的数据,但是第二次查询却看到了第一次查询没看到的行。
啥时候会出现幻读?
事务的隔离级别为可重复读,并且是当前读。
select * from t where id =1; -- 属于快照读。
select * from t where id =1 for update; -- 属于当前读。
一般情况下,幻读仅指新插入的行。
为何会出现幻读?
因为行锁只能锁定存在的行,针对新插入的操作没有限定。
幻读会带来啥问题?
对行锁语义的破坏 和 破坏了数据一致性。
如何解决幻读呢?
最简单的方法就是:升级事务隔离级别到可串行化,但这会让MySQL失去并发处理能力。
加之现有的行锁也解决不了幻读,因为即使锁住所有记录,还是阻止不了插入新数据。
所以,MySQL InnoDB引擎创造了一种新的锁,目的是锁住记录之间的“间隙”,且看下一部分的介绍。
2 间隙锁(gap lock)
啥是间隙锁?
顾名思义,间隙锁,锁的就是两个值之间的空隙。
比如下图所示的某张表t,在该表主键索引(id)上插入了6个记录(0,5,10,15,20,25),因此产生了7个间隙。
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB; insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

图片来源:林晓斌《MySQL实战45讲》
间隙锁是专门用于解决幻读这种问题的锁,它锁了行与行之间的间隙,这样就能够阻塞新插入的操作。
因此,划重点:当MySQL InnoDB引擎在一行行扫描的过程中,不仅会给行加上行锁,还会给行的两边的空隙也加上间隙锁。
补充:间隙锁之间是不冲突的,跟间隙锁存在冲突关系的只是“往这个间隙中插入一个记录”的操作。
注意事项
间隙锁在可重复读级别下才是有效的(换句话说,如果调整隔离级别为读提交就没有间隙锁了)。
间隙锁的引入也带来了一些新的问题,比如:降低并发度,可能导致死锁。
3 next-key lock
由于间隙锁(gap lock)仍在存在一些问题,可能会降低并发度和仍然可能导致死锁。因此,MySQL InnoDB为间隙锁引入了一个补充:next-key lock。
那么,问题来了:啥是next-key lock?
所谓next-key lock,它是间隙锁和行锁的合体,每个next-key lock都是前开后闭区间,如 (0,5]。
间隙锁都是开区间,如 (0,5)。
next-key lock帮助MySQL在默认隔离级别下解决了幻读问题,因此它也是MySQL加锁的基本单位。
MySQL加锁的原则
(1)加锁的基本单位是 next-key lock
(2)查找过程中访问到的对象才会加锁
该原则适用的前提条件为:
MySQL版本:5.x系列<=5.7.24,8.0系列<=8.0.13,且只有在可重复读隔离级别下(切换到读提交的话就只剩下行锁了)。
MySQL加锁的优化
索引上的等值查询,如果是给唯一索引加锁,此时next-key lock 退化为行锁。
索引上的等值查询,如果不是唯一索引,需要向右遍历访问到第一个值不满足等值条件的时候,此时next-key lock 退化为间隙锁。
MySQL加锁的Bug
唯一索引上的范围查询会访问到第一个不满足条件的值为止。
4 小结
本文总结了MySQL的InnoDB引擎是如何解决幻读问题的,即通过 间隙锁 + 行锁组成的next-key lock来实现的。
参考资料
林晓斌(丁奇),《MySQL实战45讲》
扫码订阅《MySQL实战45讲》


MySQL核心知识学习之路(7)的更多相关文章
- 零基础的学习者应该怎么开始学习呢?Python核心知识学习思维分享
近几年,Python一路高歌猛进,成为最受欢迎的编程语言之一,受到无数编程工作者的青睐. 据悉,Python已经入驻部分小学生教材,可以预见学习Python将成为一项提高自身职业竞争力的必修课.那么零 ...
- MySQL索引知识学习笔记
目录 一.索引的概念 二.索引分类 三.索引用法 四 .索引架构简介 五.索引适用的情况 六.索引不适用的情况 继我的上篇博客:Oracle索引知识学习笔记,再记录一篇MySQL的索引知识学习笔记,本 ...
- MYSQL+PHP的学习之路
MYSQL+PHP 先从MYSQL开始吧 第一步:SQL语句基础 1.书籍 2.网站: 这个网站在线测试和考试http://sqlzoo.net/wiki/SELECT_basics/zh 3.学习过 ...
- mysql 核心知识要点
整体知识介绍:mysql基本操作和使用,mysql优化(索引,分表等),mysql部署(读写分离,负载均衡等) 数据库基本介绍:数据库概念,常用数据库,web应用三大软件分工,PHP动态语言特点(处理 ...
- MySQL核心知识
MySQL常用的命令 启动:net start mySql; 进入:mysql -u root -p/mysql -h localhost -u root -p databaseName; 列出数据库 ...
- Webwork 学习之路【03】核心类 ServletDispatcher 的初始化
1. Webwork 与 Xwork 搭建环境需要的的jar 为:webwork-core-1.0.jar,xwork-1.0.jar,搭建webwork 需要xwork 的jar呢?原因是这样的,W ...
- MySQL学习之路(一)——初涉MySQL。
MySQL学习之路(一) 1.1MySQL的概述 MySQL由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一个开源的关系型数据库管理系统. MySQL分为社区版和企业版. 1 ...
- Docker 与 K8S学习笔记(二)—— 容器核心知识梳理
本篇主要对容器相关核心知识进行梳理,通过本篇的学习,我们可以对容器相关的概念有一个全面的了解,这样有利于后面的学习. 一.什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,使应用程序可以在 ...
- 阿里封神谈hadoop学习之路
阿里封神谈hadoop学习之路 封神 2016-04-14 16:03:51 浏览3283 评论3 发表于: 阿里云E-MapReduce >> 开源大数据周刊 hadoop 学生 s ...
- 13本热门书籍免费送!(Python、SpingBoot、Entity Framework、Ionic、MySQL、深度学习、小程序开发等)
七月第一周,网易云社区联合清华大学出版社为大家送出13本数据分析以及移动开发的书籍(Python.SpingBoot.Entity Framework.Ionic.MySQL.深度学习.小程序开发等) ...
随机推荐
- 常见的 AI 模型格式
来源:博客链接 过去两年,开源 AI 社区一直在热烈讨论新 AI 模型的开发.每天都有越来越多的模型在 Hugging Face 上发布,并被用于实际应用中.然而,开发者在使用这些模型时面临的一个挑战 ...
- 抽象类和接口的对比、及各自的使用场景--java进阶day02
1.区别 2.各自的使用场景 1.抽象类的使用场景 如图,有三个类,其中存在共性,我们就会写一个父类并抽取出共性的东西,但有的方法难免会描述不清,所以我们就将其写为了抽象方法,抽象方法又得存在于抽象类 ...
- DevOps工程师技能
技术背景 DevOps工程师必须持有计算机科学.工程或其他相关领域的学位.2年以上工作经验.这包括开发人员.系统管理员或devops驱动的团队成员的工作.这是一个重要的需求,同时也是对所有IT操作的理 ...
- P3392 涂国旗 题解
题目大意 题目真的是不说人话...... 有一个国家的国旗是由一个 N * M 的方格组成的.如果想要这面国旗合法,就必须满足要求: 国旗从上到下必须是白色.蓝色和红色,顺序不能改变. 每一种颜色都至 ...
- Chrome 135 版本开发者工具(DevTools)更新内容
Chrome 135 版本开发者工具(DevTools)更新内容 一.性能(Performance)面板改进 1. 性能面板中的配置文件和函数调用现已显示来源和脚本链接 Performance > ...
- java基础之成员变量和局部变量区别
1:在类中的位置不同 成员变量:类中,方法外 局部变量:方法中,或者方法声明上(形参) 2:作用范围不一样 成员变量:类中 局部变量:方法中 3:初始化值的不同 成员变量:有默认值 局部变量:没有默认 ...
- React AntD的Dropdown组件报错:React.Children.only expected to receive a single React element child.可能的n原因
React.Children.only expected to receive a single React element child. Error: React.Children.only exp ...
- wpf 打开输入法、禁用输入法
1 <StackPanel Margin="10"> 2 <TextBox Text="默认"></TextBox> 3 & ...
- CF1740C题解
众所周知,这道题的难度是 1400,所以是简单题. 分析 首先,坚信这是一道简单题,所以不要想复杂了. 首先我们需要对 aaa 数组排序,这点是肯定的,为啥应该不用我解释. 下面,我们假设 p1, ...
- 【经验】Git|Windows下如何管理和部署多个Git账号的SSH密钥文件
生成 SSH 密钥 先打开一个git窗口,生成ssh密钥. 如果打开的不是git窗口,而是cmd窗口,则需要先切换到C:\Users\用户名\.ssh目录下. 下面这条指令的your_email和yo ...