MySQL知识点总结(四)——MVCC

MySQL知识点总结(四)——MVCC

  • 三个隐式字段
    • row_id
    • trx_id
    • roll_pointer
  • undo log
  • read view
  • MVCC与隔离级别的关系
  • 快照读和当前读

MVCC全称是Multi Version Concurrency Control,也就是多版本并发控制。它的作用是提高事务的并发度,通过MVCC机制,数据库可以不通过加锁,也能保证事务的隔离性。MySQL的InnoDB存储引擎也有自己的MVCC机制的实现,通过MVCC机制保证了“读已提交”和“可重复读”两个隔离级别下的隔离性。

要理解MVCC,就要理解InnoDB里面的三样东西:“数据行记录中的三个隐式字段”、“undo log”、“read view”。理解了这三个东西,也就是理解了MVCC。

在这里插入图片描述

三个隐式字段

当我们使用InnoDB作为我们某个库表的存储引擎时,我们添加到该库表中的数据行记录,InnoDB都会默认给该行记录添加三个隐式字段,这三个隐式字段分别是“row_id”、“trx_id”、“roll_pointer”。

在这里插入图片描述

row_id

这个是InnoDB为每一个行记录生成的一个唯一的id,它和主键一样,都可以唯一标识一条行记录。当我们没有给我们的库表定义主键、也没有定义唯一索引时,InnoDB就会拿它来作为库表的主键。

于是,InnoDB中库表主键的选取,首先看库表是否有显式定义主键列,如果有,那么当前库表的主键就是我们显式定义的主键列;如果没有定义主键,但是我们定义了唯一索引,那么当前库表的主键就是我们定义的唯一索引(多个唯一索引,选其中一个);如果我们没有定义主键列,也没有定义唯一索引,那么InnoDB就会把row_id作为当前库表的主键。

在这里插入图片描述

trx_id

“trx_id”是事务id,记录的是当前行记录是被哪个事务修改提交的。

InnoDB会为每个开启的事务分配一个递增的id,用于唯一标识一个事务,当某个事务修改了某个行记录时,就会在这个行记录的trx_id隐式字段中记录当前事务的id。

在这里插入图片描述

roll_pointer

roll_pointer是回滚指针,当一个事务对某库表的一条行记录进行修改时,会把该行记录先拷贝到undo log日志中作为一个历史版本,然后再对该行记录进行修改,并且使用一个roll_pointer指针指向undo log中该行记录的历史版本。

在这里插入图片描述

undo log

undo log是InnoDB的回滚日志,用于事务回滚。每次对库表进行增删改,InnoDB都会把涉及到的行记录的历史版本拷贝到undo log中,然后使用行记录中的隐式字段“roll_pointer”指向undo log中该行记录的最近的版本,这样,undo log就形成了一个链表,沿着roll_pointer回滚指针,我们可以不断的往前追溯某个行记录的历史版本。

在这里插入图片描述

有了undo log,就可以实现事务的可重复读,只要当前事务通过某种机制记住该行记录哪个历史版本对于自己是可见的,然后每次读取该行记录时都读取这个历史版本,就可以实现可重复读,其他事务也可以照常进行更新操作,不会被阻塞。

而这个机制就是“read view”,read view记录了当前活跃的事务id,也就是已开启但还未提交的事务对于的事务id。有了“read view”,当前事务读取某库表的行记录时,就可以沿着roll_pointer指针往前进行遍历,拿到该行记录的每个版本对应的trx_id字段,在read view中进行比对,如果发现trx_id在read view中是存在的,那说明这个版本是当前某个活跃事务修改(但未提交)的,因此对于当前事务尚不可见,直到遍历到某个版本,发现在read_view中不存在,那么就可以读取这个版本。

在这里插入图片描述

read view

“read view”是一种快照,它不仅记录了当前有哪些事务正处于活跃状态,还记录了当前活跃事务中最小的id,以及下一个开启的事务将会被分配的事务id。

在这里插入图片描述

比如当前活跃的事务对应的事务id是5、4、3,那么read view就会通过一个列表trx_ids记录[3,4,5]。通过trx_ids可以得知,当最小的活跃事务id是3,InnoDB用一个变量up_limit_id记录这个3,然后下一个开启的事务被分配的事务id是6,InnoDB用一个变量low_limit_id记录这个6。

在这里插入图片描述

这样,通过read view不但可以得知当前活跃事务,也可以知道在当前事务开启前已经提交的最新事务是多少,比如这里的read view记录的时[3,4,5],那就可以知道在当前事务开启以前,最新提交的事务是2,那么trx_id小于等于2(trx_id < up_limit_id)的行记录对于当前事务都是可见的。

除此以外,也可以知道下一个要开启的事务被分配的事务id是多少,比如这里比如这里的read view记录的时[3,4,5],那就可以知道下一个要开启的事务会被分配事务id为6。如果在当前事务开启之后,又开启了其他事务,并且提交了修改,那么被修改的行记录的trx_id就是大于等于6的(trx_id >= low_limit_id),对于当前事务来说是不可见,只能沿着roll_pointer往前追溯,读取历史版本。

因此,当一个事务读取某库表的某行记录时,这个可见性的判断逻辑就是这样:

  1. 判断当前记录的trx_id是否小于up_limit_id:如果是,那么当前行记录对于当前事务是可见的;如果不是,执行下一步的判断逻辑(步骤2)。
  2. 判断trx_id是否大于等于low_limit_id:如果是,那么当前行记录对于当前事务是不可见的,只能沿着roll_pointer指针往前遍历,读取当前行记录的上一个历史版本,并且回到步骤1重新比对;如果不是,那么执行下一步的判断逻辑(步骤3)。
  3. 判断trx_id是否在trx_ids列表中:如果是,那么表示当前行记录是当前某个活跃的事务修改的,执行下一步判断逻辑(步骤4);如果不是,那么表示当前行记录是在当前事务开启并生成read view前就已经提交了的,那么对于当前事务来说可见,读取该版本的行记录。
  4. 判断trx_id是否是当前事务自己的id:如果是,那么表示是自己做的修改,还是可见的;否则对于当前事务来说也是不可见,只能沿着roll_pointer指针往前遍历,读取当前行记录的上一个历史版本,并且回到步骤1重新比对。

在这里插入图片描述

MVCC与隔离级别的关系

我们知道隔离级别从低到高有四个:读未提交、读已提交、可重复读、串行化。在InnoDB中,读已提交和可重复读这两个隔离级别就是通过MVCC保证的。

在读已提交隔离级别下,事务的每次SQL都会生成一个新的read view,这是它可以读到其他事务最新提交的修改的原因。比如现在有一个事务A读取某库表id为5的这一条记录,读到【name】字段的值“zhagnsan”。此时,另一个事务B修改了该库表id为5的这一行记录的【name】字段为“lisi”,并提交了。此时事务A再次读取该库表id为5的这一行记录,在读取前,会重新生成read view,由于事务B已经提交了,活跃事务列表trx_ids中就不包含事务B的事务id了,因此事务B修改id为5的行记录的【name】字段为“lisi”,是可以被事务A读到的,这就是不可重复读问题出现的原因。

在这里插入图片描述

而在可重复读隔离级别下,read view只在当前事务开启后,第一次发起读操作时生成一遍,后续就不再生成。也就是说,在可重复读隔离级别下,一个事务的read view一旦生成,后续就不再改变,即使中间有某个活跃的事务修改数据并提交了,当前事务的read view也不会发生变化,再次发起读操作时也不会再重新生成read view,因此read view的trx_ids中还是记录着这个已提交的事务的事务id,因此该修改对于当前事务就不可见,不会被当前事务读取到。

在这里插入图片描述

快照读和当前读

上面这种通过MVCC读取一个行记录的历史版本的做法,就是快照读,也就是说我们读到的是数据的历史版本。

而当前读则是保证读到的一定是当前行记录的最新版本,那什么时候会触发快照读,什么时候会触发当前读呢?

当一个事务开启以后,一般的select语句都是快照读,只有显式地添加“lock in share mode”或者“for update”的select语句才会进行当前读,因为这两个语句是加锁的语句,都已经要加锁了,就没有必要走MVCC的逻辑了。

除此以外,“update”、“insert”、“delete”等SQL也会触发当前读,因为增删改这种写操作必然是要基于最新的行记录的,如果对一个历史版本的数据进行修改是毫无意义的,并且写操作是需要保证绝对的隔离性的,否则就会发送更新丢失,因此写操作也会加锁,那么就会触发当前读。

在这里插入图片描述

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

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

相关文章

虹科技术丨一文详解IO-Link Wireless技术如何影响工业无线自动化

来源&#xff1a;虹科工业智能互联 虹科技术丨一文详解IO-Link Wireless技术如何影响工业无线自动化 原文链接&#xff1a;https://mp.weixin.qq.com/s/qVIkdeI5zzzagPd0UEkfDg 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #工业自动化 #IO-Link Wireless #工业无…

C语言指针学习 之 指针变量

前言&#xff1a; 通过学习我们认识了什么是指针&#xff0c;就让我们一起来分析一个例子。 #include<stdio.h> int main() {int a100;int * hz; hz &a;printf("a%d \n",a);printf("*hz%d \n",*hz);return 0; }a100 *hz100 PS C:\csay\cyuya…

使用 SortableJS 组件的 Blazor 可排序列表

作者&#xff1a;Burke Holland 排版&#xff1a;Alan Wang 在 Web 应用程序中&#xff0c;一个常见功能部分是可排序列表。SortableJS 是我最喜欢的 JavaScript 库之一&#xff0c;在进行 Blazor 开发时我很想念它。为了解决这个问题&#xff0c;我决定包装 SortableJS 库&…

算法学习——华为机考题库1(HJ1 - HJ10)

算法学习——华为机考题库1&#xff08;HJ1 - HJ10&#xff09; HJ1 字符串最后一个单词的长度 描述 计算字符串最后一个单词的长度&#xff0c;单词以空格隔开&#xff0c;字符串长度小于5000。&#xff08;注&#xff1a;字符串末尾不以空格为结尾&#xff09; 输入描述&…

【Springcloud篇】学习笔记一(一至三章):微服务介绍、构建环境

零基础微服务架构理论入门介绍 一个基于分布式的服务架构应该含有的架构内容如下&#xff1a; 1.1SpringCloud是什么 1.2基于微服务的系统 1.3服务与之对用的技术 1.4课程目录 第一章_SpringBoot和SpringCloud版本选择 详细可见SpringCloud2020.mmap文件 1.概述 2.SpringBoo…

Java自救手册

目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&#xff1a; 网络不通一般有两种情况&#xff1a; Maven 拿Maven 拿到Maven以后 Maven单独的报红 Git git注意&#xff1a; 目录 访问地址 访问地址&#xff0c;发现不通&#xff0c;无法访问&…

2024年美国大学生数学建模竞赛(D题)湖泊水位调控|粒子群强化学习建模解析,小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 此篇文章是由鹿鹿学长倾心打磨&#xff0c;解决挑战&#xff0c;创造美赛建模独特思路。融合粒子群算法、深度强化学习等前沿技术&#xff0c;构建全面…

Unity C#高级特性 Partial 详细使用案例

文章目录 实例 1&#xff1a;分隔UI逻辑实例 2&#xff1a;Unity编辑器自动生成代码实例 3&#xff1a;数据模型分割实例 4&#xff1a;序列化扩展实例 5&#xff1a;多视图架构实例 6&#xff1a;Unity编辑器自定义 inspectors 在Unity中&#xff0c;部分类&#xff08;Partia…

jsp服装穿搭推荐系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 游戏网上商城系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

Elasticsearch-内存结构

ElasticSearch的内存从大的结构可以分堆内存&#xff08;On Heap&#xff09;和堆外内存&#xff08;Off Heap&#xff09;。Off Heap部分由Lucene进行管理。On Heap部分存在可GC部分和不可GC部分&#xff0c;可GC部分通过GC回收垃圾对象&#xff0c;从而释放内存。不可GC部分不…

第九节HarmonyOS 常用基础组件22-Marquee

1、描述 跑马灯组件&#xff0c;用于滚动展示一段单行文本&#xff0c;仅当文本内容宽度超过跑马灯组件宽度时滚动。 2、接口 Marquee(value:{start:boolean, step?:number, loop?:number, fromStart?: boolean ,src:string}) 3、参数 参数名 参数类型 必填 描述 st…

qt -chart控件设计器可拖拉

qt -chart控件设计器可拖拉 一、演示效果二、安装过程三、核心程序四、程序链接 一、演示效果 二、安装过程 三、核心程序 #include <QtGui> #include <QColor>#include <cstdlib> #include <cassert> #include <numeric>#include <chartwor…

【Java程序设计】【C00232】基于Springboot的抗疫物资管理系统(有论文)

基于Springboot的抗疫物资管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的抗疫物资管理系统 用户主要分为管理员和普通用户 管理员&#xff1a; 管理员可以对后台数据进行管理、拥有最高权限、具体权限有…

【LLM KBQA】FlexKBQA:一种结合LLM的KBQA框架

前言 大语言模型&#xff08;LLMs&#xff09;在知识库问答&#xff08;KBQA&#xff09;领域的应用主要集中在包括但不限于以下几个方面&#xff1a; 直接生成答案&#xff1a;一些方法直接利用LLMs生成答案&#xff0c;而不是生成中间的程序&#xff08;如SPARQL查询&#…

算法学习——华为机考题库3(HJ21 - HJ25)

算法学习——华为机考题库3&#xff08;HJ21 - HJ30&#xff09; HJ21 简单密码 描述 现在有一种密码变换算法。 九键手机键盘上的数字与字母的对应&#xff1a; 1–1&#xff0c; abc–2, def–3, ghi–4, jkl–5, mno–6, pqrs–7, tuv–8 wxyz–9, 0–0&#xff0c;把密码…

Vue3.0(一):Vue的引入-options api-模板语法

Vue的引入方式 CDN方式进行引入 将以下 script标签引入即可 <script src"https://unpkg.com/vue3/dist/vue.global.js"></script><!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><met…

Linux下tar命令详解

tar #归档命令 格式 • Tar -参数 [args]..... 参数&#xff1a; 必选参数&#xff1a; 辅助参数&#xff1a; 额外参数&#xff1a; # 打包时排除某个文件 tar cf 文件名.tar --exclude路径/文件 路径 注&#xff1a;此处的路径前后需要保持保持一致&#xff0c;统一…

使用 IDEA 开发一个简单易用的 SDK

目录 一、什么是 SDK 二、为什么要开发 SDK 三、开发 SDK 的详细步骤 四、导入 SDK 进行测试 附&#xff1a;ConfigurationProperties 注解的介绍及使用 一、什么是 SDK 1. 定义&#xff1a;软件开发工具包 Software Development Kit 2. 用于开发特定软件或应用程序的工…

Javascript | JS如何断点测试(WebStorm)

JavaScript的断点与之前所学到的Java和python在jetbrain系列编辑器中的断点debug不太一样&#xff0c;往常我们在编写python的时候用pycharm的时候是直接断点进入debug的&#xff0c;就像下面这样 只要直接在代码中断点&#xff0c;然后运行debug功能即可 但是在WebStorm中不是…

【Tomcat与网络3】Tomcat的整体架构

目录 1.演进1&#xff1a;将连接和处理服务分开 2演进2&#xff1a;Container的演进 3 再论Tomcat的容器结构 4 Tomcat处理请求的过程 5 请求的处理过程与Pipeline-Valve管道 在前面我们介绍了Servlet的基本原理&#xff0c;本文我们结合Tomcat来分析一下如何设计一个大型…