【MySQL】MVCC详解, 图文并茂简单易懂

在这里插入图片描述

欢迎来到啊妮莫的学习小屋
祝读本文的朋友都天天开心呀

目录

  • MVCC简介
  • 快照读与当前读
    • 快照读
    • 当前读
  • 隔离级别
  • 隐藏字段和Undo Log版本链✨
  • MVCC原理--ReadView✨
    • ReadView简介
    • 设计思路
      • 适用隔离级别
      • 重要内容
    • ReadView规则
    • MVCC整体流程
  • 不同隔离级别下的MVCC
    • 读已提交
    • 可重复读
  • 总结

在这里插入图片描述

MVCC简介

MVCC也称: 多版本并发控制. 顾名思义, MVCC是通过数据行的多个版本管理来实现数据库的并发控制. MVCC使得在InnoDB的事务隔离级别下, 执行一致性读操作有了保证. 简单来说就是: 在需要读取一些正在被另一个事务更新的行数据时, 读取之前的历史版本数据(旧数据); 而不需要等待另一个事务释放锁.

并不是所有的存储引擎都支持MVCC技术, 本文讲解的是MySQLInnoDB存储引擎下的MVCC机制.

快照读与当前读

MVCC机制主要解决的是读--写冲突问题, 提高数据库的并发性能.

当发生读写冲突时:

采用快照读, 不加锁 非阻塞并发读

采用当前读, 加锁

MVCC机制本质上是采用了乐观锁思想

快照读

又名一致性读, 读取到的是快照数据. 不加锁的简单SELECT都是快照读.

例如:

SELECT * FROM student WHERE...

快照读可能读到的并不一定是数据的最新版本, 而有可能是之前的历史版本.

快照读可以形象的理解为我们生活中的照片, 拍摄到的画面都是过去式.

在这里插入图片描述

当前读

当前读读取到的是 最新版本数据.

读取时需要保证其他并发事务不能修改当前记录, 因此需要加锁.

例如:

SELECT * FROM student LOCK IN SHARE MODE;    # 共享锁
SELECT * FROM student FOR UPDATE;    # 排他锁
-- 修改操作对应的排他锁
INSERT INTO student VALUES ...    
DELETE FROM student WHERE ...
UPDATE student SET ...

当前读可以形象的理解为生活中的直播, 看到到的画面是实时的, 最新的.

在这里插入图片描述

隔离级别

事务有四种隔离级别: 读未提交, 读已提交, 可重复读, 串行化.

  1. 读未提交: 其他事务可以看见未提交事务做出的数据改变. 也就是会发生脏读.
  2. 读已提交: 其他事务只能看到已经提交事务做出的数据改变. 若另一个事务不断的更新某一行数据并提交, 那么读取出来的数据前后不一致, 即不可重复读.
  3. 可重复读: 解决了不可重复读问题, 确保同一事务多次读取结果一致. 但是依然会发生幻读问题–另一个事务插入新的数据行, 那么读取该范围内的数据时, 会发现新的"幻影"行.
  4. 串行化: 最严格的隔离级别, 通过加锁避免了脏读, 不可重复读和幻读, 但是性能较差.

在这里插入图片描述

MySQL的默认隔离级别是可重复读
可重复读隔离级别解决了脏读不可重复读问题, 未解决幻读问题.

但是, MySQL中的MVCC机制解决了幻读问题! 它可以在大多数情况下代替行级锁, 提高数据库的事务并发能力.

在这里插入图片描述

隐藏字段和Undo Log版本链✨

对于使用InnoDB存储引擎的表来说, 其聚簇索引中的行数据包含了三个隐藏字段: row_id, trx_id, roll_pointer.

其中trx_idroll_pointer使得用户记录生成一条Undo Log版本链.

  • trx_id: 这个字段记录了最后修改行记录的事务ID.
  • roll_pointer: 这个字段是一个指针, 指向该行记录的回滚段, 在发生事务回滚时用来撤销行记录的修改.

例如: students的表数据如下

mysql> SELECT * FROM students WHERE id=1;
+------+----------+----------+
| id   | stu_name | major    |
+------+----------+----------+
|    1 | 张三     | 软件工程 |
+------+----------+----------+
1 row in set (0.00 sec)

假设插入该记录的事务ID等于8, 则该条记录的示意图如下所示:

在这里插入图片描述

🌈

注意: insert undo只在事务回滚起作用, 当事务提交后, 该类型的undo日志就没有用了, 它占用的UndoLog Segment也会被系统回收(也就是该undo日志占用的Undo页面链表要么被重用, 要么被释放).

假设之后两个事务ID分别为10, 20的事务对该条数据进行UPDATE操作, 操作流程如下:

在这里插入图片描述

🌈

注意: 不能两个事务交叉更新同一条数据! 即: 一个事务修改另一个未提交的事务修改过的数据 (脏写).

InnoDB使用锁来保证不会有脏写的情况发生: 当一个事务更新了某条记录后, 会给这条记录加锁; 另一个事务需要等待锁被释放后才可以更新.

每次修改, 都会记录一条undo日志, 每一条undo日志也都会有一个roll_pointer字段, 将这些undo日志串成一个链表–Undo Log 版本链

在这里插入图片描述

Undo Log 版本链的头结点就是当前的最新记录. 所有版本依靠roll_ptr字段连接成一个链表.

MVCC原理–ReadView✨

MVCC的实现依赖于: 两个隐藏字段, Undo Log, ReadView.

在这里插入图片描述

ReadView简介

ReadView就是事务在使用MVCC机制进行快照读操作时产生的读视图.

当事务读取数据时, 会数据库系统生成当前的一个快照, InnoDb会为事务构造一个数组, 用于记录并维护系统中当前的活跃事务ID组(活跃是指: 开启了但是还没有进行提交).

设计思路

适用隔离级别

ReadView仅仅适用于读已提交可重复读隔离级别, 对于这两种隔离级别, 都必须保证读到的是已经提交的事务修改过的记录. 假如另一个事务已经修改但是还没有提交, 是不能直接读取到的. 核心问题是判断版本链中哪些版本记录是当前事务可见的,这是ReadView要解决的主要问题.

对于读未提交: 读到的就是最新版本数据.

对于串行化: 事务排队执行, InnoDB使用机制来避免读写冲突.

重要内容

  1. creator_trx_id: 创建这个ReadView事务ID.
  2. trx_ids: 在生成ReadView时, 当前系统中活跃的读写事务的ID列表.
  3. up_limit_id: 活跃的事务中最小的事务ID.
  4. low_limit_id: 表示在生成ReadView时系统应该分配给下一个事务的ID, 也就是系统中最大的事务ID值.

🌈

注意: 对于只读事务, creator_trx_id 默认为0

举例:
若现有id为1, 2, 3这三个事务, 之后id=3的事务提交了;
那么一个新的读事务在生成ReadView的时, trx_ids=[1,2], up_limit_id=1, low_limit_id的值为4

在这里插入图片描述

ReadView规则

当需要读取某条记录的时候, 只需要按照以下步骤就可以判断该记录的某个版本是否可见.

  1. 当读取版本的trx_id=creator_trx_id, 也就是当前事务修改过的记录–可见.
  2. trx_id<up_limit_id, 该版本的事务已经在生成ReadView之前就提交了–可见.
  3. trx_id>=low_limit_id, 该版本的事务是在生成ReadView之后才开启的–不可见.
  4. up_limit_id<=trx_id<low_limit_id, 则需要分情况讨论
    • 不在trx_ids列表中, 说明该事务已经提交–可见.
    • 在列表中, 该事务在生成ReadView时处于活跃状态–不可见.

如图所示:

在这里插入图片描述

MVCC整体流程

  1. 获取自己的事务版本号:creator_trx_id
  2. 生成ReadView
  3. 将查询到的数据, 与ReadView中的事务版本号进行对比
  4. 若可见, 则从Undo Log中获取历史快照, 否则顺着版本链找到下一个数据, 重复3,4.
  5. 若最后一个版本也不可见, 则意味着这条记录对该事务是完全不可见的, 查询结果就不包含该记录.

🌈

说明: MVCC是通过隐藏字段生成的Undo Log版本链, 加上ReadView规则帮我们判断当前版本的数据是否可见.

不同隔离级别下的MVCC

读已提交

在隔离级别为读已提交时,一个事务中的每一次 SELECT 查询都会重新获取一次Read View

在这里插入图片描述

🌈

注意: 此时同样的查询语句都会重新获取一次Read View这时如果Read View不同,就可能产生不可重复读或者幻读的情况

可重复读

当隔离级别为可重复读的时候,就避免了不可重复读,这是因为一个事务只在第一次 SELECT 的时候会获取一次 ReadView,而后面所有的 SELECT 都会复用这个ReadView

在这里插入图片描述

总结

本文介绍了MVCCREAD COMMITTDREPEATABLE READ这两种隔离级别下事务在执行快照读操作时访问记录的版本链的过程。这样使不同事务的读-写操作并发执行,从而提升系统性能。

核心点在于 ReadView 的原理,READ COMMITTDREPEATABLE READ这两个隔离级别的一个很大不同就是生成ReadView的时机不同:

  • READ COMMITTD在每一次进行普通SELECT操作前都会生成一个ReadView
  • REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查询操作都重复使用这个ReadView就好了。

🌈

说明: 执行DELETE语句或者更新主键的UPDATE语句并不会立即把对应的记录完全从页面中删除,而是执行一个所谓的delete mark操作; 相当于只是对记录打上了一个删除标志位,这主要就是为MVCC服务的

通过MVCC可以解决:

  1. 读写冲突问题: 通过MVCC可以让读写互相不阻塞,即读不阻塞写,写不阻塞读,这样就可以提升数据库并发处理能力

  2. 降低了死锁的概率: 这是因为MVCC采用了乐观锁的方式. 读取数据时并不需要加锁,对于写操作,也只锁定必要的行

  3. 解决快照读的问题: 当我们查询数据库在某个时间点的快照时,只能看到这个时间点之前事务提交更新的结果,而不能看到这个时间点之后事务提交的更新结果

如果本篇文章对你有所帮助的话, 不要忘了给我点个赞哦~ 笔芯💞

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

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

相关文章

VSCode Live Server 插件安装和使用

VSCode Live Server是一个由Ritwick Dey开发的Visual Studio Code扩展插件&#xff0c;它提供了一个带有实时重载功能的本地开发服务器。在VSCode中安装和使用Live Server插件进行实时预览和调试Web应用程序。这将大大提高前端开发效率&#xff0c;使网页设计和开发变得更为流畅…

MC1.12.2 macOS高清修复OptiFine运行崩溃

最近在玩RLCraft&#xff0c;在windows中运行正常的&#xff0c;移植到macOS中发现如果加载OptiFine模组就会崩溃 报错日志 报错日志如下&#xff0c;其中已经包含了各种版本信息&#xff0c;我就不单独说明了。这里说一下&#xff0c;报错的时候用的是oracle jdk x64的&…

医学图像分割半监督学习记录

半监督学习中&#xff0c;一部分数据带标签&#xff0c;一部分不带标签&#xff0c;在模型训练过程中&#xff0c;带标签的数据我们注重分类&#xff0c;无标签的数据我们注重分布。 半监督坚持一致性正则&#xff08;consistency regularization&#xff09;来进行半监督学习&…

12 USART串口通讯

1 串口物理层 两个设备的“DB9接口”之间通过串口信号建立连接&#xff0c;串口信号线中使用“RS232标准”传输数据信号。由于RS232电平标准的信号不能直接被控制器直接识别&#xff0c;所以这些信号会经过“电平转换芯片”转换成控制器能识别的“TTL校准”的电平信号&#xff…

工程水印相机结合图纸,真实现场时间地点,如何使用水印相机,超简单方法只教一次!

在工程管理领域&#xff0c;精准记录现场信息至关重要。水印相机拍照功能&#xff0c;为工程人员提供了强大的现场信息记录工具&#xff0c;助力工程管理和统计工程量&#xff0c;更可以将图片分享到电脑、分享给同事&#xff0c;协同工作。 一、打开图纸 打开手机版CAD快速看图…

abap安装cl_json类

文章来自 SAP根据源码导入/ui2/cl_json类 - pikeduo - 博客园 新建一个se38程序&#xff0c;把源码放到里&#xff0c;源码如下 *----------------------------------------------------------------------* * CLASS zcl_json DEFINITION *----------------------------…

day09_kafka高级

文章目录 kafka高级今日课程内容核心概念整理Kafka的数据位移offset**为什么 Kafka 的 offset 就像是“书签”&#xff1f;****实际意义** Kafka的基准/压力测试测试生产的效率测试消费的效率 Kafka的分片与副本机制kafka如何保证数据不丢失生产者端Broker端消费者端相关参数 K…

vue2制作长方形容器,正方形网格散点图,并且等比缩放拖动

需求&#xff1a;有个长方形的容器&#xff0c;但是需要正方形的网格线&#xff0c;网格线是等比缩放的并且可以无线拖动的&#xff0c;并且添加自适应缩放和动态切换&#xff0c;工具是plotly.js,已完成功能如下 1.正方形网格 2.散点分组 3.自定义悬浮框的数据 4.根据窗口大小…

Spring Boot 2 学习指南与资料分享

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域&#xff0c;Spring Boot 2 凭借其卓越的特性&#xff0c;为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2&#xff0c;以下这份精心…

【PyQt】如何在mainwindow中添加菜单栏

[toc]如何在mainwindow中添加菜单栏 如何在mainwindow中添加菜单栏 主要有两种方法&#xff1a; 1.直接创建mainwindow进行添加 2.使用ui文件加载添加 第二种方法更为常见&#xff0c;可以应用到实际 1.直接创建mainwindow进行添加 import sysfrom PyQt5.QtWidgets import …

Vue如何构建项目

目录 1.安装Node.js 2.换源(建议) 3.选择一个目录 4.创建一个vue项目 5.验证是否成功 1.安装Node.js 安装18.3或更⾼版本的 Nodejs 点击下载->Node.Js中文网 node -v npm -v 安装好后在windows的cmd窗口下运行 如果能运行出结果就说明安装好了。 2.换源(建议) //…

uniapp 小程序 textarea 层级穿透,聚焦光标位置错误怎么办?

前言 在开发微信小程序时&#xff0c;使用 textarea 组件可能会遇到一些棘手的问题。最近我在使用 uniapp 开发微信小程序时&#xff0c;就遇到了两个非常令人头疼的问题&#xff1a; 层级穿透&#xff1a;由于 textarea 是原生组件&#xff0c;任何元素都无法遮盖住它。当其…

[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们&#xff0c;今天带来《c语言》游戏中[三子棋boss]速通教程&#xff01;我们的目标是一边编写博文&#xff0c;一边快速用c语言实现三子棋游戏。准备好瓜子&#xff0c;我们计时开始&#xff01; 前期规划 在速通中&#xff0c;我们必须要有清晰的前期规划&#xf…

Chatper 4: Implementing a GPT model from Scratch To Generate Text

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.1 Coding an LLM architecture4.2 Normalizing activations with layer normalization4.3 Implementing a feed forward network with GELU activations4.4 Adding shortcut connections4.5 Connecting at…

【Vim Masterclass 笔记13】第 7 章:Vim 核心操作之——文本对象与宏操作 + S07L28:Vim 文本对象

文章目录 Section 7&#xff1a;Text Objects and MacrosS07L28 Text Objects1 文本对象的含义2 操作文本对象的基本语法3 操作光标所在的整个单词4 删除光标所在的整个句子5 操作光标所在的整个段落6 删除光标所在的中括号内的文本7 删除光标所在的小括号内的文本8 操作尖括号…

Termora跨平台 SSH/SFTP/Terminal 客户端工具

前言 Termora一款强大的终端模拟与SSH客户端工具&#xff0c;集SFTP传输、跨平台兼容、Zmodem协议、SSH端口转发、配置同步、宏录制、关键词高亮、密钥管理、多会话命令发送及数据加密于一体&#xff0c;专为追求高效远程工作的您设计。无论是开发、管理还是日常任务&#xff…

音视频入门基础:RTP专题(1)——RTP官方文档下载

一、引言 实时传输协议&#xff08;Real-time Transport Protocol&#xff0c;简写RTP&#xff09;是一个网络传输协议&#xff0c;由IETF的多媒体传输工作小组1996年在《RFC 1889》中公布的。 RTP作为因特网标准在《RFC 3550》有详细说明。而《RFC 3551》详细描述了使用最小…

JVM之垃圾回收器ZGC概述以及垃圾回收器总结的详细解析

ZGC ZGC 收集器是一个可伸缩的、低延迟的垃圾收集器&#xff0c;基于 Region 内存布局的&#xff0c;不设分代&#xff0c;使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记压缩算法 在 CMS 和 G1 中都用到了写屏障&#xff0c;而 ZGC 用到了读屏障 染色指针&a…

Redis复制(replica)

Redis主从复制 [Redis主从复制]&#xff08;replica&#xff09;是一个多Redis实例进行数据同步的过程&#xff0c;其中一个实例是主实例&#xff08;Master&#xff09;&#xff0c;其他实例是从实例&#xff08;Slave&#xff09;。主实例负责处理命令请求&#xff0c;而从实…

React:构建用户界面的JavaScript库

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…