MVCC多版本并发控制
# MVCC多版本并发控制
# 基本概念
快照读(一致性非锁定读)就是单纯(普通)的 SELECT
语句,不加锁但不包括下面这两类 SELECT
语句:
SELECT ... FOR UPDATE
# 共享锁 可以在 MySQL 5.7 和 MySQL 8.0 中使用
SELECT ... LOCK IN SHARE MODE;
# 共享锁 可以在 MySQL 8.0 中使用
SELECT ... FOR SHARE;
1
2
3
4
5
2
3
4
5
快照即记录的历史版本,每行记录可能存在多个历史版本(多版本技术)。
快照读的情况下,如果读取的记录正在执行 UPDATE/DELETE 操作,读取操作不会因此去等待记录上 X 锁的释放,而是会去读取行的一个快照。
**读未提交的普通的select与该两个隔离级别下的普通的select都是不加锁读,但只有在事务隔离级别 RC(读取已提交) 和 RR(可重读)下,InnoDB 才会使用一致性非锁定读: 并且:普通的 select 语句是不会对记录加锁的但是串行化隔离级别会 **
- 在 RC 级别下,对于快照数据,一致性非锁定读总是读取被锁定行的最新一份快照数据。
- 在 RR 级别下,对于快照数据,一致性非锁定读总是读取本事务开始时的行数据版本。
快照读比较适合对于数据一致性要求不是特别高且追求极致性能的业务场景。
当前读 (一致性锁定读)就是给行记录加 X 锁或 S 锁。
当前读的一些常见 SQL 语句类型如下:
# 对读的记录加一个X锁
SELECT...FOR UPDATE
# 对读的记录加一个S锁
SELECT...LOCK IN SHARE MODE
# 对读的记录加一个S锁
SELECT...FOR SHARE
# 对修改的记录加一个X锁
INSERT...
UPDATE...
DELETE...
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 实现原理
其实现主要包括三个部分:隐藏字段,undolog,readview。
# 隐藏字段
trx_id : 最近修改该记录的事务id,作用是与readview一起参与可见性算法的运算,决定要读哪一个版本。
# undolog
对记录的修改操作都会记录其历史版本到redolog中形成一个版本链。
# readview
使用隐藏字段,与readview再根据可见性算法来确定读哪一个版本,可见性算法如下:
# 工作流程
读取数据的时候会遍历版本链,根据可见性算法找到可以读取到的数据,每个版本的记录中参与可见性算法运算的就是trx_id (最近修改记录的事务id)
一条记录的版本链值存在一个,不同的事务根据自己生成的readview ,然后遍历版本链根据可见性算法来读取自己可以读取的历史版本。
上次更新: 2024/08/09, 16:07:34