1.MVCC功能
MVCC(多版本并发控制)是 MySQL InnoDB 实现高并发读写的核心机制,它通过保存数据的多个版本来实现读写不阻塞,提高了数据库的并发性能。
2 MVCC核心思想
"MVCC 的核心思想是:为每个事务创建一个数据快照,不同事务看到的数据版本可能不同。这样就实现了:
-
读不阻塞写:读取历史版本
-
写不阻塞读:修改创建新版本
-
避免了大量的锁竞争"
2. 关键组成部分
"MVCC 主要依赖于三个关键部分:
① 隐藏字段:
-
DB_TRX_ID:最近修改的事务ID -
DB_ROLL_PTR:指向 undo log 的回滚指针 -
DELETE_BIT:删除标记
② ReadView(读视图):
相当于事务的快照,包含:
-
m_ids:当前活跃事务ID列表 -
min_trx_id:最小活跃事务ID -
max_trx_id:最大分配事务ID+1
③ Undo Log(回滚日志):
存储数据的历史版本,形成版本链"
3. 工作流程
"以 SELECT 查询为例:
-
首先获取当前事务的 ReadView
-
读取数据行的最新版本
-
检查该版本的
DB_TRX_ID:-
如果小于
min_trx_id:可见(事务已提交) -
如果大于等于
max_trx_id:不可见(事务后开始) -
如果在
m_ids中:不可见(事务进行中) -
否则:可见
-
-
如果不可见,通过
DB_ROLL_PTR找到 undo log 中的上一个版本,重复判断"
4. 不同隔离级别的差异
"不同隔离级别下 MVCC 的表现不同:
-
RC(读已提交):每次 SELECT 都生成新 ReadView
-
RR(可重复读):事务第一次 SELECT 时生成 ReadView,后续复用
-
RU(读未提交):直接读最新数据,不用 MVCC
-
Serializable(串行化):退化为加锁读写,不用 MVCC"
5、实际事务场景演示(隔离级别:可重复读)
事务 1(读事务,TRX_ID=100)
BEGIN; -- 事务启动,分配 TRX_ID=100
-- 第一次查询 user 表
SELECT * FROM user WHERE id=1; -- 结果:name=Alice, age=20
- 生成 Read View1:此时无其他活跃事务,
m_ids=[],min_trx_id=100,max_trx_id=101。 - 版本判断:行数据的
DB_TRX_ID为插入时的事务 ID(假设为 99),满足99 < 100,可见,返回结果。
事务 2(写事务,TRX_ID=101)
BEGIN; -- 分配 TRX_ID=101
UPDATE user SET age=22 WHERE id=1; -- 修改 id=1 的数据
-- 此时事务 2 未提交
- 版本链变化:更新操作会将旧版本(age=20,
DB_TRX_ID=99)写入 undo log,新版本(age=22,DB_TRX_ID=101)留在数据页,DB_ROLL_PTR指向 undo log 中的旧版本。 - 事务 2 未提交,因此新版本的
DB_TRX_ID=101属于活跃事务,对其他事务不可见。
事务 1 再次查询(同一事务内)
-- 事务 1 未提交,再次查询同一数据
SELECT * FROM user WHERE id=1; -- 结果仍为:name=Alice, age=20
- 关键特性:可重复读隔离级别下,事务内仅在第一次查询时生成一次 Read View(Read View1 复用)。如果是读已提交就在每次select是生成新的readview
- 版本判断:新版本的
DB_TRX_ID=101满足100 ≤ 101 < 101不成立,且101在当前活跃事务 ID 集合中,因此不可见;转而通过DB_ROLL_PTR读取 undo log 中的旧版本(age=20),保证了可重复读。
事务 2 提交,事务 1 第三次查询
-- 先提交事务 2
COMMIT; -- 事务 2 提交,TRX_ID=101 变为非活跃
-- 事务 1 仍未提交,第三次查询
SELECT * FROM user WHERE id=1; -- 结果还是:name=Alice, age=20
- 原因:可重复读隔离级别下 Read View 复用,依旧用 Read View1 判断版本。新版本
DB_TRX_ID=101满足100 ≤ 101 < 101不成立,仍不可见,继续读取旧版本。
事务 1 提交后,新事务查询
-- 提交事务 1
COMMIT;
-- 开启新事务 3(TRX_ID=102)
BEGIN;
SELECT * FROM user WHERE id=1; -- 结果:name=Alice, age=22
- 生成 Read View2:此时无活跃事务,
m_ids=[],min_trx_id=102,max_trx_id=103。 - 版本判断:新版本
DB_TRX_ID=101 < 102,满足可见性规则,返回最新数据。
浙公网安备 33010602011771号