目录
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 只建一次并复用,保证“可重复读”。