InnoDB存储引擎对MVCC的实现

news2025/1/20 3:55:49

MVCC

MVCC的目的

在搞清楚MVCC之前,我们要搞懂一个问题,MVCC到底解决的是什么问题?

我用一句话概括,那就是为了解决读-写可以一起的问题!

在我们的印象里,InnoDB可以读读并发,不能读写并发,或者写写并发

这是很正常的想法,因为如果读写并发的化,会有并发问题

而对于写写并发来说,我们还是得加锁,这是没办法改的

但是对于读-写并发来说,我们就可以用MVCC来解决

所以,综上所述,MVCC就是为了解决读-写并发,提高性能.

更准确的说,它是针对读操作的!和写操作关系不大

所以在MVCC的加持上,如果要解决并发问题?
读 + MVCC
写 + 锁

解决哪些并发问题?

先说结论:
对于读已提交

MVCC 解决了脏读

对于可重复读
MVCC 解决了脏读 + 不可重复读 + 幻读


然后其次,我们要搞清楚,有四种隔离级别,我相信大家都知道

读未提交 什么都没解决
读已提交 解决了脏读
可重复读 解决了脏读 + 不可重复读
串行 解决了脏读 +不 可重复读 + 幻读

这我相信你也是滚瓜烂熟

那么对于MVCC来说,它实际解决了哪些问题呢? 这个我们就得分情况了,因为MVCC也是贴合四种隔离级别的!我先说这个就是为了有一个大致的方向

需要注意的是,对于MVCC来说,读未提交 和 串行是束手无策的

你想一想就知道,读未提交连脏读都可以容忍,它还要你MVCC来干嘛,直接读就可以了
对于串行来说,它的读 + 写都是串行化的,不管你读还是写,都要排队,根本没有读 - 写并发的情况

所以,我们需要明确一点,MVCC是针对读已提交 + 可重复读

想清楚这一点,我们再来分别看,MVCC解决的问题,你可能会问,既然你都是贴合四种隔离级别的,那不就是对应隔离级别解决的问题嘛,不是的,这里就是有一个特殊,所以我才会拿来说

对于读已提交

MVCC 解决了脏读

对于可重复读
MVCC 解决了脏读 + 不可重复读 + 幻读

那么比较特殊的一点就是,对于可重复读来说,多解决了一个幻读的问题

综上所述,我们的结论就是,MVCC是针对读已提交 + 可重复读,并且在可重复读的情况下,还多解决了一个幻读问题

如何实现的?

读到这里,你就很好奇了,它是如何实现的呢?

其实很简单,就是一句话,MVCC读的是副本,不是当前的当前正在并发的数据

我们来反过来想,为什么会出现脏读 + 不可重复读,就是因为事务在并发的时候,有可能会修改你正在读的数据,这就导致,读第二次的时候会出现不一致

那我们该如何解决呢?也很简单,就是在事务一开始的时候,保存一份当前数据的副本,这样就算其他事务修改了,它修改的是数据库的数据,而不是我们的副本,这样不就避免了这两个问题吗?

顺着这个思路想,如果每次事务一开始的时候,我们都要取保存一份当前数据的副本,那如果有上亿的读的访问的话,那不是内存炸了?

所以,我们得用MySQL现成的功能来实现这个副本的功能!

所以,自然而然你会想到,Undo log,只有它存着历史的数据,那就是刚刚好的

至此,我们大致就可以引出了三个依赖
第一,隐藏字段
第二,Undo log
第三,Read View

Undo log就不用说了,就是为了生成副本的
Read View 也好说,不过是副本的官方的名字
对于隐藏字段来说,我们就得说一说了

对于聚簇索引来说,他有必要的隐藏列,
trx_id: 事务id
roll_pointer: 指针

事务id,就不用多说了,你需要一个标识来标识事务
对于roll_pointer来说,它和Undo log就会有联系,就是一个指针嘛,我们直接看图就能懂了,为什么需要roll_pointer,还有Undo log实际上长什么样子
在这里插入图片描述
一看就懂,不就是链表嘛,第一个就是最新的记录,后边的都是历史记录

此时,你就大概能明白,为什么需要隐藏字段了把,其实也不是很重要,一笔带过就行

我们特别要注意的是,Read View 副本的结构,这才是我们需要研究的东西
因为我们不熟啊

Read View结构

对于Read View我们先看图,它的大致结构如下

在这里插入图片描述
实际,它记录的不是实际的数据,而是一群活跃的事务id

什么叫活跃的事务id呢?就是那些在并发的时候,在那捣乱的事务,为啥要记录呢?很好理解嘛,在Undo log中,只要有这些捣蛋鬼做的记录,我们就不看,读那些已经提交的记录

结构

creator_trx_id: 创建Readview的事务id
trx_ids: 活跃的事务id列表
up_limit_id: 最小的事务ID
low_limit_id: 下一个最大的事务ID

这里需要特别注意,up_limit_id是最小的
low_limit_id是最大的

还有一点是,这里的最小最大的选取标准是不一样的
这里举个例子,比较容易懂

比如说,事务id列表中,有三个事务id, 1,3,5

我们要假设MySQL只有这三个事务id,其他没有,暗含的意思是,这里的id = 5,是当前生成的最大的事务id

那么up_limit_id 就是1
low_limit_id 是当前生成过的最大的事务id + 1 也就是 5 + 1 = 6

假设事务5提交了,此时的事务列表是1,3
low_limit_id 还是6,因为它类似于Auto_increment 自增id的意思,它会记录当前生成过的最大的事务ID

ReadView的规则

我们研究这个规则,实际上就是研究MVCC的核心规则了

我们得对应着Undo log的版本链来看,版本链就是历史记录

如下
在这里插入图片描述
然后就着
ReadView的结构来看

在这里插入图片描述

事务开始,生成一个ReadView,
然后当前事务,要读取的时候,此时就会去查看两个东西 ReadView + Undo log

查看Undo log就是顺着链表一个一个往下看,找到符合条件的就返回

符合的条件就是规则

第一,如果此时查看的记录trx_id = creator_trx_id,符合条件,读此记录
意思就是,当前记录就是我们自己事务干的事,ReadView是我们当前事务自己生成的,自己读自己的,当然没问题

第二,如果不是自己的,就检查,ReadView的trx_ids,也就是事务id列表
如果发现,当前访问的记录,就是这些捣蛋鬼其中一个干的,那就是不符合条件,如果发现不在这群事务id里边,说明,当前读的是,已经提交了的记录,符合条件

第三,需要注意的是,对于第二,来说,当前的记录的trx_id是介于
up_limit_id < 当前 事务id < low_limit_id,

up_limit_id,和low_limit_id,是一个范围,还有一个功能就是快速的判断

如果,最新的记录是小于up_limit_id的,那么直接就是返回当前记录

为什么呢?因为事务id是单调递增的,和主键id一样,如果我们最新的记录都提交了,那更早的记录是不是都提交了,返回返回没问题!

如果,最新的记录是大于等于low_limit_id的,那么不符合条件,往下找
为什么呢? 因为,如果此时最新的记录是大于low_limit_id的,意思就是这个记录它是在我们事务生成ReadView之后生成的,也就是

我们生成ReadView
然后紧接着,有一个事务进来修改了

那更不可能读这条记录了,比迟到的人还迟到.

综上所述,我们总结一下
trx_id = creator_trx_id,可以读
当trx_id < up_limit_id,可以读
当trx_id >= low_limit_id,不可以读
当up_limit_id <= trx_id < low_limit_id的时候,查看当前记录的id是不是在trx_ids里边,如果在的话,说明这是捣蛋鬼干的,不可以读,如果不存在,可以读

再总结一下,我们只要记住什么时候不可以读

当trx_id >= low_limit_id 的时候,不可以读
当trx_id在范围中间,且当前的记录id,在trx_ids里边,不可以读
其他情况都可以读

读已提交 和 可重复读的不同流程

因为,MVCC要贴合这两个隔离级别解决的问题,所以,他们的流程会有点不一样

对于读已提交来说,事务开始,每一次select都会去获取ReadView
对于可重复读来说,事务开始,到结束,只会获取一次ReadView

这个想想就能明白,读已提交,没有解决不可重复读问题,那么每一次读ReadView的时候,有可能有一些事务就提交了,会读到多的数据

可重复读的时候,由于至始至终,只看一个ReadView,那就是事务开始的时候的ReadView,那可想而知,不会有可重复读的问题,还有幻读的问题了,因为,只看一个ReadView,就算多一万遍,读到的记录还是不会多不会少,所以这也是为什么对于可重复读来说,它可以解决幻读问题了.

RR -> MVCC + Next-key-Lock 防止幻读

对于本篇文章来说,我文中说的,在可重复读的情况下,可以解决幻读问题的
这其实是不严谨的

对于快照读来说,在RR下,是可以解决幻读问题

但是对于当前读来说,因为读到的是最新的数据,还有就是,在undo log中,分为insert log 和 update log,insert log是对其他事务不可见的,所以在RR下,并且是当前读,就有可能出现幻读问题

总结就是一句话,当前读的情况下,如果其他事务做了插入操作,可能会有幻读问题

在RR下,哪些是当前读呢?
select…for update/lock in share mode、insert、update、delete

如此,我们的解决办法就是Next-key-Lock
记录锁 + 间隙锁 = Next-key-Lock

它的原理也很简单,就是在行锁的基础上,锁定范围,如果其他事务要插入到这个范围内的化,会被拒绝

换个角度想就是,我不让你插入,我就不会有幻读问题!

总结

所以我们最后来总结一下

MVCC的目的是什么?

为了解决读-写并发,但是只针对读已提交 + 可重复读

MVCC是怎么实现的?

第一,隐藏字段-> 事务id + 指针
第二,Undo log
第三,ReadView

如何实现这个问题,就转换成ReadView如何做校验?

对于读已提交,每次select的时候,获取一个ReadView
对于可重复读,事务开始的时候,获取一个ReadView

做实际的校验

到最后,做校验的问题,就转换成校验的规则是什么?

如果,trx_id >= low_limit_id,不符合条件
如果,up_limit_id <= trx_id < low_limit_id,并且trx_id在trx_ids中,不符合条件
其他情况都符合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1496086.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式:什么是设计模式?①

一、什么是设计模式&#xff1f; 1. 是一类程序设计思想 2. 是在大量实践过程中摸索总结出的标准经验提炼 3. 具有多样性和丰富性&#xff0c;不同情况应用的思想不同 二、设计模式的好处 1. 代码生产力和效率的提升 2. 让代码表现更为规整&#xff0c;简洁。阅读维护管理的成本…

InfluxDB SHOW SERIES语句按照什么顺序返回?

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言样例SHOW SERIES比较原理结论结束语 引言 influxdb的计算引擎为了做到自底而上的…

曲线曲面 - 连续性, 坐标变换矩阵

连续性 有两种&#xff1a;参数连续性&#xff08;Parametric Continuity&#xff09;、几何连续性&#xff08;Geometric Continuity&#xff09;参数连续性&#xff1a; 零阶参数连续性&#xff0c;记为&#xff0c;指相邻两段曲线在结合点处具有相同的坐标 一阶参数连续性&…

前缀和+哈希表:联手合击Leetcode 560.和为k的子数组

题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;nums [1,2…

GPT-4技术解析:与Claude3、Gemini、Sora的技术差异与优势对比

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚…

【笔记】OpenHarmony和HarmonyOS区别及应用开发简介

一、概念 OpenHarmony(OH) &#xff1a; OpenAtom OpenHarmonyHarmonyOS(HO)&#xff1a;开发 | 华为开发者联盟 (huawei.com) HO当前最高是3.1&#xff0c;在华为mate 60上面也是。关于4.0、5.0和next这类版本说法都是面向用户的&#xff0c;不是开发人员。对于程序员&#…

算法相关计算

1 内存管理相关 1 .1 float 6.9 f 的内存计算方法 二进制小数的计算&#xff1a; &#xff08;1&#xff09;小数的二进制算法和整数的大致相反&#xff0c;就是不断的拿小数部分乘以2取积的整数部分&#xff0c;然后正序排列。比如求0.9的二进制&#xff1a; 0.9*21.8 取 1…

opencv边缘检测之Canny算法

文章目录 简介实战 简介 Canny在1986年提出了一种边缘检测算法&#xff0c;因其卓越的性能和准确性而广泛应用于各种图像分析领域。opencv中提供了这种算法&#xff0c;其操作步骤如下 高斯滤波&#xff1a;采用 5 5 5\times5 55的高斯核函数进行滤波&#xff0c;对图像进行…

chrome插件chrome.storage数据写入失败QUOTA_BYTES_PER_ITEM quota exceeded

Unchecked runtime.lastError while running storage.set: QUOTA_BYTES_PER_ITEM quota exceeded at Object.callback 在开发浏览器插件的时候&#xff0c;报错提示&#xff1a;超出存储限制&#xff0c;浏览器插件存储官方文档&#xff1a;https://developer.chrome.com/docs…

selinux规则

selinux状态 相关命令 进程要和文件的安全上下文相匹配&#xff0c;进程才能打开文件 查找这个命令从哪个安装包来的用 yum provides 命令 进程httpd 必须与ls -Z的文件类型一致&#xff0c;要不然在强制模式下面&#xff0c;打开不了 在终端2用此命令&#xff0c;把文件类型改…

【Ubuntu】将多个python文件打包为.so文件

1.为什么要将python打包为.so文件&#xff1f; 保护源码 2.实战例子 a.安装相应的包 pip install cython 验证安装是否成功 cython --version b.实战的文件目录和内容 hi.py # This is a sample Python script.# Press ShiftF10 to execute it or replace it with your…

基于OpenCV的图形分析辨认01

目录 一、前言 二、实验目的 三、实验内容 四、实验过程 一、前言 编程语言&#xff1a;Python&#xff0c;编程软件&#xff1a;vscode或pycharm&#xff0c;必备的第三方库&#xff1a;OpenCV&#xff0c;numpy&#xff0c;matplotlib&#xff0c;os等等。 关于OpenCV&…

Docker的镜像操作

目录 镜像的操作(**开头为常用请留意) 镜像查找 **拉取镜像 **推送镜像 **查看镜像 **修改镜像名称 **查看镜像的详细信息 ​编辑 删除镜像 查看所有镜像ID 删除全部镜像 **查看镜像的操作历史 镜像迁移 镜像打包 远程发送镜像(需要先打包) 本地镜像tar包恢复 镜像过…

FPGA——三速自适应以太网设计(2)GMII与RGMII接口

FPGA——以太网设计&#xff08;2&#xff09;GMII与RGMII 基础知识&#xff08;1&#xff09;GMII&#xff08;2&#xff09;RGMII&#xff08;3&#xff09;IDDR GMII设计转RGMII接口跨时钟传输模块 基础知识 &#xff08;1&#xff09;GMII GMII:发送端时钟由MAC端提供 下…

Web安全:报错注入原理分析,报错注入步骤,报错注入常用函数

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全自学教程》 报错注入 一、什么是报错注入二、执行原理1. 代码逻辑…

node_vue个人博客系统开发

Day01 一、导入express 1、创建node_serve服务文件夹 2、初始化项目 npm init -y3、导入express框架 npm i express4、创建一个app.js文件,为服务端的入口文件 // 导入express模块 const express = require(express); // 创建express服务 const app = express(); // 调用…

Promisification、微任务

前提摘要 Promise 对象的构造器&#xff08;constructor&#xff09;语法如下&#xff1a; let promise new Promise(function(resolve, reject) { // executor }); 传递给 new Promise的函数被称为 executor&#xff0c;当 new Promise 被创建&#xff0c;executor 会自动…

小程序Taro框架 自定义底部Tabbar,处理自定义Tab栏切换卡顿、闪烁

最终效果 最近在用Taro框架开发一个小程序&#xff0c;有一个自定义底部Tabbar的需求&#xff0c;最终效果如下 起步 这页是我第一次接触自定义小程序底部Tabbar&#xff0c;所有第一选择必然是相看官方文档&#xff1a;微信小程序自定义 Tabbar | Taro 文档 &#xff08;如果…

支部管理系统微信小程序(管理端+用户端)flask+vue+mysql+微信小程序

系统架构如图所示 高校D支部管理系统 由web端和微信小程序端组成&#xff0c;由web端负责管理&#xff0c;能够收缴费用、发布信息、发布问卷、发布通知等功能 部分功能页面如图所示 微信小程序端 包含所有源码和远程部署&#xff0c;可作为毕设课设

SAP PP学习笔记07 - 简单BOM,派生BOM,多重BOM,批量修改工具 CEWB

上一章讲了BOM的操作。 SAP PP学习笔记06 - BOM操作&#xff08;BOM 展开&#xff0c;BOM 使用先一览&#xff0c;BOM比较&#xff0c;批量更改BOM&#xff09;-CSDN博客 本章延续上一章&#xff0c;继续讲BOM操作。 主要讲 派生BOM&#xff0c;多重BOM&#xff0c;以及BOM批…