首页 > 其他分享 >MVCC 详解

MVCC 详解

时间:2024-08-19 21:23:23浏览次数:12  
标签:事务 ReadView 生成 trx 详解 版本 MVCC id

MVCC 简单理解

MVCC,全称 Multi-Version Concurrency Control,是多版本并发控制的意思。

在高并发情况下操作数据库可能会出现脏写、脏读、不可重复度、幻读这四个问题。通过 MVCC 可以实现在不加锁的前提下避免一些问题。

MVCC 的实现原理

多版本

首先,我们引入一个概念,即行数据的版本。每次通过事务对行数据进行更新的时候,都会生成一个新的数据版本,并记录事务的唯一 id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。

下图记录了某一行数据的变更过程,图中虚线框里是同一行数据的 4 个版本,当前最新版本是 V4,k 的值是 22,它是被 transaction id 为 25 的事务更新的,因此它的 row trx_id 也是 25。

图中的虚线箭头,就是 undo log(回滚日志)。而 V1、V2、V3 并不是物理上真实存在的,而是每次需要的时候根据当前版本和 undo log 计算出来的。比如,需要 V2 的时候,就是通过 V4 依次执行 U3、U2 算出来。

image.png

一致性视图(Read View)与数据版本可见性规则

一个事务对某条记录进行读操作时,会查看这一条记录的一系列事务 id(由 undo log 构成的版本链中的事务 id),并根据事务的隔离级别(“读已提交”、“可重复读”)去选择生成 Read View 的方式,通过比较事务 id 来确定可见的版本。

实现原理是:在事务创建的时候,InnoDB 会构建一个视图数组用来存储“活跃”的事务的 id。这里的“活跃”是指:启动了但还没有提交。

该视图数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。

这个视图数组 + 高水位,就组成了当前事务的一致性视图(read-view)。

视图数组、低水位、高水位、当前事务 id 可记为:

  • m_ids:表示在生成 ReadView 时当前系统中活跃的事务(创建了但还没有提交的事务)的事务id列表。
  • min_trx_id:表示在生成 ReadView 时当前系统中活跃的事务中最小的事务 id,也就是 m_ids 中的最小值。
  • max_trx_id:表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
  • creator_trx_id:表示生成该 ReadView 的事务的事务 id。

是基于数据的 row trx_id 和这个一致性视图的对比结果,即可判断某一行数据的哪个版本是可见的。

数据版本可见性规则:

image.png

  • 如果被访问版本的 trx_id 值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。对应黄色区块。
  • 如果被访问版本的 trx_id 值大于或等于 ReadView 中的 max_trx_id 值,表明生成该版本的事务在当前事务生成 ReadView 后才开启,所以该版本不可以被当前事务访问。对应红色区块。
  • 如果被访问版本的 trx_id 值小于 ReadView 中的 min_trx_id 值,表明生成该版本的事务在当前事务生成 ReadView 前已经提交,所以该版本可以被当前事务访问。对应黄色区块。
  • trx_id 值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断一下 trx_id 值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问,对应黄色区块;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问,对应绿色区块。

需要注意的是:上图的 id 并不是从左到右递增的,已提交的 id 可能会比活跃的 id 大。

不同隔离级别生成 Read View

不同隔离级别产生 Read View 的方式是不同的:

  • READ COMMITTED(读取已提交)——每次读取数据前都生成一个 Read View
  • REPEATABLE READ —— 仅第一次读取数据时生成一个 Read View

快照读与当前读

我们前面提到的实际上都是 MVCC 中的“快照读”,对应的就是最常见的不加锁的查询,如:

mysql> select k from t where id=1;

而事务中的 update 语句,使用的是“当前读。它用到了这样一条规则:更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。

因此,在下面的例子中,事务 B 读到的 k = 3。

image.png

事实上,如果把事务 A 的查询语句 select * from t where id=1 修改一下,加上 lock in share mode 或 for update,返回的 k 的值也会是 3。下面这两个 select 语句,就是分别加了读锁(S 锁,共享锁)和写锁(X 锁,排他锁)。

mysql> select k from t where id=1 lock in share mode;
mysql> select k from t where id=1 for update;

参考

标签:事务,ReadView,生成,trx,详解,版本,MVCC,id
From: https://blog.csdn.net/weixin_43987408/article/details/141335291

相关文章

  • APP安全检测报告内容详解
    一、APP安全检测的必要性APP安全检测是确保移动应用安全的重要一环。在开发过程中,由于技术、人员和管理等方面的原因,APP可能存在各种安全漏洞和风险。这些漏洞一旦被黑客利用,可能导致用户数据泄露、恶意代码注入、应用被篡改等严重后果。因此,对APP进行安全检测,及时发现并修复......
  • SpringCloud:服务保护和分布式事务详解
    ♥️作者:小宋1021......
  • re模块详解
    正则表达式(RegularExpression,简称regex或regexp)是一种文本模式,包括普通字符(例如,a到z之间的字母)和特殊字符(称为“元字符”)。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在编程和数据处理中,正则表达式极其强大,可以用来搜索、编辑或操作文本和......
  • 字符函数与字符串函数详解
    ......
  • IDEA常用快捷键大全(详解)
    前言IDEA中提供了很多快捷键,点击File-->Settings-->keymap便可进入看到IDEA提供的快捷键。我们也可以搜索和自定义所有快捷键,下面给出的是IDEA中默认的快捷键;一.Ctrl相关Ctrl+F在当前文件进行文本查找(必备)Ctrl+R在当前文件进行文本替换(必备)Ctrl+Z撤销(必备......
  • C/C++语言基础--指针三大专题详解2(指针与数组关系,动态内存分配,代码均可)
    本专栏目的更新C/C++的基础语法,包括C++的一些新特性前言指针是C/C++的灵魂,和内存地址相关联,运行的时候速度快,但是同时也有很多细节和规范要注意的,毕竟内存泄漏是很恐怖的指针打算分三篇文章进行讲解,本专题是二,介绍了指针和数组的关系、动态内存如何分配和释放等问题专题......
  • 常见的排序算法汇总(详解篇)
    目录排序的概念以及运用排序的概念1.插入排序1.1直接插入排序1.1.1 基本思想1.1.2代码实现直接插入排序的特征总结:1.1.3希尔排序(缩小增量排序)......
  • 意向共享锁与意向排它锁:详解与应用
    在数据库系统中,锁机制是保证数据一致性和完整性的关键。除了行级锁和表级锁外,还有一种锁类型,它在数据库的事务处理中扮演着重要的角色——意向锁(IntentionLocks)。在这篇博客中,我们将详细讲解意向共享锁(IntentionSharedLock)和意向排它锁(IntentionExclusiveLock)的概念、作用及......
  • MySQL 排他锁之表级锁:使用与实例详解
    在数据库系统中,锁机制是确保数据一致性、完整性的重要手段。MySQL中的排他锁(ExclusiveLock)是防止数据在修改过程中被其他事务访问或修改的关键工具。排他锁不仅可以作用于单行数据,还可以作用于整个表。当排他锁用于表级别时,它可以阻止其他事务对表的任何操作,从而确保数据的一致性......
  • MySQL 排他锁之行级锁:使用与实例详解
    在MySQL中,排他锁(ExclusiveLock),也称为写锁(WriteLock),是确保数据一致性的重要工具。当一个事务对某行数据加上排他锁时,其他事务既不能读取也不能修改该数据。这种锁通常在进行更新或删除操作时自动应用,以防止数据冲突。本文将通过具体实例来展示排他锁的使用方法。1.什么是排他锁......