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

MVCC:数据库事务隔离的 “时空魔法”

目录

一、引入

二、概念

2.1 MVCC 是什么?

2.2 什么是版本链?

2.3 ReadView 是什么?

 2.4 可见性规则:

1. trx_id < min_trx_id:已提交,可见。

2. trx_id > max_trx_id:未开始,不可见。

3. trx_id in m_ids:活跃中,未提交,不可见。

4. trx_id == creator_trx_id:自己改的,可见。

2.5 RC 与 RR 的核心区别:ReadView 的生成时机


在默认隔离级别(REPEATABLE READ)下,InnoDB 的普通 SELECT 默认是快照读(底层就是MVCC实现)。

而快照读之所以出现,根本原因正是为了解决“共享锁(S 锁)与排他锁(X 锁)互斥”带来的读写阻塞问题

💡了解一下:不普通的SELECT读就是显式加锁的 SELECT (也就是手动加锁的情况)。

一、引入

MVCC(多版本并发控制)是MySQL实现高并发事务的核心机制,其核心在于通过版本链和ReadView实现不同隔离级别下的数据可见性控制。下面我将详细解释MVCC的工作原理,以及Read View在RC(读已提交)RR(可重复读)隔离级别下的不同表现。

二、概念

2.1 MVCC 是什么?

MVCC(Multi-Version Concurrency Control)是 InnoDB 实现高并发读写的机制。
它通过以下三部分协同工作:

  • 隐藏字段:每条记录有 trx_id(最近修改事务ID)和 roll_ptr(指向旧版本)。

  • Undo Log:保存数据的历史版本,形成版本链

  • ReadView:事务执行快照读时生成的“可见性快照”,决定当前事务能看到哪个版本的数据。

2.2 什么是版本链?

版本链 = 同一条记录被多次修改后,借助 Undo Log 形成的“历史快照链表”。

InnoDB 根据 roll_ptr 指针把旧版本串起来,快照读时顺着这条链找可见版本。

2.3 ReadView 是什么?

ReadView 是一个逻辑快照,包含以下关键信息:

  • m_ids:当前活跃的事务ID列表。

  • min_trx_id:最小活跃事务ID。

  • max_trx_id:下一个将分配的事务ID。

  • creator_trx_id:创建该 ReadView 的事务ID。

 2.4 可见性规则

遍历版本链,找到第一个满足以下条件的数据版本:

1. trx_id < min_trx_id:已提交,可见。
  • min_trx_id 是当前系统中最小活跃事务 ID

  • 如果某个数据版本的 trx_id 小于 min_trx_id,说明它早于所有当前活跃事务已经提交,所以可见

2. trx_id > max_trx_id:未开始,不可见。
  • max_trx_id 是系统下一个即将分配的事务 ID

  • 如果某个数据版本的 trx_id 大于 max_trx_id,说明这个版本是由未来事务生成的,还没开始,所以不可见

3. trx_id in m_ids:活跃中,未提交,不可见。
  • m_ids 是当前活跃事务列表

  • 如果某个数据版本的 trx_id 在这个列表中,说明这个事务还没提交,所以不可见

4. trx_id == creator_trx_id:自己改的,可见。
  • 如果某个数据版本的 trx_id 就是当前事务自己的 ID,那说明是自己修改的,自己当然能看到

2.5 RC 与 RR 的核心区别:ReadView 的生成时机

隔离级别ReadView 生成时机可见性表现
RC(读已提交)每次 SELECT 都新建 ReadView每次都能看到最新已提交的数据,可能会不可重复读
RR(可重复读)事务中第一次 SELECT 创建 ReadView,之后复用整个事务内看到的数据保持一致,避免不可重复读

MVCC 是底层机制,RC 和 RR 是它暴露出来的两种“快照策略”:

  • RC 每次快照读都生成新的 ReadView,看到最新已提交数据

  • RR 只在第一次快照读时生成 ReadView,之后复用该快照,保证可重复读

 简单而言,MVCC 通过 Undo 日志保存多版本数据,ReadView 控制“哪个版本可见”。
RC 每次查询都新建 ReadView,保证“读已提交”;RR 只建一次并复用,保证“可重复读”

http://www.lryc.cn/news/609039.html

相关文章:

  • mysql管理
  • 【Linux系统】进程间通信:匿名管道
  • http://localhost:8080/photos/xxx.png的本地图片访问方案
  • 常见的框架漏洞(Thinkphp,spring,Shiro)
  • io_submit系统调用及示例
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-54,(知识点:硬件设计流程)
  • 知识随记-----MySQL 连接池健康检测与 RAII 资源管理技术
  • vulnhub-noob靶机攻略
  • ICT模拟零件测试方法--电位器测试
  • 【QT】常⽤控件详解(二)windowOpacitycursorfontsetToolTipfocusPolicystyleSheet
  • 8.1.3 TiDB集群方案雨Replication原理
  • git用户设置
  • 嵌入式 C 语言入门:多文件编程实践笔记 —— 从文件创建到调用
  • Python Seaborn【数据可视化库】 全面讲解
  • C++ 之 【模拟实现 优先级队列】
  • Java 大视界 -- Java 大数据机器学习模型在金融市场情绪分析与投资决策辅助中的应用(379)
  • 控制建模matlab练习05:比例积分控制-①系统建模
  • 【游戏比赛demo灵感】Scenario No.9(又名:World Agent)
  • 【Python✨】解决 Conda 安装 MoviePy 报错问题
  • 【Linux系统编程】进程信号
  • Rust 同步方式访问 REST API 的完整指南
  • python学智能算法(三十一)|SVM-Slater条件理解
  • Rust:如何开发Windows 动态链接库 DLL
  • 【AI编程工具IDE/CLI/插件专栏】-国外IDE与Cursor能力对比
  • 08.Redis 持久化
  • Pytorch实现一个简单的贝叶斯卷积神经网络模型
  • (一)全栈(react配置/https支持/useState多组件传递/表单提交/React Query/axois封装/Router)
  • CICD--自动化部署--jinkins
  • TV电视版软件集合分享
  • 动感按钮:如何打造交互感十足的点击动画效果