谈谈MVCC机制

2024-04-01 08:36
文章标签 机制 mvcc 谈谈

本文主要是介绍谈谈MVCC机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在MySQL中,MVCC(多版本并发控制)是InnoDB存储引擎使用的并发控制机制。它提供对数据的并发访问,并确保多用户环境中数据的一致性和隔离性。

InnoDB通过“Undo log”存储每条记录的多个版本,提供历史记录供读取,并允许不同的事务访问不同的数据版本。在事务期间,客户端只能看到当前事务开始之前提交的记录以及当前事务内所做的修改。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。

隔离级别

MySQL中有4种隔离级别:

READ UNCOMMITED

当前事务可以读取未提交的数据。这些数据可能会回滚,所以我们将未提交的数据称为脏数据,这种问题称为脏读。

READ COMMITED

当前事务确实可以读取已提交的数据,因此不存在脏读问题。但是,如果当前事务多次读取同一条记录,则可能检索到不同的数据。这是因为,在当前事务期间,可能有其他事务修改并提交了该记录。此问题称为不可重复读。

REPETABLE READ

事务多次读取特定的记录集,即使其他事务在事务过程中修改或提交对这些记录的更改,它也始终会获得这些记录的相同值。但是,如果我们在当前事务中多次执行“SELECT COUNT(*) FROM {table_name}”,我们可能会看到不同的结果,这个问题称为幻读。

REPEATABLE READ 是 MySQL InnoDB 中的默认隔离级别。

SERIALIZABLE

所有事务都强制排序,解决了脏读、不可重复读、幻读等问题。但Serialized隔离级别性能较差,因此在实际中很少使用。

MVCC 仅适用于 READ COMMITTED 和 REPEATABLE READ 隔离级别,因为 READ UNCOMMITTED 始终读取最新记录,而 SERIALIZABLE 会为其读取的所有记录添加锁。

概念

TRANSACTION ID

当一个新的事务开始时,它会得到一个自增的事务ID,通过它InnoDB可以知道每个事务的执行顺序。

隐藏列

InnoDB中的每条记录都有两个隐藏列“db_trx_id”和“db_roll_pointer”,如果表中没有主键或非空唯一键,InnoDB将生成一个隐藏的自增列“db_row_id”。

字段名称描述
db_trx_id记录操作该行的事务的事务id
db_roll_pointerundo指针,指向该行的undo日志

InnoDB 在撤消日志中记录“插入”、“更新”和“删除”操作。然而,对于“删除”操作,InnoDB实际上将其记录为“更新”操作,即通常所说的“软删除”。InnoDB 不是物理删除该行,而是更新“已删除标志”来指示该行已被逻辑删除。此方法允许检索该行的先前版本,如果该行被永久删除,则无法检索先前版本。

当前读

一些 SQL 语句,例如“SELECT * ... LOCK IN SHARE MODE(共享锁)”、“SELECT * ... FOR UPDATE(独占锁)”、“UPDATE”、“DELETE”和“INSERT”, 考虑当前的读取操作。这些操作读取该行的最新版本。在读取过程中,InnoDB通过对当前记录加锁来确保没有其他事务可以修改当前记录。

快照读

没有加锁的 SELECT 语句被视为快照读取操作,通过 MVCC 读取所需的版本。快照读取无锁,有效提升事务性能。

本质上,快照是一种以空间换取时间的方式。

Undo log

Undo log存储修改行的先前版本。在行被修改之前,InnoDB会将当前版本复制到Undo log中,Undo log具有以下功能:

  • 如果事务回滚,InnoDB可以找到以前的版本来恢复。

  • 如果当前版本对于当前事务不可见,则会通过undo log查找可见版本。

前面提到,InnoDB将删除操作记录为更新操作,因此Undo Log中只有两种操作:

  • Insert undo log:由insert操作产生,仅用于事务回滚,事务提交后可立即丢弃。

  • 更新undo log:由更新操作生成,不仅用于事务回滚,还用于快照读取。

版本链

当多个事务同时操作同一条记录时,每个事务都会生成一个新的版本,这些版本通过 db_roll_pointer 形成一个链表,称为版本链。

 

Read View

ReadView是事务执行快照读取时生成的记录快照。

读取视图存储当前事务开始之前的所有活动事务。有 4 个重要属性:

  • trx_ids:活动事务ID(不包括当前事务和已提交事务)。

  • low_limit_id:分配的下一个交易ID。

  • up_limit_id:trx_ids中的最小交易id,如果trx_ids为空,则up_limit_id等于low_limit_id。

  • Creator_trx_id:生成读取视图的事务ID。

以下规则用于检查记录是否对当前事务可见:

  • 如果访问版本的事务ID=creator_trx_id,则表示当前事务访问了自己修改过的记录,则该版本对当前事务可见。

  • 如果访问版本的事务ID < up_limit_id,则说明生成该版本的事务在当前事务生成ReadView之前已经提交,因此该版本可以被当前事务访问。

  • 如果访问版本的事务ID > low_limit_id 值,则说明生成该版本的事务是在当前事务生成ReadView之后打开的,因此当前事务无法访问该版本。

  • 如果访问版本的事务ID在up_limit_id和m_low_limit_id之间,则需要判断该版本的事务ID是否在trx_ids列表中。如果是,说明该版本生成的事务在ReadView创建时仍然处于活动状态,该版本无法访问。

  • 如果没有,说明创建ReadView时生成该版本的事务已经提交,可以访问该版本。

MVCC实现原理

了解了上面的概念后,MVCC的实现就很好理解了。

查询流程

  1. 获取交易自己的交易ID,称为trx_id。(这不是在 SELECT 语句期间获得的,而是在事务开始时获得的,即执行 BEGIN 时获得的。)

  2. 检索 ReadView(仅在 SELECT 语句期间生成)。

  3. 在数据库表中,如果找到数据,则将其与ReadView中的事务版本号进行比较。4、如果不符合ReadView的可见性规则,则需要Undo Log中的历史快照,直到返回符合规则的数据。

InnoDB通过ReadView和Undo Log的结合来实现MVCC。Undo Log 存储历史快照,而 ReadView 的可见性规则有助于确定当前版本数据的可见性。

这篇关于谈谈MVCC机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866704

相关文章

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了

Spring中事务的传播机制

一、前言 首先事务传播机制解决了什么问题 Spring 事务传播机制是包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。 事务的传播级别有 7 个,支持当前事务的:REQUIRED、SUPPORTS、MANDATORY; 不支持当前事务的:REQUIRES_NEW、NOT_SUPPORTED、NEVER,以及嵌套事务 NESTED,其中 REQUIRED 是默认的事务传播级别。

多头注意力机制(Multi-Head Attention)

文章目录 多头注意力机制的作用多头注意力机制的工作原理为什么使用多头注意力机制?代码示例 多头注意力机制(Multi-Head Attention)是Transformer架构中的一个核心组件。它在机器翻译、自然语言处理(NLP)等领域取得了显著的成功。多头注意力机制的引入是为了增强模型的能力,使其能够从不同的角度关注输入序列的不同部分,从而捕捉更多层次的信息。 多头注意力机

Linux-笔记 线程同步机制

目录 前言 实现 信号量(Semaphore) 计数型信号量 二值信号量  信号量的原语操作 无名信号量的操作函数 例子 互斥锁(mutex) 互斥锁的操作函数 例子 自旋锁 (Spinlock) 自旋锁与互斥锁的区别 自旋锁的操作函数 例子 前言         线程同步是为了对共享资源的访问进行保护,确保数据的一致性,由于进程中会有多个线程的存在,

Spring 集成 RabbitMQ 与其概念,消息持久化,ACK机制

目录 RabbitMQ 概念exchange交换机机制 什么是交换机binding?Direct Exchange交换机Topic Exchange交换机Fanout Exchange交换机Header Exchange交换机RabbitMQ 的 Hello - Demo(springboot实现)RabbitMQ 的 Hello Demo(spring xml实现)RabbitMQ 在生产环境

Rust:Future、async 异步代码机制示例与分析

0. 异步、并发、并行、进程、协程概念梳理 Rust 的异步机制不是多线程或多进程,而是基于协程(或称为轻量级线程、微线程)的模型,这些协程可以在单个线程内并发执行。这种模型允许在单个线程中通过非阻塞的方式处理多个任务,从而实现高效的并发。 关于“并发”和“并行”的区别,这是两个经常被提及但含义不同的概念: 并发(Concurrency):指的是同时处理多个任务的能力,这些任务可能在同一时

ROS话题通信机制实操C++

ROS话题通信机制实操C++ 创建ROS工程发布方(二狗子)订阅方(翠花)编辑配置文件编译并执行注意订阅的第一条数据丢失 ROS话题通信的理论查阅ROS话题通信流程理论 在ROS话题通信机制实现中,ROS master 不需要实现,且连接的建立也已经被封装了,需要关注的关键点有三个: 发布方(二狗子)订阅方(翠花)数据(此处为普通文本) 创建ROS工程 创建一个ROS工程

Java面试题:内存管理、类加载机制、对象生命周期及性能优化

1. 说一下 JVM 的主要组成部分及其作用? JVM包含两个子系统和两个组件:Class loader(类装载)、Execution engine(执行引擎)、Runtime data area(运行时数据区)、Native Interface(本地接口)。 Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)装载class文件到Runtim

【笔记】事务隔离级别以及MVCC解决幻读

事务提交可能碰到的问题: (1)脏读:事务1对数据进行修改但还没提交,事务2读取修改后的数据,之后事务1执行错误,回滚了,此时事务2的数据是错误的脏数据。 (2)不可重复读:事务1读取数据1后,事务2对数据1进行修改,之后事务1的再次读取数据1时,发现前后读取结果不一致 (3)幻读:事务1根据条件查询到一批数据后,事务2删除或增加或修改了某些数据,之后事务1再次根据条件查询,发现读取的数据数量不对

C++初学者指南第一步---14.函数调用机制

C++初学者指南第一步—14.函数调用机制 文章目录 C++初学者指南第一步---14.函数调用机制1.记住:内存的结构2.函数调用是如何工作的3. 不要引用局部变量4. 常见编译器优化5. Inlining内联 1.记住:内存的结构 堆(自由存储) 用于动态存储期对象,例如 std::vector 的内容。空间大,可以用于大容量存储(大多数用于主内存)。可以根据需要分配