MVCC——一个我特别不想聊的技术


前言

提示:此处涉及到的点比较多,若是有什么疑问点欢迎下方交流
我最开始仅仅是在spring层面进行使用Mysql的事务,但是后来不知道什么时候忽然被面试官问到这个问题了,没办法问到了就整理一下吧。
整理了三天,总算是出来了,但是还没有到自己想要的那么精简
so,有好的意见记得找我哦


一、MVCC?官方一些解释

MVCC全称为Multi-Version Concurrency Control即多版本并发控制。
它是一种用于数据库管理系统中的并发控制的技术,
在许多数据库系统(如MySQL的InnoDB存储引擎、PostgreSQL等)中得到使用。

MVCC通过为数据库对象(如行记录)提供多个版本来实现在没有锁定资源的情况下进行并发访问,增强了读写(这两个是一个整体)操作的并发性能。

但是在我看来就是一个思想,我们实际上用到的就是一个读数据的级别(当前读还是快照读)和同时操作多张表的原子性要么都操作成功,要么都操作失败

二、介绍MVCC

1.并发控制的必要性

1、并发控制是数据库管理系统同步多个事务的行为
2、避免由于事务之间的相互影响引起的一系列问题。
如果不妥善处理,并发操作可能会导致数据不一致,
例如脏读(读取未提交的数据)。
不可重复读(一个事务内两次及以上读取不一致)。
幻读(同一个事务两次及以上读取时出现新的行)。
补充:其实我也搞不懂为什么要查询两次或者多次在一个事务中?
但是:MVCC主要是解决读-写和写-读场景下的并发问题,而不是写-写场景,写-写通常还需要依赖锁机制。

2. MVCC的定义及目的

MVCC是一种用来控制数据库并发访问的技术,允许不同的事务看到某个时间点的数据快照。MVCC的主要优势是它可以在不加锁的情况下使读取操作并行进行,从而大大提高了事务的处理速度,同时维护了数据的一致性。
这里的一致是在某些场景下(如RR)的同一个事务内的一致。

MVCC的优势在于:

  1. 减少了锁的需求:读取操作通常不需要锁定资源,这样减少了锁竞争,提高了并发度。
  2. 读写分离:读写操作能够相互独立进行,因此在很多情况下,对数据的写入(更新、删除)不影响到数据的读取。
  3. 避免了读写冲突:读者不会阻塞写者,写者也不会阻塞读者。(因为读取的就不是一个地方)

补充:在MySQL的InnoDB存储引擎中每行记录都有隐藏的系统列如下:
DB_TRX_ID(最近修改事务的ID)
DB_ROLL_PTR(撤回指针,指向undo log的记录)
DB_ROW_ID(当未定义聚集索引时的隐藏的行ID)
以支持MVCC的实现。当你在执行SELECT、UPDATE、DELETE等操作时,InnoDB会通过MVCC机制确保每个事务都能正确地看到它应该看到的数据版本。

3、MVCC的核心机制和组件

Undo Log版本链:

当数据被修改时,其原版本并不会立即被覆盖,而是被记录在Undo Log中并生成版本链(类似于双向裂变)。如果需要,可以通过Undo Log找回之前的数据版本。这个机制使得数据库能够支持事务的回滚以及提供旧数据版本给不同的事务访问。

ReadView:

在事务开始时,系统会生成一个ReadView,其中记录了活跃的事务及其ID。ReadView确保了在事务执行期间,即使外部数据发生变化,事务也能继续看到一致的数据视图。还有最新的事务id以及最小事务id

4. 隔离级别与M

### MySQL 事务与 MVCC 实现原理 #### 一、事务的概念及其特性 在数据库环境中,事务是指一系列作为一个整体执行的操作序列。这一系列操作要么全部成功完成并永久生效;如果其中任何一个环节失败,则整个事务都会回滚至初始状态,确保数据一致性[^1]。 - **原子性(Atomicity)**:事务中的所有操作视为单一工作单元,该单元内各项更改应同生共死。 - **一致性(Consistency)**:事务前后需保持一致的状态转换,即遵循预定义规则。 - **隔离性(Isolation)**:各并发运行的事务间相互独立不受干扰。 - **持久性(Durability)**:一旦提交,即使发生系统崩溃也能够恢复成果。 #### 二、MVCC概述 为了提升并发处理能力的同时保障读写的正常交互,MySQL引入了多版本并发控制(MVCC)[^2]。其核心在于维护同一份记录的不同时间点上的多个版本,以此支持不同类型的读取行为——快照读与当前读: - **快照读(Snapshot Read)**:无需加锁即可获取指定时刻的数据视图,适用于大多数SELECT查询场景; - **当前读(Current Read)**:涉及锁定机制以防止其他会话修改正在访问的对象实例,常用于UPDATE/DELETE以及特定条件下带有FOR UPDATE或LOCK IN SHARE MODE修饰符的SELECT语句中。 #### 三、InnoDB存储引擎下的MVCC实现细节 作为MySQL默认使用的高性能事务型表管理器,InnoDB实现了上述提到的两种主要读取模式,并通过以下组件共同作用达成高效稳定的并发控制效果[^3]: - **隐藏列**:每行记录额外携带两个隐含属性`DB_TRX_ID`(最近更新此条目的事务ID)`DB_ROLL_PTR`(指向undo日志的位置),用作判断可见性的依据之一; - **Undo Log**:当某笔交易对现有资料进行了变更时,旧版会被复制到undo log区域保存起来直到不再需要为止(比如超出了必要的保留期限或是相关联的事物已经结束); - **ReadView**:每当启动一个新的只读类事物之前都要构建一个read view对象,里面包含了创建瞬间活跃着的所有活动事物列表以及其他必要信息用来决定哪些历史版本是可以被看见的。 #### 四、可见性逻辑判定流程 针对某个给定的记录版本R,假设现在有一个正在进行中的事务T想要对其进行读取,那么根据如下准则来确定是否能观察到它: 1. 若R是在T开启之后才产生的变动,则不可见; 2. 假设R是由另一个尚未完结且位于T之前的事务S所引起的变化,此时要看S是否处于已准备提交但还未正式commit阶段: - 是 -> R暂时不可见; - 否 -> 继续下一步骤; 3. 检查产生R的那个事务U是否存在于当前T持有的readview之内: - 存在-> 不可见 ; - 缺失-> 可见; 此外还有专门针对某些特殊情况设计的小于最低限度id比较规则等辅助手段帮助更精准地界定可视范围边界条件[^4]。 ```sql -- 示例SQL展示如何查看当前系统的最小未分配事务ID SHOW ENGINE INNODB STATUS\G ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值