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也会触发当前读,因为增删改这种写操作必然是要基于最新的行记录的,如果对一个历史版本的数据进行修改是毫无意义的,并且写操作是需要保证绝对的隔离性的,否则就会发送更新丢失,因此写操作也会加锁,那么就会触发当前读。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Axure 动态面板初使用 - 实现简单的Banner图轮播效果

实现简单的Banner图轮播效果 使用工具版本实现的效果步骤过程 使用工具版本 Axure 9 实现的效果 步骤过程 1、打开Axure工具&#xff0c;从元件库拖个动态面板到空白页&#xff1b; 2、给面板设置一个常用的banner尺寸&#xff0c;举个栗子&#xff1a;343151(移动端我常用…

SpringBoot:多环境配置

多环境配置demo代码&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 方式一、多个properties文件配置 注意&#xff1a;创建properties文件,命名规则&#xff1a;application-&#xff08;环境名称&#xff09; 示例&#xff1a;application-dev.proper…

【CSS】什么是BFC?BFC有什么作用?

【CSS】什么是BFC&#xff1f;BFC有什么作用&#xff1f; 一、BFC概念二、触发BFC三、BFC特性即应用场景1、解决margin塌陷的问题2、避免外边距margin重叠&#xff08;margin合并&#xff09;3、清除浮动4、阻止元素被浮动元素覆盖 一、BFC概念 BFC(block formatting context)…

俏美韵实现多场景养身 树立健康养身新要义

近年来&#xff0c;“年轻”在现代社会被符号化与视觉化&#xff0c;老年化的肉身迹象出现让“不甘衰老”的青年们困扰不安。然而这代年轻人的养身模式堪称为矛盾的集合体&#xff0c;他们挣扎在放纵与自律之间。一方面&#xff0c;他们想尽办法来创造各式各样的身体“保养”方…

阿里集团基于 Fluid+JindoCache 加速大模型训练的实践

作者&#xff1a;王涛(扬礼) 陈裘凯(求索) 徐之浩(东伝) 一、背景 时间步入了 2024 年&#xff0c;新的技术趋势&#xff0c;如大模型/AIGC/多模态等技术&#xff0c;已经开始与实际业务相结合&#xff0c;并开始生产落地。这些新的技术趋势不仅提高了算力的需求&#xff0c;也…

23、数据结构/查找相关练习20240205

一、请编程实现哈希表的创建存储数组{12,24,234,234,23,234,23},输入key查找的值&#xff0c;实现查找功能。 代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> typedef struct Node {int data;struct n…

VXLAN:虚拟化网络的强大引擎

1.什么是VXLAN VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;&#xff0c;是由IETF定义的NVO3&#xff08;Network Virtualization over Layer 3&#xff09;标准技术之一&#xff0c;是对传统VLAN协议的一种扩展。VXLAN的特…

mysql 多数据源

依赖 <dependencies><!--mysql连接--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--多数据源--><dependency><g…

第3节、电机定速转动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍用定时器定时的方式&#xff0c;精准控制脉冲时间&#xff0c;从而控制步进电机速度。 一、计算过程 电机每一步的角速度等于走这一步所花费的时间&#xff0c;走一步角度等于步距角&#xff…

Meta开源大模型LLaMA2的部署使用

LLaMA2的部署使用 LLaMA2申请下载下载模型启动运行Llama2模型文本补全任务实现聊天任务LLaMA2编程Web UI操作 LLaMA2 申请下载 访问meta ai申请模型下载&#xff0c;注意有地区限制&#xff0c;建议选其他国家 申请后会收到邮件&#xff0c;内含一个下载URL地址&#xff0c;…

电商开放API商品采集接口、关键字搜索接口,获取商品ID、商品主图接口

API是application programming interface&#xff08;应用程序接口&#xff09;的简称&#xff0c;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节。…

【敏捷开发】关于敏捷开发的几点思考,推荐一些高效书籍一起学

【敏捷开发】关于敏捷开发的几点思考&#xff0c;推荐一些高效书籍 一、背景二、敏捷宣言三、极限编程四、如何进行敏捷&#xff1f;4.1 改变软件研制方式4.2 组件高效团队4.3 改善研制流程4.4 持续集成与交付 五、Scrum过程六、书籍推荐 一、背景 软件开发的未来一定是多变的…

可解释性AI(XAI)的主要实现方法和研究方向

文章目录 每日一句正能量前言主要实现方法可解释模型模型可解释技术 未来研究方向后记 每日一句正能量 当你还不能对自己说今天学到了什么东西时&#xff0c;你就不要去睡觉。 前言 随着人工智能的迅速发展&#xff0c;越来越多的决策和任务交给了AI系统来完成。然而&#xff…

介绍docker

一&#xff1a;介绍docker&#xff1a; Docker 并没有单独的图形界面&#xff0c;它主要通过命令行来进行管理和操作 1、 docker ps&#xff1a;显示正在运行的容器。 docker images&#xff1a;显示本地的镜像。 docker run&#xff1a;创建并启动一个新容器。 docker stop&a…

探索LLM的意图识别能力

不可否认的是&#xff0c;LLM&#xff08;例如 OpenAI 的 GPT 系列&#xff09;将在不断发展的对话式 AI 领域发挥重要作用。 关于使用 ChatGPT 执行各种任务的帖子和文章不计其数。 GPT 有几个关键功能值得进一步探索&#xff0c;例如其摘要、分类和生成文本的能力。 其中&…

【软考设计师笔记】一篇文章带你了解数据库

【考证须知】IT行业高含金量的证书(传送门)&#x1f496; 【软件设计师笔记】计算机系统基础知识考点(传送门) &#x1f496; 【软件设计师笔记】程序语言设计考点(传送门) &#x1f496; 【软件设计师笔记】操作系统考点(传送门)&#x1f496; 【软件设计师笔记】什么是软…

SQL,HQL刷题,尚硅谷

目录 相关表数据&#xff1a; 题目及思路解析&#xff1a; 汇总分析 1、查询编号为“02”的课程的总成绩 2、查询参加考试的学生个数 分组 1、查询各科成绩最高和最低的分&#xff0c;以如下的形式显示&#xff1a;课程号&#xff0c;最高分&#xff0c;最低分 2、查询每门课程…

Python中的for循环用法详解,一文搞定它

文章目录 for循环1.for循环的基本语法&#xff08;1&#xff09;遍历不等长多级容器&#xff08;2&#xff09;遍历不等长多级容器&#xff08;3&#xff09;遍历等长的容器 2.变量的解包3.for...else【详细讲解】4.range对象5.总结6.打印 1 ~ 10 跳过57.打印菱形小星星 for循环…

多彩贵州人文山水展风采,微环境监测智能调控护古韵

一、人文山水时光峰峦——多彩贵州历史文化展 2月3日&#xff0c;贵州省博物馆向公众开放《人文山水时光峰峦——多彩贵州历史文化展》。6000平方米展厅里&#xff0c;从石器时期开始&#xff0c;通过六个篇章&#xff0c;用3503件文物的回忆链&#xff0c;系统化的向观众揭开…

Android9~Android13 某些容量SD卡被格式化为内部存储时容量显示错误问题的研究与解决方案

声明:原创文章,禁止转载! Android9~Android13 某些容量SD卡被格式化为内部存储时容量显示错误问题的研究与解决方案 分析Android11 系统对于EMMC/UFS作为内部存储、SD卡被格式化为内部存储、SD卡/U盘被格式化为便携式存储的不同处理 一.现象描述 实测Android9 Android10 A…