前言

        多版本并发控制(MVCC)是 MySQL InnoDB 存储引擎实现高性能事务的核心机制。它通过创建数据快照,使得读写操作可以无锁并发,极大地提升了数据库的并发性能。本文将深入探讨 MVCC 的工作原理、实现细节以及它与事务隔离级别的紧密关系。

一、 MVCC 要解决什么问题?

        在高并发场景下,数据库事务处理主要面临三种操作组合:

  • 读-读:无需任何控制,不会产生问题。

  • 写-写:必须通过加锁(行锁、表锁等)实现串行化,保证数据一致性。

  • 读-写:如果采用加锁的方式,读操作会阻塞写操作,写操作也会阻塞读操作,严重影响并发性能。

MVCC 的终极目标就是优雅地解决 读-写冲突,实现无锁的非阻塞并发读

二、 MVCC 的实现基石

        MVCC 的实现依赖于两个核心部分:数据的版本链事务的读视图 (Read View)

  1. 数据的版本链 (Undo Log) InnoDB 的每行记录中都包含两个重要的隐藏字段:

    • DB_TRX_ID (6字节):记录最后一次插入或更新该行数据的事务 ID。

    • DB_ROLL_PTR (7字节):回滚指针,指向该行数据的前一个版本(存储在 Undo Log 中)。 每次对记录进行更新时,都会将旧值写入 Undo Log,然后 DB_ROLL_PTR 会形成一个指向旧版本记录的链表,即版本链。链首是最新的记录,链尾是最旧的记录。

  2. 事务的读视图 (Read View) Read View 是事务在执行快照读(普通 SELECT 语句)时产生的读视图,它决定了当前事务能看到哪个版本的数据。 它主要包含以下关键属性:

    • m_ids:创建 Read View 时,系统中所有活跃(尚未提交)事务的事务 ID 集合。

    • min_trx_id:m_ids 集合中的最小值。

    • max_trx_id:创建 Read View 时,系统尚未分配的下一个事务 ID(并非 m_ids 中的最大值)。

    • creator_trx_id:创建该 Read View 的事务的事务 ID。

三、 可见性算法

        有了版本链和 Read View,就可以根据以下规则判断某个版本的记录是否对当前事务可见:

  1. 如果数据版本的 DB_TRX_ID 小于 min_trx_id,说明该版本在 Read View 创建前已提交,可见

  2. 如果数据版本的 DB_TRX_ID 大于等于 max_trx_id,说明该版本是由在 Read View 创建之后才启动的事务生成的,不可见。需要沿着版本链继续查找旧版本。

  3. 如果数据版本的 DB_TRX_ID[min_trx_id, max_trx_id) 区间内:

    • DB_TRX_ID m_ids 集合中,说明创建 Read View 时该事务仍活跃,其修改不可见

    • DB_TRX_ID 不在 m_ids 集合中,说明创建 Read View 时该事务已提交,其修改可见

  4. 如果当前记录对自己的事务做了修改(DB_TRX_ID == creator_trx_id),那么该版本总是可见的。

四、 MVCC 与隔离级别

        MVCC 的行为因事务隔离级别而异,核心区别在于 Read View 的生成时机

  • READ COMMITTED (读已提交)每次执行快照读时都会生成一个新的 Read View。这会导致每次读都能看到其他事务已提交的最新修改,从而产生“不可重复读”现象。

  • REPEATABLE READ (可重复读):只在第一次执行快照读时生成一个 Read View,后续所有读操作都复用这个视图。这就保证了在整个事务过程中,看到的数据内容是一致的,实现了可重复读。

五、说人话(个人理解)

        对于Mysql的MVCC他解决的问题是在事务并发情况下,对于读+写操作的无锁解决方案。

        在事务并发场景下会出现读+读、读+写、写+写这三种组合,其中对于读+读是无需干预的,能够保证并发场景下数据的一致性以及隔离性。对于写+写操作就需要按照一定次序串行执行了,对于该问题就需要锁来实现,如果不加锁的话是无法保证数据的一致性以及隔离性的。这个问题不在MVCC讨论的范畴中,主要解决方式与Mysql的锁相关。此处不再赘述。对于读+写操作在解决方案上可以通过锁来保证数据的一致性但是加锁就会导致锁的竞争问题进而影响整体Mysql的并发度问题导致命令执行效率下降。此时MVCC机制就实现了无锁的情况下舍弃数据实时性为代价提高事务并发效率。因为在一定场景下可以接受数据出现一定程度的不一致问题,因此可以牺牲此部分来追求并发度的提升。

        对于MVCC机制他的实现基础,即立足点是针对数据表中的数据进行不同版本的控制,针对数据不同版本判断各个事务对于数据的可见性。即事务对应的版本对应所查询的数据的版本是否合理。进而引出了快照读这个操作。上述两个关键点:”事务的版本”和“数据的版本”是MVCC机制实现的基础。

        其中数据的版本通过每行数据中几个隐藏字段进行标识:trx_id字段标识了最后一次修改/增加改行数据的事务id。roll_pointer字段指向该行数据上个版本的数据信息。在事务执行过程中会将这些信息记录到undo log日志中,通过该日志可以实现事务回滚以及MVCC。

        事务的版本控制通过建立readview来控制。readview包含信息为:m_ids记录了当前readview创建时刻所有活跃的事务(已创建但是未提交的事务)。min_trx_id记录创建readview时最小的活跃事务id。max_trx_id记录创建readview时最大的活跃事务id。create_trx_id记录创建readview时分配给当前事务的id,该字段为全局自增字段。通过trx_id和roll_pointor字段可以对数据建立一个版本链。然后每个事务的readview为该事务创建时刻对当前数据库事务处理情况的一个快照,通过对比当前事务需要查询的数据版本链信息可以得出当前事务可见的数据版本。

        这个具体的规则为:当数据trx_id小于事务readview的min_trx_id时,证明此时数据行最后一次修改的事务是在当前事务创建之前就已经提交了,所以是合理的,因此是对于该事务而言是可见的。当trx_id大于事务readview的max_trx_id时,证明此时数据行最后一次修改的事务是在事务创建之后又新建的事务,此时在时间线上该数据行的版本是先于当前事务的,所以该数据行对于事务而言是不可见的,需要通过roll_pointor字段查询旧版本的数据行。如果trx_id位于readview的min_trx_id和max_trx_id之间时,证明此数据行最后一次修改的事务是与当前事务是位于同一时间线的,证明是同一版本,但是修改该数据行的事务是否提交这个还需要判断,因此进一步判断该trx_id是否存在于m_ids列表中,如果存在,证明这两个事务都是活跃的,此时不能保证该数据行是否修改完成,所以是不可见的。而如果不存在m_ids列表中时,证明修改该数据行的事务已经提交,此时是可见的。

        而对应MVCC的控制也有级别之分。其中就是可重复读级别和读已提交级别。 对于两者的区别是两者的readview创建时机不同。其中读已提交级别他的readview创建是在每一次快照读时都会重新创建,更新其中的m_ids等字段,此时他的并发程度更高,因为该级别每一次快照读都会放大数据行的版本可见区间。但是会在数据一致性上带来不可重复读的问题,也就是一个事务两次读取同一数据不一致的问题。因为他在每次快照读时都会重建readview,如果第一次和第二次查询期间有其他事务提交对任务的修改,此时就会出现不可重复读的问题。而可重复读的readview创建时机是在事务第一次创建时进行创建,后续不会新建。此时对于可重复读隔离级别而言他的快照读操作就定格在了事务创建的那一刻了,此时就算有其他事务在第一次查询和第二次查询期间他都只会查询到第一次的数据行,因为第二次的数据行对于该隔离级别而言是不可见的。但是也会有一定问题就是幻读问题。

 更多资料:0voice · GitHub

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

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

相关文章

景区负氧离子气象站:引领绿色旅游,畅吸清新每一刻

在绿色旅游成为消费主流的今天,游客对 “清新空气” 的需求不再是模糊的期待,而是可感知、可选择的具体体验。景区负氧离子气象站的出现,正以科技之力重塑绿色旅游格局,让 “畅吸清新每一刻” 从口号变为触手可及的现实&#xff0…

Pytorch笔记一之 cpu模型保存、加载与推理

Pytorch笔记一之 cpu模型保存、加载与推理 1.保存模型 首先,在加载模型之前,我们需要了解如何保存模型。PyTorch 提供了两种保存模型的方法:保存整个模型和仅保存模型的状态字典(state dict)。推荐使用第二种方式&…

当AI在代码车间组装模块:初级开发者的创意反成「核心算法」

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录当AI在…

技术视界 | 跨域机器人通信与智能系统:打破壁垒的开源探索

8 月 16 日,在 OpenLoong 社区举办的第九期线下分享会上,国家地方共建人形机器人创新中心的软件开发负责人 Amadeus 博士带来了一场主题为“跨域机器人通信与智能系统:打破行业壁垒的创新方案”的演讲。深入探讨了当前机器人领域的一个关键痛…

Android入门到实战(八):从发现页到详情页——跳转、传值与RecyclerView多类型布局

一. 引言在上一篇文章里,我们从零开始实现了 App 的 发现页面,通过网络请求获取数据,并使用 RecyclerView 展示了剧集列表。但光有发现页还不够,用户在点击一部剧时,自然希望进入到一个更详细的页面,去查看…

【工具】41K star!网页一键变桌面应用

项目中遇到了一个需要将现有的 web 页面打包成一个 桌面应用 的需求。 最一开始想到的是 Electron,但是它还需要一些开发工作并且打包后的应用体积比较大,调研后发现了开源工具 Pake。 它能让你用最轻量的方式,把任何网页一键打包成跨平台桌…

浪潮CD1000-移动云电脑-RK3528芯片-2+32G-安卓9-2种开启ADB ROOT刷机教程方法

浪潮CD1000-移动云电脑-RK3528芯片-232G-安卓9-2种开启ADB ROOT刷机教程方法 往期文章: 浪潮CD1000-移动云电脑-RK3528芯片-232G-安卓9-开启ADB ROOT破解教程 地址1:浪潮CD1000-移动云电脑-RK3528芯片-232G-开启ADB ROOT破解教程-CSDN博客 中国移动浪潮…

Day23_【机器学习—聚类算法—K-Means聚类 及评估指标SSE、SC、CH】

一、聚类算法概念属于无监督学习算法,即有特征无标签,根据样本之间的相似性,将样本划分到不同的类别中。所谓相似性可以理解为欧氏距离、曼哈顿距离、切比雪夫距离... 。分类按颗粒度分为:粗聚类、细聚类。按实现方法分为&#xf…

android seekbar显示刻度

SeekBar简介 SeekBar是Android中的一个可交互UI组件,允许用户通过拖动滑块在特定范围内选择数值。继承自ProgressBar,但增加了用户手动调节功能,常用于音量控制、亮度调节等场景。 核心属性 android:maxHeight // 背景高度 android:progres…

【高并发内存池】五、页缓存的设计

文章目录Ⅰ. page cache页缓存的结构设计Ⅱ. 完善central cache中的 get_span() 函数Ⅲ. 实现页缓存获取span对象的接口Ⅰ. page cache页缓存的结构设计 ​ 首先页缓存还是一个哈希桶的结构,但是和前两者不同的是,页缓存的哈希桶中存放的是一个或者多个…

Elasticsearch(text和keyword)区别分析

text:全文检索类型,经过分词处理,支持模糊匹配‌ keyword:精确匹配类型,适用于聚合、排序和过滤‌ text 1. 核心属性 ‌analyzer属性‌: 指定用于索引和搜索的分词器 默认使用标准分析器(Standard Analyzer) 示例:"analyzer": "ik_max_word"(中文…

通过tailscale实现一台电脑上vscode通过ssh连接另一台电脑上的VMware Linux 虚拟机

当需要通过一台windows电脑上的vscode来ssh连接另一台电脑上的linux虚拟机进行远程操作,可以通过tailscale来实现。 Linux虚拟机上安装tailscale 由于挂代理下载仍然很慢,而清华镜像源又没有tailscale的软件包,所以可以通过下载 DEB 包安装…

[Upscayl图像增强] docs | 前端 | Electron工具(web->app)

链接:https://upscayl.org/docs:Upscayl Upscayl是一款桌面应用程序,允许用户使用人工智能放大和增强图像。 提供了一个用户友好的图形界面(渲染器用户界面),用户可以选择图像或文件夹,从多种AI…

阿里云通义MoE全局均衡技术:突破专家负载失衡的革新之道

MoE模型的基本原理与核心价值 混合专家模型(Mixture of Experts,MoE)是当前AI大模型领域最重要的架构创新之一,其核心思想是通过多个“专家”网络协同处理输入数据,并由门控网络动态选择或组合各个专家的输出&#xf…

macOS中设置环境变量的各文件及作用域

在 macOS 中,~/.zshrc 和 ~/.bash_profile 是 Shell 的配置文件,用于设置环境变量、命令别名、启动命令等。它们在你每次打开终端时会被自动加载。文件对应 Shell作用~/.zshrcZsh(macOS Catalina 及以后默认)每次打开新的终端窗口…

【华为培训笔记】OptiX OSN 9600 设备保护专题

OptiX OSN 9600 设备保护专题 1、光层保护 定义 方式 应用

Python开篇撬动未来的万能钥匙 从入门到架构的全链路指南

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…

LabVIEW 与 PLC 通讯

在工业自动化领域,LabVIEW 与 PLC 的通讯极为关键,它能实现设备间高效的数据交互与协同运作。接下来,将从应用场景、软件架构、功能实现、特点、开发问题及解决方法等层面展开阐述。 应用场景​ 智能工厂生产线监控系统中,LabVIE…

11-FreeRTOS任务相关的其他API函数

数据来源地址:gitee.com FreeRTOS任务相关的其他API函数 一、FreeRTOS任务相关的其他API函数介绍 1、FreeRTOS任务相关API函数介绍(部分常用的) 答: 二、任务状态查询API函数 1、获取任务优先级函数 答: UBaseType_t uxTaskPriorityGet…

ECMAScript(2)核心语法课件(Node.js/React 环境)

📚 ECMAScript 核心语法课件(Node.js/React 环境) 1. 变量与作用域 变量声明方式 var:函数作用域,存在变量提升(hoisting)console.log(a); // undefined(变量提升) var a…