作为一个后端工程师,想必没有人没用过数据库,跟我一起复习一下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讲》

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

MySQL核心知识学习之路(7)的更多相关文章

  1. 零基础的学习者应该怎么开始学习呢?Python核心知识学习思维分享

    近几年,Python一路高歌猛进,成为最受欢迎的编程语言之一,受到无数编程工作者的青睐. 据悉,Python已经入驻部分小学生教材,可以预见学习Python将成为一项提高自身职业竞争力的必修课.那么零 ...

  2. MySQL索引知识学习笔记

    目录 一.索引的概念 二.索引分类 三.索引用法 四 .索引架构简介 五.索引适用的情况 六.索引不适用的情况 继我的上篇博客:Oracle索引知识学习笔记,再记录一篇MySQL的索引知识学习笔记,本 ...

  3. MYSQL+PHP的学习之路

    MYSQL+PHP 先从MYSQL开始吧 第一步:SQL语句基础 1.书籍 2.网站: 这个网站在线测试和考试http://sqlzoo.net/wiki/SELECT_basics/zh 3.学习过 ...

  4. mysql 核心知识要点

    整体知识介绍:mysql基本操作和使用,mysql优化(索引,分表等),mysql部署(读写分离,负载均衡等) 数据库基本介绍:数据库概念,常用数据库,web应用三大软件分工,PHP动态语言特点(处理 ...

  5. MySQL核心知识

    MySQL常用的命令 启动:net start mySql; 进入:mysql -u root -p/mysql -h localhost -u root -p databaseName; 列出数据库 ...

  6. Webwork 学习之路【03】核心类 ServletDispatcher 的初始化

    1. Webwork 与 Xwork 搭建环境需要的的jar 为:webwork-core-1.0.jar,xwork-1.0.jar,搭建webwork 需要xwork 的jar呢?原因是这样的,W ...

  7. MySQL学习之路(一)——初涉MySQL。

    MySQL学习之路(一) 1.1MySQL的概述 MySQL由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一个开源的关系型数据库管理系统. MySQL分为社区版和企业版. 1 ...

  8. Docker 与 K8S学习笔记(二)—— 容器核心知识梳理

    本篇主要对容器相关核心知识进行梳理,通过本篇的学习,我们可以对容器相关的概念有一个全面的了解,这样有利于后面的学习. 一.什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,使应用程序可以在 ...

  9. 阿里封神谈hadoop学习之路

    阿里封神谈hadoop学习之路   封神 2016-04-14 16:03:51 浏览3283 评论3 发表于: 阿里云E-MapReduce >> 开源大数据周刊 hadoop 学生 s ...

  10. 13本热门书籍免费送!(Python、SpingBoot、Entity Framework、Ionic、MySQL、深度学习、小程序开发等)

    七月第一周,网易云社区联合清华大学出版社为大家送出13本数据分析以及移动开发的书籍(Python.SpingBoot.Entity Framework.Ionic.MySQL.深度学习.小程序开发等) ...

随机推荐

  1. 常见的 AI 模型格式

    来源:博客链接 过去两年,开源 AI 社区一直在热烈讨论新 AI 模型的开发.每天都有越来越多的模型在 Hugging Face 上发布,并被用于实际应用中.然而,开发者在使用这些模型时面临的一个挑战 ...

  2. 抽象类和接口的对比、及各自的使用场景--java进阶day02

    1.区别 2.各自的使用场景 1.抽象类的使用场景 如图,有三个类,其中存在共性,我们就会写一个父类并抽取出共性的东西,但有的方法难免会描述不清,所以我们就将其写为了抽象方法,抽象方法又得存在于抽象类 ...

  3. DevOps工程师技能

    技术背景 DevOps工程师必须持有计算机科学.工程或其他相关领域的学位.2年以上工作经验.这包括开发人员.系统管理员或devops驱动的团队成员的工作.这是一个重要的需求,同时也是对所有IT操作的理 ...

  4. P3392 涂国旗 题解

    题目大意 题目真的是不说人话...... 有一个国家的国旗是由一个 N * M 的方格组成的.如果想要这面国旗合法,就必须满足要求: 国旗从上到下必须是白色.蓝色和红色,顺序不能改变. 每一种颜色都至 ...

  5. Chrome 135 版本开发者工具(DevTools)更新内容

    Chrome 135 版本开发者工具(DevTools)更新内容 一.性能(Performance)面板改进 1. 性能面板中的配置文件和函数调用现已显示来源和脚本链接 Performance > ...

  6. java基础之成员变量和局部变量区别

    1:在类中的位置不同 成员变量:类中,方法外 局部变量:方法中,或者方法声明上(形参) 2:作用范围不一样 成员变量:类中 局部变量:方法中 3:初始化值的不同 成员变量:有默认值 局部变量:没有默认 ...

  7. 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 ...

  8. wpf 打开输入法、禁用输入法

    1 <StackPanel Margin="10"> 2 <TextBox Text="默认"></TextBox> 3 & ...

  9. CF1740C题解

    众所周知,这道题的难度是 1400,所以是简单题. 分析 首先,坚信这是一道简单题,所以不要想复杂了. 首先我们需要对 aaa 数组排序,这点是肯定的,为啥应该不用我解释. 下面,我们假设 p1,   ...

  10. 【经验】Git|Windows下如何管理和部署多个Git账号的SSH密钥文件

    生成 SSH 密钥 先打开一个git窗口,生成ssh密钥. 如果打开的不是git窗口,而是cmd窗口,则需要先切换到C:\Users\用户名\.ssh目录下. 下面这条指令的your_email和yo ...