08.MVCC原理常识原理
MVCC(多版本并发控制)是数据库系统中的一种乐观并发控制方式,通过可见性算法实现高效的并发访问。
MVCC的两种读形式包括快照读(无需加锁,读取当前事务可见版本)和当前读(读取最新版本,涉及增删改操作)。
MVCC通过隐藏字段(如RowID、事务ID、回滚指针)和undo log(记录事务操作的日志)来实现。
可见性算法通过比较事务ID和系统活跃事务列表判断数据对当前事务的可见性,从而避免了锁的使用带来的性能问题。
# 01.MVCC原理
# 1、MVCC概述
- MySQL 的 MVCC(多版本并发控制)机制用于
解决读写冲突
,保证事务的隔离性
- 其底层原理主要基于
每行数据
的版本管理
和事务的快照隔离
- 每当对行数据进行修改时,MySQL 会生成一个新的版本,而不是直接修改原有数据
- 这是通过在每行数据中增加两个隐藏列来实现的
- 一个是
trx_id
,表示修改该行的事务 ID - 另一个是
delete_flag
,用于标记行是否已被删除
- 一个是
# 2、快照读和当前读
快照读
:- 读取的只是当前事务的可见版本,不用加锁
- 而你只要记住 简单的 select 操作就是快照读(select * from table where id = xxx)
当前读
:- 读取的是当前最新版本,比如 特殊的读操作,更新/插入/删除操作
- 当前读会被其他事务的写操作阻塞,确保读取的是最新的数据状态
# 3、MVCC 实现原理
# 1)MVCC隐藏字段
- MVCC 使用了“三个隐藏字段”来实现版本并发控制
RowID | DB_TRX_ID | DB_ROLL_PTR | id | name | password |
---|---|---|---|---|---|
自动创建的id | 事务id | 回滚指针 | id | name | password |
RowID
:隐藏的自增ID
,当建表没有指定主键,InnoDB会使用该RowID创建一个聚簇索引DB_TRX_ID
:最近修改(更新/删除/插入)该记录的事务ID
DB_ROLL_PTR
:回滚指针,指向这条记录的上一个版本
删除标记(Delete Flag)
:指示该行是否已被逻辑删除
# 2)MVCC 的 可见性算法
undoLog
: 事务的回滚日志,是 可见性算法 的非常重要的部分,分为两类insert undo log
:- 事务在
插入新记录产生的undo log,当事务提交之后可以直接丢弃
- 事务在
update undo log
:事务在进行
update 或者 delete 的时候产生的 undo log
,在快照读的时候还是需要的,所以不能直接删除只有当系统没有比这个log
更早的read-view了的时候才能删除
ps:所以长事务会产生很多老的视图导致undo log无法删除 大量占用存储空间
read-view
: 读视图,是MySQL秒级创建视图的必要条件- 比如一个事务在进行 select 操作(快照读)的时候会创建一个 read-view ,这个read-view 其实只是三个字段
alive_trx_list
:read-view生成时所有活跃事务 ID 列表
up_limit_id
:记录上面的 alive_trx_list 中的最小事务 ID
low_limit_id
:目前已出现的事务ID的最大值 + 1
(表示将来可能出现的事务的下限)
可见性算法规则
指的是当前事务
对特定数据记录的可见性判断当前事务
:是正在执行
某些操作的事务,它有自己的事务 IDDB_TRX_ID
:
最后一
次对特定数据
行进行修改的事务的 ID
(插入、更新或删除操作)
1)
比 读视图最小事务ID 还小(可见)
- 比较
DB_TRX_ID(最近修改事务ID)
与up_limit_id(前读视图中 最小事务 ID)
- 如果
最近修改事务ID
≤最小事务 ID
,当前事务可以看到该记录(否则,进入下一步判断)
- 比较
2)
比 读视图当时最大事务ID还大(不可见)
- 比较
DB_TRX_ID最近修改事务ID)
与low_limit_id(前读视图中 事务ID的最大值 + 1)
- 如果
最近修改事务ID
≥事务ID的最大值 + 1
,则当前事务无法看到该记录(否则,进入下一步判断)
- 比较
3)
如果最近修改事务已经完成提交(可见)
- 判断
DB_TRX_ID(最近修改事务ID)
是否在活跃事务的数组中 - 如果在活跃事务列表中,则该记录尚未提交,对当前事务不可见
- 如果不在,则该记录已提交,当前事务可见
- 判断
上次更新: 2024/10/15 16:27:13