【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理

news2024/11/23 19:04:52

前言: 

在当今互联网时代,数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言,高效地处理并发访问和事务管理是至关重要的。多版本并发控制(MVCC)是一种数据库事务处理的技术,旨在提高并发性和数据一致性,而MySQL是其中一个广泛采用MVCC的数据库管理系统

在本文中,我们将深入探讨MVCC的概念、原理和实现方式,特别关注MySQL中MVCC的实现。我们将探讨MVCC是如何克服传统数据库锁定机制的局限性,从而实现更高的并发性和更好的数据一致性。通过深入了解MVCC,读者将能够更好地理解MySQL的工作原理,并能够优化数据库设计和性能调优。

目录

前言: 

当前读:

快照读:

MVCC:

实现原理:

RC隔离级别下:

RR隔离级别下:

总结: 


本片的数据库表的属性,如果没有特殊说明,那默认就是(innoDB+RR) 

 在介绍MVCC之前,我们要先介绍两个概念:

当前读:

读取的是当前记录的最新版本,读取的时候还需要保证其他并发事务不能修改当前记录,会对当前记录加锁。对于我们日常的select......lock in share modeselect......for updateupdateinsertdelete都是一种当前读。

快照读:

读取的是数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。常见隔离级别下的select:

  • RC:每一次select,都生成一个快照读。
  • RR:开启一个事务之后,只有第一个select语句才会生成一张快照,此后读的都是快照中的数据,直到事务提交。
  • Serializable:快照读退化为当前读。

我们用一个例子来看一下,以下为我们模拟的表数据(数据库默认使用InnoDB,隔离级别为RR):

我们同时开启两个MySQL客户端来对这张表进行操作:

 先尝试读取数据,这种能读取到表中最新数据的模式就叫做当前读。现在我们来看看什么是快照读

1.创建两个MySQL客户端,都开启事务,并且在第一个MySQL客户端中做一次SQL查询。

2.在第二个MySQL客户端中对id为1的用户姓名进行修改,并且提交当前事务。

3.重新在第一个MySQL客户端中查询。

我们会发现:第一个MySQL客户端中读取的数据竟然是老数据。这是为什么呢?

原因很简单:之前我们讲过MySQL的innoDB引擎在RR的隔离级别下,当我们开启事务的时候,只有第一次Select是当前读,读取完之后会生成一张快照,此后这个事务中后续的所有相同的select语句读的都是第一次Select所生成的快照。

当我们提交第一个MySQL客户端的时候之后,再尝试select * from emp ,会发生什么呢?

我们可以发现,此时就可以读取到正常的数据了。也就是说在InnoDB中select....... in share mode语句就是当前读。


MVCC:

        MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于数据库管理系统中实现并发控制的技术。它允许多个事务同时对数据库进行读写操作而不会导致数据不一致或丢失。

MVCC 的核心思想是在数据库中维护多个数据版本,并根据事务的隔离级别来决定哪个版本对特定事务是可见的。快照读就为MVCC提供了一个非阻塞读的功能,MVCC的具体实现还需要依赖数据库中的三个隐式字段undo log 日志readView

实现原理:

1.记录中的隐藏字段:当我们尝试创建一张表之后,InnoDB会自动为我们加上两个字段:

  • DB_TRX_ID:最近一次修改或删除记录的事务ID
  • DB_ROLL_PTR:回滚指针,指向记录的上一个版本
  • DB_ROW_ID:隐藏主键,如果表结构没有主键,将会生成该隐藏字段

2.undo log 日志:

  • Undo 日志记录了对数据的修改操作,包括插入、更新、删除等。
  • Undo 日志中记录了修改前的数据值,以及撤销操作所需的信息,以便在事务回滚或 MVCC 中使用。
  • 当事务提交的时候,相关的Undo log 日志就被标记为可回收状态,可以在之后的操作中被回收

如果是insert语句,那么Undo log日志只需要在回滚的时候需要,当事务提交之后,会被立即删除。

如果是update,delete的时候,产生的undo log日志不仅在回滚的时候需要,在产生快照读的时候也需要,因此其不会被立即删除。(undo log 中残留的旧版本数据可供其他并发事务进行快照读)

3.undo log 版本链:

(本图来自黑马程序员,偷懒了没画,如有侵权,请联系我立即删除)

 

 4.readview

readview是快照读SQL执行时候MVCC提取数据的依据,记录并且维护当前事务活跃的事务(未提交)的id。

ReadView包含了四个核心字段:

字段含义
m_min_trx_id最小活跃事务ID
max_try_id预分配事务ID,其实是当前最大事务ID+1(因为事务是自增的)
m_ids当前活跃的事务ID集合
creator_trx_idReadView创建者的事务ID

那么基于readView,其实就已经决定了哪些事务可以访问undo的哪些数据版本:

InnoDB不同的隔离级别,生成ReadView的实际不同:

  • READ COMMITTED : 在事务每一次执行快照读的时候生成ReadView。
  • REPEATABLE READ:仅在事务中第一次执行快照读的时候生成ReadView,后续一致复用该ReadView。 

我们来口述以下在这两种不同的隔离级别下,具体读取的是哪一个版本的快照:

RC隔离级别下:

其实就是去做比较,将undo log 中的DB_TRX_ID套入比较规则中,只要一个比较符合规则,那么就可以进行读取该版本的数据

经过一个一个的尝试,我们可以发现DB_TRX_ID=2的时候 ,符合比较规则2:trx_id<min_trx_id。

因此我们事务5中第一次查询id为30的记录的时候,实际上读的是DB_TRX_ID=2的快照读。

其实这四个比较看起来比较唬人,其实很好理解:RC是读已提交,也就是说我们的事务5在读取的时候,要么读取在自己之前已经提交了事务的版本数据要么读取自己修改的数据。那我们返回表中看:只有事务2在表5第一条语句之前提交了事务,因此我们事务5可以读事务2的数据版本。

因此我们可以看到RC可以防止脏读,因为它用的数据版本就是一个已经提交了事务的数据版本,自然不可能读到其他事务还没有提交的数据

RR隔离级别下:

RR隔离级别下,单个事务中一直复用的是该事务第一次查询版本快照。在当前案例中,事务5一直复用的就是自己第一次查询id等于30的数据记录。

因此我们可以看到RR可以防止重复读,这是因为事务一直使用的是自己第一次产生的readview,readview一样,那么匹配到的历史数据版本就一样,如果我们一直读取的都是一个历史版本数据,自然不可能出现两次读取结果不一致的情况了。

总结: 

        MVCC 是数据库系统中一种重要的并发控制机制,它通过在数据库中维护多个版本的数据来支持事务的并发执行,并提供了一致性读取和隔离性的保证。在 MVCC 中,每个事务都可以看到一个独立的数据版本,这使得读操作不会被写操作所阻塞,从而提高了数据库的并发性能。

MVCC 的实现主要依赖于两个关键组件:Undo 日志和版本链。Undo 日志记录了事务执行过程中对数据所做的修改操作,用于在事务回滚或撤销时恢复数据到之前的状态。而版本链则是指数据库中维护的多个数据版本之间的关系,包括当前版本、已提交版本和未提交版本等。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

【数据结构练习题】队——1.用队实现栈2.用栈实现队

♥♥♥♥♥个人主页♥♥♥♥♥ ♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥ ♥♥♥♥♥上一章&#xff1a;堆的练习题♥♥♥♥♥ 文章目录 1.用队去实现栈1.1问题描述1.2思路分析1.3绘图分析1.4代码实现2.用栈实现队2.1问题描述2.2思路分析1.3绘图分析2.4代码实现 1.用队去实现…

doss攻击为什么是无解的?

这个让Google、亚马逊等实力巨头公司也无法避免的攻击。可以这么说&#xff0c;是目前最强大、最难防御的攻击之一&#xff0c;属于世界级难题&#xff0c;并且没有解决办法。 Doss攻击的原理不复杂&#xff0c;就是利用大量肉鸡仿照真实用户行为&#xff0c;使目标服务器资源…

【漏洞复现】WordPress Welcart 任意文件读取漏洞(CVE-2022-4140)

0x01 产品简介 Welcart 是一款免费的 WordPress 电子商务插件。Welcart 具有许多用于制作在线商店的功能和自定义设置。您可以轻松创建自己的原始在线商店。 0x02 漏洞概述 Welcart存在任意文件读取漏洞&#xff0c;未授权的攻击者可以通过该漏洞读取任意文件&#xff0c;获…

【无标题】系统思考—心智模式

“直到你使无意识变为有意识&#xff0c;它将指导你的生活并且你会称之为命运。”—卡尔荣格 心智模式深藏于我们内心之中&#xff0c;它潜移默化地影响着我们对世界的理解和判断。往往这些影响是如此隐蔽&#xff0c;以至于我们自己都未必察觉到是什么在驱动我们的选择、决策…

利用Python ARM网关仓储物流AGV小车控制器

在现代智慧物流体系中&#xff0c;高效的信息管理系统是物流中心实现精准跟踪货物、科学管理库存及优化配送路线的关键环节。通过采用ARM架构的工控机或网关&#xff0c;并结合Python的二次开发能力&#xff0c;可以有效集成并强化物流管理系统的数据处理与通信功能&#xff0c…

最坏情况为线性时间的第k大元素

在统计和数据分析中&#xff0c;我们经常会遇到求最大值、最小值、中位数、四分位数、Top K等类似需求&#xff0c;其实它们都属于顺序统计量&#xff0c;本文将对顺序统计量的定义和求解算法进行介绍&#xff0c;重点介绍如何在最差时间复杂度也是线性的情况下求解第k大元素。…

代码随想录:栈与队列4-6

20.有效的括号 题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一…

OpenHarmony分布式软总线API调用测试工具 softbus_tool使用说明

softbus_tool 是 OpenHarmony 分布式软总线 API 调用测试工具&#xff0c;文件结构如下图所示。 softbus_tool 能够将软总线 interfaces 目录下的一些常用接口集中起来&#xff0c;供设备间搭建一些场景时使用&#xff08;比如设备绑定、BR 组网&#xff0c;BLE 组网&#xff…

红豆Cat 1开源|项目三: 从0-1设计一款HTTP版本RTU(支持GNSS)产品的软硬件全过程

HTTP版RTU&#xff08;支持GNSS&#xff09;项目概述 RTU&#xff08;Remote Terminal Unit&#xff09;&#xff0c;中文即远程终端控制系统&#xff0c;负责对现场信号、工业设备的监测和控制。RTU是构成企业综合自动化系统的核心装置&#xff0c;通常由信号输入/出模块、微…

ArrayList中多线程的不安全问题

ArrayList中的不安全问题 正常的输出 List<String> list Arrays.asList("1","2","3"); list.forEach(System.out::println);为什么可以这样输出&#xff0c;是一种函数是接口&#xff0c;我们先过个耳熟 Arrys.asList是返回一个ArrayL…

Redis高级-分布式缓存RDB原理

分布式缓存 1.1.2.RDB原理 bgsave开始时会fork主进程得到子进程&#xff0c;子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。 fork采用的是copy-on-write技术&#xff1a; 当主进程执行读操作时&#xff0c;访问共享内存&#xff1b;当主进程执行写操…

振弦式应变计在岩土工程中的应用

岩土工程是土木工程的一个重要分支&#xff0c;主要研究岩石、土壤等天然材料的工程特性及其在工程中的应用。它涉及地基基础、边坡工程、隧道工程、水利水电工程等众多领域&#xff0c;是保障建筑物安全、稳定的基础性工程。 点击输入图片描述&#xff08;最多30字&#xff09…

rabbitmq延迟队列的使用

rabbitmq延迟队列的使用 1、场景&#xff1a; 1.定时发布文章 2.秒杀之后&#xff0c;给30分钟时间进行支付&#xff0c;如果30分钟后&#xff0c;没有支付&#xff0c;订单取消。 3.预约餐厅&#xff0c;提前半个小时发短信通知用户。 A -> 13:00 17:00 16:30 延迟时间&a…

再也不怕面试官问 OOM了,一次生产环境 Metaspace OOM 排查流程实操!

问题背景 小奎公司的运维同时今天反映核心业务一个服务目前 CPU 的使用率、堆内存、非堆内存的使用率有点高。刚反映没有过多久该服务就直接 OOM 了&#xff0c;以下是生产监控平台监控信息。 CPU 使用率监控 堆内存和非堆内存使用率 OOM 产生的日志报错信息 问题分析 根…

kali使用msf+apkhook520+cploar实现安卓手的攻击

学习网络安全的过程中&#xff0c;突发奇想怎么才能控制或者说是攻击手机 边找工作边实验 话不多说启动kali 一、使用msfapktool生成简单的木马程序 首先使用kali自带的msfvenom写上这样一段代码 选择安卓 kali的ip 一个空闲的端口 要输出的文件名 msfvenom -p android/met…

9个最受欢迎的开源自动化测试框架盘点!

自动化测试框架可以帮助测试人员评估多个Web和移动应用程序的功能&#xff0c;安全性&#xff0c;可用性和可访问性。尽管团队可以自己构建复杂的自动化测试框架&#xff0c;但是当他们可以使用现有的开源工具&#xff0c;库和测试框架获得相同甚至更好的结果时&#xff0c;通常…

ubuntu系统逻辑卷Logical Volume扩容根分区

Linux LVM详解 https://blog.csdn.net/qq_35745940/article/details/119054949 https://blog.csdn.net/weixin_41891696/article/details/118805670 https://blog.51cto.com/woyaoxuelinux/1870299 LVM&#xff08;Logical Volume Manager&#xff09;逻辑卷管理&#xff0c…

C++入门语法(命名空间缺省函数函数重载引用内联函数nullptr)

目录 前言 1. 什么是C 2. C关键字 3. 命名空间 3.1 命名空间的定义 3.2 命名空间的使用 4. C输入和输出 5. 缺省函数 5.1 概念 5.2 缺省参数分类 6. 函数重载 6.1 概念 6.2 为何C支持函数重载 7. 引用 7.1 概念 7.2 特性 7.3 常引用 7.4 引用与指针的区别 7…

OSCP靶场--Hetemit

OSCP靶场–Hetemit 考点(python代码注入 systemctrl提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.117 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 05:52 EDT Nmap scan report for 192.168.1…

详解多态、虚继承、多重继承内存布局及虚表(C++)

本篇文章深入分析多态、虚继承、多重继承的内存布局及虚函数表以及实现原理。编译器使用VS 2022&#xff0c;直接放结论&#xff0c;代码及内存调试信息在后文。 结论 内存布局 一个没有虚函数的类&#xff0c;它的大小其实就是所有成员变量的大小&#xff0c;此时它就是一个…