当前位置: 首页 > article >正文

innodb如何实现mvcc的

InnoDB 实现 MVCC(多版本并发控制)的机制主要依赖于 Undo Log(回滚日志)Read View(读视图)隐藏的事务字段。以下是具体实现步骤和原理:


1. 核心数据结构

InnoDB 的每一行数据(聚簇索引记录)包含两个隐藏字段:

  • DB_TRX_ID:最近修改该行的事务 ID。
  • DB_ROLL_PTR:指向该行旧版本数据的回滚指针(即 Undo Log 的地址)。

2. Undo Log 与版本链

  • Undo Log 的作用
    每次对数据进行修改(INSERT/UPDATE/DELETE),InnoDB 会生成 Undo Log,记录修改前的数据镜像。
  • 版本链的构建
    通过 DB_ROLL_PTR 字段,将同一行数据的多个版本按修改顺序链接成链表。
    示例
    当前行 → [版本3: trx_id=300, roll_ptr → 版本2]  ↑  
    版本2 → [trx_id=200, roll_ptr → 版本1]  ↑  
    版本1 → [trx_id=100, roll_ptr → NULL]
    

3. Read View 的生成

当事务执行 一致性读(如 SELECT)时,InnoDB 为其生成一个 Read View,包含以下信息:

  • m_ids:当前活跃(未提交)的事务 ID 列表。
  • min_trx_idm_ids 中的最小事务 ID。
  • max_trx_id:下一个即将分配的事务 ID(即当前最大事务 ID +1)。
  • creator_trx_id:创建该 Read View 的事务 ID(仅当该事务自身有修改时存在)。

4. 数据可见性判断规则

对于某一数据行的版本,判断其对当前事务是否可见的规则如下:

  1. 版本的事务 ID < min_trx_id
    该版本已提交,可见。
  2. 版本的事务 ID ≥ max_trx_id
    该版本由未来事务生成,不可见。
  3. min_trx_id ≤ 版本的事务 ID < max_trx_id
    • 若版本的事务 ID 不在 m_ids,说明该事务已提交,可见。
    • 若版本的事务 ID m_ids,说明该事务未提交,不可见。
  4. 版本的事务 ID = creator_trx_id
    该版本由当前事务自身修改,可见。

5. MVCC 的查询流程

  1. 定位最新数据行:通过聚簇索引找到当前行的最新版本。
  2. 遍历版本链:从最新版本开始,根据 DB_ROLL_PTR 回溯旧版本。
  3. 可见性检查:对每个版本应用 Read View 规则,找到第一个可见的版本。

示例
假设事务 A(trx_id=200)的 Read View 中:

  • m_ids = [100, 300]
  • min_trx_id=100, max_trx_id=400

遍历某行的版本链:

  • 版本3(trx_id=300):在 m_ids 中 → 不可见。
  • 版本2(trx_id=200):等于 creator_trx_id → 可见(若事务 A 修改了该行)。
  • 版本1(trx_id=100):在 m_ids 中 → 不可见。
  • 版本0(trx_id=50):小于 min_trx_id → 可见。

最终事务 A 读取到版本0。


6. 不同隔离级别的实现差异

  • 读已提交(Read Committed)
    每次执行 SELECT 时生成新的 Read View,看到已提交的最新数据。
  • 可重复读(Repeatable Read)
    事务内第一次 SELECT 时生成 Read View,后续复用该视图,保证多次读取一致性。

7. Undo Log 的清理

  • Insert Undo Log:事务提交后立即删除(不参与 MVCC)。
  • Update/Delete Undo Log:需保留至所有可能访问旧版本的事务结束(通过 purge 线程异步清理)。

8. MVCC 与锁的协同

  • 写操作(UPDATE/DELETE)
    即使使用 MVCC,写操作仍需加锁(如行锁)避免脏写。
  • 读操作(SELECT)
    默认无锁,通过 MVCC 读取快照版本。若需锁定读,可加锁(如 SELECT ... FOR UPDATE)。

总结

InnoDB 通过以下机制实现 MVCC:

  1. 版本链:通过 DB_ROLL_PTR 链接数据的历史版本。
  2. Read View:判断事务可见性的依据。
  3. Undo Log:存储历史版本数据,支持版本链回溯。
  4. 隔离级别适配:通过动态生成或复用 Read View 实现不同隔离级别。
# MVCC 执行示例
事务A(trx_id=200)读取某行数据:
1. 找到最新版本(trx_id=300)。
2. 检查 Read View:m_ids=[100, 300], min=100, max=400。
3. trx_id=300 在 m_ids 中 → 不可见。
4. 回溯到版本2(trx_id=200),等于 creator_trx_id → 可见。

相关文章:

innodb如何实现mvcc的

InnoDB 实现 MVCC&#xff08;多版本并发控制&#xff09;的机制主要依赖于 Undo Log&#xff08;回滚日志&#xff09;、Read View&#xff08;读视图&#xff09; 和 隐藏的事务字段。以下是具体实现步骤和原理&#xff1a; 1. 核心数据结构 InnoDB 的每一行数据&#xff08…...

多模态大语言模型arxiv论文略读(四)

A Survey on Multimodal Large Language Models ➡️ 论文标题&#xff1a;A Survey on Multimodal Large Language Models ➡️ 论文作者&#xff1a;Shukang Yin, Chaoyou Fu, Sirui Zhao, Ke Li, Xing Sun, Tong Xu, Enhong Chen ➡️ 研究机构: 中国科学技术大学、腾讯优图…...

空对象模式(Null Object Pattern)在C#中的实现详解

一 、什么是空对象模式 空对象模模是靠”空对孔象式是书丯一种引施丼文行为,行凌,凌万成,个默疤"空象象象象来飞䛿引用用用用电从延盈盈甘仙丿引用用用职从延务在仅代砷易行行 」这种燕式亲如要目的片片 也说媚平父如如 核心思烟 定义一个人 派一个 &#xfffd; 创建…...

在kotlin的安卓项目中使用dagger

在 Kotlin 的 Android 项目中使用 ​​Dagger​​&#xff08;特别是 ​​Dagger Hilt​​&#xff0c;官方推荐的简化版&#xff09;进行依赖注入&#xff08;DI&#xff09;可以大幅提升代码的可测试性和模块化程度。 1. 配置 Dagger Hilt​​ ​​1.1 添加依赖​​ 在 bu…...

(三)链式工作流构建——打造智能对话的强大引擎

上一篇&#xff1a;&#xff08;二&#xff09;输入输出处理——打造智能对话的灵魂 在前两个阶段&#xff0c;我们已经搭建了一个基础的智能对话&#xff0c;并深入探讨了输入输出处理的细节。今天&#xff0c;我们将进入智能对话的高级阶段——链式工作流构建。这一阶段的目…...

python三大库之---pandas(二)

python三大库之—pandas&#xff08;二&#xff09; 文章目录 python三大库之---pandas&#xff08;二&#xff09;六&#xff0c;函数6.1、常用的统计学函数6.2重置索引6.3 遍历6.3.1DataFrame 遍历6.3.2 itertuples()6.3.3 使用属性遍历 6.4 排序6.4.1 sort_index6.4.2 sort_…...

php7.4.3连接MSsql server方法

需要下载安装Microsoft Drivers for PHP for SQL Server驱动&#xff0c; https://download.csdn.net/download/tjsoft/90568178 实操Win2008IISphp7.4.3连接SqlServer2008数据库所有安装包资源-CSDN文库 适用于 SQL Server 的 PHP 的 Microsoft 驱动程序支持与 SQL Server …...

Flask返回文件方法详解

在 Flask 中返回文件可以通过 send_file 或 send_from_directory 方法实现。以下是详细方法和示例: 1. 使用 send_file 返回文件 这是最直接的方法,适用于返回任意路径的文件。 from flask import Flask, send_fileapp = Flask(__name__)@app.route("/download")…...

JS中的Promise对象

基本概念 Promise 是 JavaScript 中用于处理异步操作的对象。它代表一个异步操作的最终完成及其结果值。Promise 提供了一种更优雅的方式来处理异步代码&#xff0c;避免了传统的回调地狱。 Promise 有三种状态 Pending&#xff08;等待中&#xff09;&#xff1a;初始状态&…...

macOS设置定时播放眼保健操

文章目录 1. ✅方法一&#xff1a;直接基于日历2. 方法二&#xff1a;基于脚本2.1 音乐文件获取(ncm转mp3)2.2 创建播放音乐任务2.3 脚本实现定时播放 1. ✅方法一&#xff1a;直接基于日历 左侧新建一个日历&#xff0c;不然会和其他日历混淆&#xff0c;看起来会有点乱 然后…...

Python 小练习系列 | Vol.14:掌握偏函数 partial,用函数更丝滑!

&#x1f9e9; Python 小练习系列 | Vol.14&#xff1a;掌握偏函数 partial&#xff0c;用函数更丝滑&#xff01; 本节的 Python 小练习系列我们将聚焦一个 冷门但高能 的工具 —— functools.partial。它的作用类似于“函数的预设模板”&#xff0c;能帮你写出更加灵活、优雅…...

记录学习的第二十三天

老样子&#xff0c;每日一题开胃。 我一开始还想着暴力解一下试试呢&#xff0c;结果不太行&#x1f602; 接着两道动态规划。 这道题我本来是想用最长递增子序列来做的&#xff0c;不过实在是太麻烦了&#xff0c;实在做不下去了。 然后看了题解&#xff0c;发现可以倒着数。 …...

Web品质 - 重要的HTML元素

Web品质 - 重要的HTML元素 在构建一个优秀的Web页面时,HTML元素的选择和运用至关重要。这些元素不仅影响页面的结构,还直接关系到页面的可用性、可访问性和SEO表现。本文将深入探讨一些关键的HTML元素,并解释它们在提升Web品质方面的重要性。 1. <html> 根元素 HTM…...

SpringBoot整合sa-token,Redis:解决重启项目丢失登录态问题

SpringBoot整合sa-token&#xff0c;Redis&#xff1a;解决重启项目丢失登录态问题 &#x1f525;1. 痛点直击&#xff1a;为什么登录状态会消失&#xff1f;2.实现方案2.1.导入依赖2.2.新增yml配置文件 3.效果图4.结语 &#x1f600;大家好&#xff01;我是向阳&#x1f31e;&…...

Python 字典和集合(子类化UserDict)

本章内容的大纲如下&#xff1a; 常见的字典方法 如何处理查找不到的键 标准库中 dict 类型的变种set 和 frozenset 类型 散列表的工作原理 散列表带来的潜在影响&#xff08;什么样的数据类型可作为键、不可预知的 顺序&#xff0c;等等&#xff09; 子类化UserDict 就创造自…...

npm fund 命令的作用

运行别人的项目遇到这个问题&#xff1a; npm fund 命令的作用 npm fund 是 npm 提供的命令&#xff0c;用于显示项目依赖中哪些包需要资金支持。这些信息来自包的 package.json 中定义的 funding 字段&#xff0c;目的是帮助开发者了解如何支持开源维护者。 典型场景示例 假…...

ES:账号、索引、ILM

目录 笔记1&#xff1a;账号权限查看、查看账号、创建账号等查看所有用户查看特定用户验证权限修改用户权限删除用户 笔记2&#xff1a;索引状态和内容的查看等查看所有索引查看特定索引内容查看索引映射查看索引设置查看索引统计信息查看ILM策略 笔记1&#xff1a;账号权限查看…...

哈希表(开散列)的实现

目录 引入 开散列的底层实现 哈希表的定义 哈希表的扩容 哈希表的插入 哈希表查找 哈希表的删除 引入 接上一篇&#xff0c;我们使用了闭散列的方法解决了哈希冲突&#xff0c;此篇文章将会使用开散列的方式解决哈希冲突&#xff0c;后面对unordered_set和unordered_map的…...

#在docker中启动mysql之类的容器时,没有挂载的数据...在后期怎么把数据导出外部

如果要导出 Docker 容器内的 整个目录&#xff08;包含所有文件及子目录&#xff09;&#xff0c;可以使用以下几种方法&#xff1a; 方法 1&#xff1a;使用 docker cp 直接复制目录到宿主机 适用场景&#xff1a;容器正在运行或已停止&#xff08;但未删除&#xff09;。 命…...

[蓝桥杯] 挖矿(CC++双语版)

题目链接 P10904 [蓝桥杯 2024 省 C] 挖矿 - 洛谷 题目理解 我们可以将这道题中矿洞的位置理解成为一个坐标轴&#xff0c;以题目样例绘出坐标轴&#xff1a; 样例&#xff1a; 输入的5为矿洞数量&#xff0c;4为可走的步数。第二行输入是5个矿洞的坐标。输出结果为在要求步数…...

Johnson算法 流水线问题 java实现

某印刷厂有 6项加工任务J1&#xff0c;J2&#xff0c;J3&#xff0c;J4&#xff0c;J5&#xff0c;J6&#xff0c;需要在两台机器Mi和M2上完 成。 在机器Mi上各任务所需时间为5,1,8,5,3,4单位; 在机器M2上各任务所需时间为7,2,2,4,7,4单位。 即时间矩阵为&#xff1a; T1 {5, …...

远程监控系统项目里练习

1、项目目标 设备端&#xff1a; &#xff08;1&#xff09;基于stm32mp157开发板&#xff0c;裁剪linux5.10.10&#xff0c;完成ov5640摄像头移植&#xff1b; &#xff08;2&#xff09;完成用户层程序&#xff0c;完成对摄像头的控制及与云端服务的数据交互。 云端&…...

安装并配置Maven

如图所示&#xff0c;解压安装包&#xff0c;配置环境变量&#xff0c;在bin目录那个界面新建文件夹repository&#xff0c;写上安装路径的坐标&#xff0c;修改Maven仓库镜像&#xff0c;输入cmd验证是否安装成功 <mirror><id>alimaven</id><mirrorOf>…...

PlatformIO 自定义脚本选择编译库源文件 - 设置只用于C++ 的编译选项

PlatformIO 只支持以文件夹为单位选择要编译的源文件&#xff0c;不像Keil 或者CMake&#xff0c;可以手动控制每一个源文件。而且默认只会将库的src 文件夹下的源文件全部加入编译。比如&#xff0c;某个库的文件结构如下&#xff1a; libx src include mem| a.c| b.c| c.c…...

dolphinscheduler单机部署链接oracle

部署成功请给小编一个赞或者收藏激励小编 1、安装准备 JDK版本:1.8或者1.8oracle版本&#xff1a;19Coracle驱动版本&#xff1a;8 2、安装jdk 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8 下载后上传到/tmp目录下。 然后执行下面命…...

MongoDB常见面试题总结(上)

MongoDB 基础 MongoDB 是什么&#xff1f; MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统&#xff0c;由 C 编写的。MongoDB 提供了 面向文档 的存储方式&#xff0c;操作起来比较简单和容易&#xff0c;支持“无模式”的数据建模&#xff0c;可以存储比较复杂…...

java基础 迭代Iterable接口以及迭代器Iterator

Itera迭代 Iterable < T>迭代接口(1) Iterator iterator()(2) forEach(Consumer<? super T> action)forEach结合Consumer常见场景forEach使用注意细节 (3)Spliterator spliterator() Iterator< T>迭代器接口如何“接收” Iterator<T>核心方法迭代器的…...

CentOS禁用nouveau驱动

1、验证 nouveau 是否在运行 lsmod | grep nouveau如果命令返回结果&#xff0c;说明 nouveau 驱动正在运行。 2、编辑黑名单文件 通过编辑黑名单配置文件来禁用 nouveau 驱动&#xff0c;这样在系统启动时不会加载它。 vi /etc/modprobe.d/blacklist-nouveau.conf修改以下…...

Linux 时间同步工具 Chrony 简介与使用

一、Chrony 是什么&#xff1f; chrony 是一个开源的网络时间同步工具&#xff0c;主要由两个组件组成&#xff1a; chronyd&#xff1a;后台服务进程&#xff0c;负责与时间服务器交互&#xff0c;同步系统时钟。chronyc&#xff1a;命令行工具&#xff0c;用于手动查看或修…...

C语言:字符串处理函数strstr分析

在 C 语言中&#xff0c;strstr 函数用于查找一个字符串中是否存在另一个字符串。它的主要功能是搜索指定的子字符串&#xff0c;并返回该子字符串在目标字符串中第一次出现的位置的指针。如果没有找到子字符串&#xff0c;则返回 NULL。 详细说明&#xff1a; 头文件&#xf…...