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

【MySQL】可重复读级别下基于Next Key Lock解决幻读

昨天读到了一篇文章[1],里面讲,面试官说mysql的可重复读级别下有解决幻读的方式,最后公布了答案,是在sql后面加for update。这么说倒是没错,但是这种问法给我一种奇怪的感觉,因为for update无论在哪个隔离级别下,都能提供x锁进行锁定防止幻读,而next key lock,是x锁的三种实现算法之一,next key lock,也不应该翻译为间隙锁。下面我们一一讲来。

一,mysql的锁

mysql的锁,

按照读或写,分成s锁和x锁

按照锁的范围,分成表锁和行锁

按照意向锁的读或写,分成is锁和ix锁。其中is锁和ix锁是表锁,但不是真的用排他锁锁表,而是一种共享锁,旨在告诉其他线程表中有s锁或者x锁;而s锁和x锁是真的加了排他锁,s锁是对读共享对写排他,x锁是对其他线程的任何操作都排他,且s锁和x锁都是行锁。

而最后一个,mysql行锁的三种算法。

行锁(Record Lock),只锁单行记录本身。

间隙锁(Gap Lock),锁住记录两边的记录,但是对记录本身,不加锁。

临键锁(Next Key Lock),即锁住记录本身,也锁住记录两边,这种锁的范围是左闭右开。还有一种锁,叫做Previous Key Lock,和Next Key Lock类似,区别只是锁的范围左开右闭。它们都来自于谓词锁,即锁住满足某一查询条件的所有数据项,它不仅包括当前在数据库中满足条件的记录,也包括即将要插入,更新或删除到数据库并满足查询条件的数据项。

下图来自《MySQL技术内幕 InnoDB存储引擎》一书。
在这里插入图片描述
在这里插入图片描述

第一个需要清晰指出的误区是,Next Key Lock翻译为临键锁[2],而不是间隙锁。next意为下一个,key意为键;而gap指空挡、间隙,因此Gap Lock才是间隙锁。

第二个误区是,Next Key Lock确实能够解决幻读问题,但是不止在可重复读(rr)级别下,你在所有级别下,在sql后面加for update都能施加x锁(有时是临键锁有时是行锁,这个后面讲)解决幻读问题。

二,mysql解决并发问题的机制

mysql有两种解决并发问题的机制,一种叫做基于一致性的非锁定读(Multi Version Concurrent Control, MVCC),也叫快照读;另一种叫做基于一致性的锁定读(Lock Based Concurrent Control, LBCC)也叫当前读

mysql四种隔离级别,读未提交,就是没有并发控制;读已提交和可重复读默认走的MVCC;串行化走的LBCC;但是不管哪个级别,加了lock in share mode(s锁)和for update(x锁)都是走的LBCC了。

简单来说,读已提交和可重复读不加锁走MVCC,加锁走LBCC。串行化就走LBCC没法走MVCC;读未提交默认没并发控制,加了所走LBCC,不过这种级别应该也应用不广。

MVCC其实就是不直接读取记录本身,只读写操作形成的undo log,undo log其实就是一种数据快照,其中包括记录所有数据,此外还多了一个指向其他undo log的指针(roll_ptr)和生成此undo log的事务id(trix_id),因此MVCC被称为快照读。这些不同事务写操作的undo log形成一个undo log链表,在查询的时候事务去undo log链表中进行查询,读已提交和可重复读的区别就是,读已提交每次查询都生成一个ReadView,而可重复读只有第一次查询生成一个ReadView。ReadView如何控制查询和解决不可重复读问题的,可以看往期文章[3]。

LBCC是直接去读取记录本身,这个没有什么好说的。

需要特别说明的是,MVCC和LBCC都是针对读请求的并发机制,对于写请求,会直接对要修改的行加锁进行操作,写操作在事务中会形成undo log并不持久化到硬盘,事务提交后持久化到硬盘并删除无用的undo log。

三,Next Key Lock如何解决幻读问题

要知道Next Key Lock如何解决幻读问题,首先要知道什么是幻读。幻读问题,简单的说就是a事务进行了两次相同的查询,第二次查询结果比第一次多了一些结果,原因是b事务在a事务两次查询中间,向其查询范围内插入了数据并提交,导致a事务第二次查询范围内多出了这些b事务提交的数据。好,接下来我们看一下例子。

假设有这样的一个sql,其中a是辅助索引,a的值有1、3、5、8、10。

select * from t where a = 5 for update;

由于加了x锁,走的LBCC,x锁的具体实现为临键锁,锁住(3, 5)+5+(5,8),即(3,8)。为什么使用临键锁锁住一整个区域呢,用行锁Record Lock只锁住一行不行吗,毕竟我们的查询条件只是a=5。

答案是不行。行锁的定义就是只锁住一行,而且a是辅助索引,并非唯一索引,意味着a=5可能有多行,只靠Record Lock锁不住多行a=5的记录。不仅如此,还有可能新插入的a=5的记录插入在原本a=5索引的最左侧或最右侧,因此要使用Next Key Lock锁住接近a=5的所有索引值对应的记录。即(3, 5)范围内有可能插入一个新的a=5的记录,(5,8)范围内也有可能插入一个新的a=5的记录,因此要锁住临近a=5的一整个范围。整个可能被插入的范围都被锁住,那么新插入数据的可能性就不存在了,幻读因此不可能出现。

至此,我们解释了为什么不能直接使用行锁来加锁,也解释了临键锁为什么能防止幻读。

四,Next Key Lock降级为Record Lock

前面我们解释了为什么普通索引要使用临键锁。其实还有一种情况,即等值查询时,使用的索引是唯一索引,那么Next Key Lock会被mysql降级为Record Lock。

因为唯一索引的数据是唯一的,不管查找的唯一索引的数据有或者没有,都只需要锁住一行即可,使用行锁锁住一行就能锁住等值查询的要找的那一条记录。

五,没有LBCC,可重复读只靠默认的MVCC能解决幻读问题吗

在可重复读级别下,只靠MVCC能够防止幻读吗?先说答案,部分情况下能,部分情况下,不能。

1,能防止幻读的情况

先说一下能防止幻读的原因。a事务进行了两次相同的查询,b事务在这两次查询中间,插入了在a事务查询范围内的数据,并提交,导致a事务第二次查询比第一次查询多出了数据,这就是幻读,两次相同的查询但是结果不一样,多了数据。

出现这种幻读的情况下,分为两种情况,事务b比事务a早开启,和事务b比事务a晚开启。

(1)假设事务b比事务a早开启,在事务a两次查询中间提交。

那么事务a第一次查询时生成了一个ReadView,在事务a第二次查询时,还会使用这个ReadView去进行查询(因为是可重复读级别下)。首先事务a会发现根据这个ReadView,事务b的trx_id在ReadView的min_trx_id和max_trx_id之间,表示事务b可能是活跃的事务,是不是还需要查看m_ids列表;

第二步,其中的m_ids列表(包括了生成ReadView时所有活跃的事务id)会包含事务b的trx_id,因此会认为事务b还是一个活跃事务,活跃事务的数据属于脏数据,因此不会被事务a读取。

注,ReadView的使用规则,查看文章[3]。

(2),假设事务b比事务a晚开启,在事务a两次查询中间提交。则事务b在提交数据后生成的undo log的trx_id就是事务b的trx_id,事务b要比事务a晚开启,意味着事务b的trx_id比事务a第一次查询时生成的ReadView的max_trx_id要大,则事务a在第二次查询时,可以通过ReadView知道,事务b是生成ReadView以后才开启,则事务a不会读取将来的数据。

两种情况列举下来,均可以避免幻读。

2,不能防止幻读的情况

那么什么时候不能防止幻读呢?在防止幻读时举的例子如下:
a事务进行了两次相同的查询,b事务在这两次查询中间,插入了在a事务查询范围内的数据,并提交,导致a事务第二次查询比第一次查询多出了数据

我们只需要在事务a第二次查询数据前,对事务b提交的数据做修改,然后再进行事务a的第二次查询。只用添加这么一步,就会出现幻读。

这是因为update本身不会根据MVCC,具体说就是ReadView去查看是否可以修改,update本身是加悲观锁直接对记录进行修改的,也就是说在事务b插入并提交以后,事务a是可以找到这条数据并成功修改的,并因此生成了undo log,并且undo log的trx_id就是事务a自己。

此时事务a再进行第二次查询,事务a查到符合范围的数据中,有一个自己修改的undo log快照,符合条件,于是就作为结果展示出来了,因此产生了幻读。

以上,就是关于可重复读、MVCC、LBCC、临键锁、间隙锁的一些解释。

参考文章:
[1],Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
[2],详解 MySql InnoDB中的三种行锁(记录锁、间隙锁与临键锁)
[3],【MySQL】基于MVCC的RR、RC级别事务原理简述

相关文章:

【MySQL】可重复读级别下基于Next Key Lock解决幻读

昨天读到了一篇文章[1],里面讲,面试官说mysql的可重复读级别下有解决幻读的方式,最后公布了答案,是在sql后面加for update。这么说倒是没错,但是这种问法给我一种奇怪的感觉,因为for update无论在哪个隔离级…...

【安全性分析】正式安全分析与非正式安全分析

安全性分析-系列文章目录 第一章 【安全性分析】正式安全分析与非正式安全分析 第二章 【安全性分析】BAN逻辑 (BAN Logic) 文章目录 安全性分析-系列文章目录前言一、正式安全分析1. 理想化模型(如随机预言机模型)2. 标准模型(Standard Model)3. 形式化验证4. 数学证明二…...

【项目开发】高校思政课程实践任务平台—数据库设计

未经许可,不得转载。 文章目录 1、项目需求2、数据库选型3、概念数据模型设计3.1、实体及属性3.2、实体关系3.3、补充说明4、数据库语句4.1、数据库对象创建语句4.2、功能实现的SQL语句4.3、视图创建语句4.4、触发器创建语句5、安全性考虑5.1、用户认证和授权5.2、数据传输安全…...

计算机网络安全应该学习哪些知识?

计算机网络安全是一个广泛而深入的领域,要成为一名专业的网络安全专家,需要系统地学习多个方面的知识。以下是一些关键的学习方向: 一、基础知识计算机网络:学习OSI、TCP/IP模型,网络协议,网络设备工作原理…...

logrotate工具强制日志轮询

说明: 1、通过定时任务logrotate工具每天强制日志轮询并压缩,节省存储空间。 参数说明: 1)/opt/yolov5/logs/.log: 是指要轮转日志文件的路径和名称。 是一个通配符,表示匹配以*.log结尾文件名。 2)daily: 是指日志文件每天轮转一次。 3)dateext: 是指轮转的日志文件名中…...

微服务系列三:微服务核心——网关路由

目录 前言 一、登录存在的问题归纳 二、*微服务网关整体方案 三、认识微服务网关 四、网关鉴权实现 五、OpenFeign微服务间用户标识信息传递实现 六、微服务网关知识追问巩固 前言 本篇文章具体讲解微服务中网关的实现逻辑、用于解决什么样的问题。其中标题中标注* 涉…...

【系统架构设计师】2023年真题论文: 论边云协同的设计与实现(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2023年 试题4)解题思路边云协同概念和架构边云协同的关键技术边云协同的设计与实现案例分析论文素材参考真题题目(2023年 试题4) 边云协同是指将边缘计算和云计算相结合,实现边缘设备与云端资源之间…...

vue3记录(第一版)

vue2与vue3的区别 vue2属于选项式API,vue3属于组合式API setup概述 setup是vue3中一个新的配置项,值是一个函数,组件中所用到的数据,方法,计算属性,监视等等,均配置在setup中 vue3中的setup和vue2的data,methods之间有什么关系呢? 因为setup比data解析的早,所以在data中可以…...

R 语言数据导入与导出

R 语言数据导入与导出 数据的导入和导出是数据处理中的重要步骤。R 语言提供了多种方法来读取和写入不同格式的数据文件,包括 CSV、Excel、JSON、SQL 数据库等。本文将介绍如何在 R 语言中进行数据的导入和导出。 1. 导入数据 1.1 读取 CSV 文件 CSV(C…...

kubectl常用命令简介

在之前浅谈Kubernetes集群架构 中介绍了kube-apiserver是提供k8s对内或对外的api请求的唯一入口,本文介绍的 kubectl 是官方的CLI命令行工具,用于与 apiserver 进行通信,将用户在命令行输入的命令,组织并转化为 apiserver 能识别的…...

【小白学机器学习31】 大数定律,中心极限定理,标准正态分布与概率的使用

目录 1 正态分布相关的2个相关定理 1.1 大数定律:(证明了)分布的稳定性 1.2 中心极限定理:(证明了)分布的收敛性 2 使用标准差和概率的2种思路 2.1 标准正态分布的曲线 2.2 两种使用方式 2.3 第1种:按整数倍标准差δ 作为标准使用 2.…...

Go语言基础语法

一、创建工程 说明: (1)go.mod文件是go项目依赖管理文件,相当于前端的package.json,也就是Java项目中的Maven的pom.xml。 二、打印数据到控制台 (1)引入fmt (2)使用fmt…...

CSS层叠/CSS变量和!important的使用

layer components {:root {--theme: red;font-family: serif !important;} } CSS Layers CSS Layers 是一种用于管理和组织样式规则的新机制。它允许开发者定义不同的样式层,以便更好地控制样式的优先级和覆盖关系。通过使用 layer 规则,开发者可以将样…...

提升工作效率的小众神器

🤖宝子们,今天我要给大家分享五款超实用的小众工作软件,让你的工作事半功倍!😎 🌟亿可达 - 自动化办公神器 亿可达是一款自动化办公工具,无需编程知识就能搭建出各种自动化工作流程。界面清新…...

【Python+Pycharm】2024-Python安装配置教程

【PythonPycharm】2024-Python安装配置教程 一、下载装 Python 1、进入Python官网首页,下载最新的Python版本 Download Python | Python.org 选择对应版本下载 安装 测试安装情况 python如果安装失败 在系统环境变量添加安装路径 where pythonwin7安装路径添加…...

systemverilog中clocking的用法

文章目录 1.clocking简介2.clocking实例分析3.重点分析(1)bus定义是不是随便取名的(2)输入输出的定义原则是什么(3)到底如何消除了竞争和冒险(4)没用到的信号如何处理(5&…...

【Python开发】大模型应用开发项目整理

不知不觉已经入职3个月了,同事很好,工作充实,学到了很多东西,大大小小的需求也实现了接近20个。负责2个主要component,数据抓取和利用GenAI做数据提取。 1 背景 提取新闻中事件关键信息,比如人名&#xff…...

Redis 的使⽤和原理

第一章:初识 Redis 1.1盛赞 Redis Redis 是⼀种基于键值对(key-value)的 NoSQL 数据库,与很多键值对数据库不同的是,Redis 中的值可以是由 string(字符串)、hash(哈希)、list&…...

前端学Java

一:语法 1、注解 注解(Annotation)是Java中的一种特殊类型的语法,它可以被用来为代码提供元数据。元数据是关于数据的数据,注解可以用于类、方法、变量等的描述与标记。 理解注解可以从以下几个方面入手&#xff1a…...

VR游戏:多人社交将是VR的下一个风口

第一部分:创业笔记 1. 市场趋势 从单机游戏转向多人互动体验:随着技术的进步,VR游戏正从单机模式向多人互动体验转变。代表作品如Rec Room、Phasmophobia、Among Us和Breachers等,这些游戏的成功证明了多人互动模式的巨大潜力。…...

Docker与虚拟机(VM)的不同

Docker与虚拟机(VM)在实现的原理上存在显著的不同,主要体现在以下几个方面: 一、基础原理 Docker 利用Linux内核的特性,如容器(containers)、命名空间(namespaces)和控制…...

Pr 视频效果:透视

效果面板/视频效果/透视 Video Effects/Perspective Adobe Premiere Pro 的视频效果中,透视 Perspective效果组主要用于在二维平面的视频剪辑中模拟三维空间的透视效果。 通过调整这些效果,可以改变图像的视角、添加阴影、创造立体感,增强画面…...

C 语言标准库 - <limit.h>

简介 <limits.h> 是 C 标准库中的一个头文件&#xff0c;定义了各种数据类型的限制。这些宏提供了有关整数类型&#xff08;char、short、int、long 和 long long 等&#xff09;和其他数据类型的最大值和最小值的信息。 这些限制指定了变量不能存储任何超出这些限制的…...

Python | Leetcode Python题解之第519题随机翻转矩阵

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, m: int, n: int):self.m mself.n nself.total m * nself.map {}def flip(self) -> List[int]:x random.randint(0, self.total - 1)self.total - 1# 查找位置 x 对应的映射idx self.map.get(x,…...

大数据新视界 -- 大数据大厂之提升 Impala 查询效率:索引优化的秘籍大揭秘(上)(3/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

【AI工作流】FastGPT - 深入解析FastGPT工作流编排:从基础到高级应用的全面指南

文章目录 一、工作流编排概述二、FastGPT的节点类型1. 基础功能插件(1) 文本输出(2) 功能调用(3) 工具(4) 外部调用(5) 其他 2. 系统插件3. 团队插件 三、工作流中的流向结语 在当今快速发展的人工智能领域&#xff0c;工作流编排的能力已成为提升用户体验和应用效率的关键因素…...

VS+Qt解决提升控件后,包含头文件格式不对问题处理

一、前言 VSQt 提升控件后&#xff0c;在uic目录下会生成ui相关的初始化文件&#xff0c;对于提升的控件头文件包含的格式为#include<> 而非 #include “ ” 导致无法找到头文件。如果手动修改为 #include “ ”相当麻烦&#xff0c;甚至每次编译都要修改一遍&#xff0c…...

opencv - py_imgproc - py_filtering filtering 过滤-卷积平滑

文章目录 平滑图像目标2D 卷积&#xff08;图像过滤&#xff09;图像模糊&#xff08;图像平滑&#xff09;1. 平均2. 高斯模糊3. 中值模糊4. 双边滤波 其他资源 平滑图像 目标 学习&#xff1a; 使用各种低通滤波器模糊图像将定制滤波器应用于图像&#xff08;2D 卷积&…...

精华帖分享|缠论系列 -笔

本文来源于量化小论坛策略分享会板块精华帖&#xff0c;作者为吴奕萱&#xff0c;发布于2023年6月4日。 以下为精华帖正文&#xff1a; 01 笔 昨天讲了3根K线组合关系的完全分类&#xff0c;按照逻辑&#xff0c;其实我们会考虑是不是应该讲4根、5根K线的组合关系了。 精华帖…...

Java项目实战II基于Spring Boot的文理医院预约挂号系统的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 在医疗资源日益紧张的背景下&#xff0…...