1.为什么需要MVCC

在并发场景下,读写操作会面临严重的冲突问题:

1.读操作如果遇到写操作,要么“读到未提交的脏数据”,要么“被写操作阻塞(等待锁释放)”;

2.写操作如果遇到读操作,要么“覆盖读操作需要的数据”,要么“被读操作阻塞”;

MVCC通过“多版本”解决了这个问题:写操作会生成新的数据版本,读操作读取旧的版本(不影响写),两者不干扰。

2.什么是MVCC

MySQL的MVCC(Multi-Version Concurrency Control,多版本并发控制)是InnoDB存储引擎实现高并发读写的核心操作。核心思想:为数据库中的每条记录维护多个版本,通过“版本链”和“可间性判断规则”,让不同实物在并发访问时,能够看到符合自己隔离级别的数据版本,从而避免读写冲突(读不阻塞写,写不阻塞读),同事保证事务隔离性。

3.MVCC的核心组成

MVCC的实现依赖三个关键组件:隐藏列(版本标识)Undo Log(版本存储)Read View(可见性判断)

3.1 隐藏列:记录的“版本身份证”

InnoDB为表中的每条记录添加了三个隐藏字段,用于记录标识的版本信息

  • DB_TRX_ID:记录最后一次修改该记录的事务ID(6字节)。每次事务对记录执行insert/update/delete时,都会将自己的事务ID写入该字段。
  • DB_ROLL_PTR:回滚指针(7字节)。指向该记录的“上个版本”在Undo Log中的位置(通过它可以串联所有的历史版本,形成“版本链”)。
  • DB_ROW_ID:记录的唯一标识(6字节)。如果表没有定义主键或唯一索引,InnoDB会用它作为默认聚簇索引(一般用不到,可忽略)。

3.2 Undo Log:版本的“历史记录馆”

Undo Log(回滚日志)是InnoDB用于存储“记录旧版本”的空间。当视为修改记录时,旧版本的数据不会被直接删除,而是被写入Undo Log,供后序“回滚”或“其他事务读取”使用。

与隐藏列相结合形成“版本链”,记录的“版本链”形成的过程如下:

  1. 初始插入一条数据时,DB_TRX_ID是插入事务的ID,DB_ROLL_PTR为null(无历史版本,新数据无历史版本)。
  2. 当事务A(事务ID=110)修改该记录时,InnoDB会先将旧版本数据写入Undo Log,然后更新记录的DB_TRX_ID=110,并将DB_ROLL_PTR指向Undo Log中的旧版本。
  3. 之后事务B(事务ID=220)再次修改该记录时,会将“事务A修改后的版本”写入Undo Log,更新DB_TRX_ID=220,DB_ROLL_PTR指向事务A版本再Undo Log的位置。
  4. 最终,通过DB_ROLL_PTR串联的Undo Log记录,形成了改记录的“版本链”(最新版本在表中,历史版本在Undo Log中)。

一条记录的版本链结构(简化):
当前记录(表中):

data:(name='HajiHang',age=21)|DB_TRX_ID=220|DB_ROLL_PTR——>Undo Log中的版本1

Undo Log:

Undo Log中的版本1(事务A修改后的版本):

data:(name='HajiHang',age=20)|DB_TRX_ID=110|DB_ROLL_PTR——>Undo Log中的版本0

Undo Log中的版本0(初始插入版本):

data:(name='HajiHang',age=19)|DB_TRX_ID=55|DB_ROLL_PTR——>null

3.3 Read View:版本的“可见性过滤器”

有了版本链后,事务如何判断“哪个版本的数据对自己可见”?这就需要Read View(读试图),它是一个“可见性判断规则集合”,用于确定当前事务能够看到版本链中的那个版本。

Read View包含4个核心变量(生成时确定):

  1. m_ids:生成Read View时,当前所有“活跃事务”(已启动但未提交)的事务ID集合(无序)
  2. min_trx_id:m_ids中的最小事务ID(当前活跃事务中最早启动的那个)
  3. max_trx_id:生成Read View时,“下一个将要分配的事务ID”(并非m_ids中的最大值,而是一个预分配的自增ID)
  4. creator_trx_id:当前生成Read View的事务自己的ID

4.可见性判断规则(核心)

设记录的版本对应的事务ID为trx_id,根据trx_id和Read View的变量对比:

  • 如果trx_id == creator_trx_id:该版本是当前事务自己修改的,可见(自己改的自己当然可以看到)
  • 如果trx_id < min_trx_id:该版本对应的事务在“当前Read View生成前”就已提交(因为它的ID比所有活跃事务的最小ID还小),可见。
  • 如果trx_id >= max_trx_id:该版本对应的事务在“当前Read View生成后”才启动(ID超过预分配的最大ID),不可见(还没提交,或刚启动)。
  • 如果min_trx_id <=trx_id <=max_trx_id:
    • 若trx_id在m_ids(活跃事务集合)中:说明该事务在Read View生成时还没提交,不可见;
    • 若trx_id不在m_ids中:说明该事务在Read View生成前已提交,可见;

5.MVCC与隔离级别的关系

MVCC的核心作用是实现隔离级别(ACID中的“I”隔离性)。InnoDB通过“Read View的生成时机”和“版本链”,在不同隔离级别下表现出不同的行为:

隔离级别MVCC行为(Read View生成时机)解决的问题
Read Uncommitted(读未提交)不使用MVCC(直接读取最新的版本)可能读到未提交的脏数据(脏读)
Read Committed(读已提交)每次执行select时,重新生成Read View避免脏读(只看到已提交的版本);但是可能出现“不可重复读”(两次查询Read View不同)
Repeatable Read(可重复读)仅在事务第一次select生成Read View,之后复用避免不可重复读(两次查询用同一个Read View,版本一致);但可能出现“幻读”(通过间隙锁解决)
Serializable(串行化)不依赖MVCC,直接通过加锁(读加共享锁,写加排它锁)实现完全串行化,无并发问题,性能低

6.补充:不同隔离级别涉及到的并发问题

不同隔离级别会产生不同的并发问题,核心问题包括脏读,不可重复读,幻读。

  • 脏读指的是一个事务读取到另一个为提交事务修改的数据。(事务A在修改name并未提交,事务B读取到了name,后事务A又进行修改并提交/或直接回滚,导入事务B读取到了一个临时,无效的数据)
  • 不可重复读指的是同一事务内,多次读取同一数据,结果因其他已提交事务的修改而不同。(事务A第一次读取name='HajiHang',事务B执行了修改操作将name改成了Hajimi,事务A再次读取name发现不是HajiHang了)
  • 幻读指的是同一事务内,多次执行相同的查询操作(通常是范围查询)时,结果集行数因其他一提交事务的插入/删除而变化(事务A查询score=90的人发现有5条数据,之后事务B插入一个90的数据,事务A再次查询score=90发现结果集变为6条)

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

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

相关文章

数据结构第2问:什么是算法?

算法 算法是一组用于解决具体问题的、明确的、有序的步骤或规则&#xff0c;能够在有限的时间内通过这些步骤得到问题的答案。 算法的5个重要特性&#xff1a; 有穷性&#xff1a;算法必须在有限的步骤内结束&#xff0c;不能无限循环&#xff0c;保证最终能够得到结果。确定性…

12-大语言模型—Transformer 打地基,下游任务盖出百样房,指标来验收|下游任务白话指南

目录 1、核心逻辑&#xff1a;Transformer 的 “语言处理闭环” 2、转导与感知 → 模型咋 “理解语言”&#xff1f; 2.1、 人类 vs 机器的 “语言理解逻辑” 2.2、 自注意力机制&#xff1a;模型 “理解语言” 的数学核心 2.2.1、通俗拆解 2.2.1.1、是什么&#xff1f; …

深入探索爬虫与自动化脚本:释放效率的利器

在当今信息爆炸的时代&#xff0c;高效获取和处理数据已成为核心竞争力。爬虫与自动化脚本正是解决这一痛点的关键技术——它们如同数字世界的勤劳助手&#xff0c;帮我们自动完成繁琐重复的任务。下面我们来系统了解这两项技术的核心要点、应用场景和最佳实践。一、爬虫与自动…

React函数组件的“生活管家“——useEffect Hook详解

&#x1f3af; React函数组件的"生活管家"——useEffect Hook详解 1. &#x1f31f; 开篇&#xff1a;从生活中的"副作用"说起 嘿&#xff0c;各位掘友们&#xff01;今天咱们来聊聊React函数组件里的一个“大管家”——useEffect Hook。你可能会问&#x…

python基础:request请求Cookie保持登录状态、重定向与历史请求、SSL证书校验、超时和重试失败、自动生成request请求代码和案例实践

Cookie保持登录状态cookie session鉴权机制 cookie是由web服务器保存在用户浏览器&#xff08;客户端&#xff09;上的小文本文件&#xff0c;他可以包含有关用户的信息。无论何时用户访问到服务器&#xff0c;都会带上该服务器的cookie信息&#xff0c;一般cookie都是有有效期…

Vulkan入门教程 | 第二部分:创建实例

前言&#xff1a;本教程为笔者依据教程https://docs.vulkan.net.cn/spec/latest/index.html#_about进行Vulkan学习并结合自己的理解整理的笔记&#xff0c;供大家学习和参考。 &#xff08;注意&#xff1a;代码仅为片段&#xff0c;非完整程序&#xff09; 学习前提&#xff1…

PHP云原生架构:容器化、Kubernetes与Serverless实践

引言 随着云计算的普及,PHP应用也在向云原生架构演进。本文将深入探讨PHP在云原生环境中的最佳实践,包括容器化部署、Kubernetes编排、Serverless架构以及云原生监控与日志方案,帮助开发者构建现代化、可扩展的PHP应用。 容器化PHP应用 基础Dockerfile优化 # 多阶段构建…

【华为机试】5. 最长回文子串

文章目录5. 最长回文子串描述示例 1示例 2示例 3示例 4提示解题思路方法一&#xff1a;中心扩展法&#xff08;推荐&#xff09;方法二&#xff1a;动态规划方法三&#xff1a;Manacher算法方法四&#xff1a;暴力解法代码实现复杂度分析测试用例完整题解代码5. 最长回文子串 …

【图像处理基石】如何对遥感图像进行实例分割?

遥感图像实例分割是指在遥感影像中&#xff0c;不仅要识别出不同类别的目标&#xff08;如建筑物、车辆、道路等&#xff09;&#xff0c;还要区分同一类别中的不同个体&#xff08;如建筑物1、建筑物2&#xff09;&#xff0c;并为每个实例生成精确的像素级掩码。 一、遥感图…

电子电气架构 --- 软件bug的管理模式

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

【每日一错】Oracle 19c CDB中如何启动一个PDB

文章目录题目扩展学习CDB与PDB的概念CDB&#xff0c;PDB结构优势总结题目 扩展学习 CDB与PDB的概念 在Oracle 12c及以上版本&#xff0c;Oracle引入了多租户架构&#xff0c;这种架构让数据库的管理和资源使用更加高效。它由两种主要组成部分组成&#xff1a; CDB&#xff0…

Android studio自带的Android模拟器都是x86架构的吗,需要把arm架构的app翻译成x86指令?

Android studio自带的Android模拟器都是x86架构的吗&#xff0c;需要把arm架构的app翻译成x86指令&#xff1f; deepseek回答&#xff1a; Android Studio 自带的官方模拟器&#xff08;Android Emulator&#xff09;主要提供基于 x86 架构的系统镜像。当运行 ARM 架构的应用…

Deep Learning_ Foundations and Concepts-Springer (2024)【拜读】20章3节

Diffusion Models 扩散模型 我们已经了解到&#xff0c;构建强大的生成模型的一种有效方法是&#xff1a;先引入一个关于潜在变量z的分布p(z)&#xff0c;然后使用深度神经网络将z变换到数据空间x。由于神经网络具有通用性&#xff0c;能够将简单固定的分布转化为关于x的高度灵…

Arduino与STM32:初学者该如何选择?

在电子爱好者和初学者的世界里&#xff0c;Arduino和STM32是两个经常被提及的名字。它们各自具有独特的优势和特点&#xff0c;适合不同类型的项目和需求。对于初学者来说&#xff0c;选择Arduino还是STM32&#xff0c;往往取决于个人的学习目标、项目需求以及预算。本文将详细…

创建型设计模式-工厂方法模式和抽象工厂方法模式

1、工厂方法模式 创建型设计模式之一 UML类图2、抽象工厂模式 也是创建型设计模式之一。虽然抽象工厂方法模式的类繁多&#xff0c;但是&#xff0c;主要分为4类。 AbstractFactory&#xff1a;抽象工厂角色&#xff0c;它声明了一组用于创建一种产品的方法&#xff0c;每一个方…

Hyperchain安全与隐私机制详解

一、核心安全机制1. 共识算法安全RBFT共识算法&#xff1a;改进型PBFT&#xff1a;基于PBFT算法优化&#xff0c;增加动态节点管理、失效数据恢复机制&#xff0c;提升系统容错性与可用性。性能指标&#xff1a;吞吐量稳定达3000-10000 TPS&#xff0c;交易执行时间控制在300ms…

Oracle优化学习十六

反连接反连接&#xff08;Anti Join&#xff09;是一种特殊的连接类型&#xff0c;与内连接和外连接不同&#xff0c;Oracle数据库里并没有相关的 关键字可以在SQL文本中专门表示反连接&#xff0c;所以这里把它单独拿出来说明。为了方便说明反连接的含义&#xff0c;我们用“t…

梳理一些 Docker 常用命令

以下是一些 Docker 常用命令&#xff0c;适用于日常开发、调试、部署等场景&#xff0c;分为几个常用类别&#xff1a;&#x1f4e6; 一、镜像&#xff08;Image&#xff09;相关命令命令说明docker images查看本地所有镜像docker pull <image>拉取镜像&#xff08;如 do…

C#_ArrayList动态数组

目录 ArrayList的特点 ArrayList 与普通数组的区别 使用示例&#xff1a; 普通数组 动态数组 主要方法和属性 属性&#xff1a; Count 获取动态数组的数据个数 读取某个位置的数据 // 索引 方法&#xff1a; Add 向集合末尾添加元素 Insert 在指定位置插入元…

Agent领域,近年来的前沿研究方向:多智能体协作、认知启发架构、伦理安全、边缘计算集成

Agent领域,近年来的前沿研究方向:多智能体协作、认知启发架构、伦理安全、边缘计算集成 在Agent领域,近年来的前沿研究方向主要集中在多智能体协作、认知启发架构、伦理安全、边缘计算集成以及生成式AI融合等方面。 一、多智能体协作与多模态任务 多智能体系统在复杂环境…