MySQL InnoDB Engine--多版本一致性视图(MVCC)

MySQL InnoDB存储引擎使用MVCC机制来提供一致性非锁定读((consistent nonlocking read)。

 为方便演示,下面图中:

黄色部分表示重做日志(UNDO LOG)

绿色部分表示正常数据

红色部分表示已删除数据

假设现在有表TB001,其表结构为:

CREATE TABLE `TB001` (
  `ID` VARCHAR(20) NOT NULL,
  `C1` VARCHAR(20) NOT NULL,
  `C2` VARCHAR(20) NOT NULL,
  PRIMARY KEY (`ID`),
  KEY `IDX_C1` (`C1`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

步骤1:事务TX1001在12:00时插入一条记录

 INSERT INTO TB001(ID,C1,C2)
 VALUES('AA0001','BB0001','CC0001');

在主键索引/二级索引/重做日志中数据如下:

步骤2:事务TX1003更新数据但未提交:

UPDATE TB001 
SET C2='CC1111'
WHERE ID='AA0001'

步骤3:事务TX99999999999开启可重复读事务,开启事务执行第一条SQL语句时:

A、当前所有TX1001及之前事务都已提交,则事务低水位线为TX1001

B、当前写事务最大ID为TX1004,则事务高水位线TX1005

C、事务TX1002和TX1004都已提交

D、事务TX1003未提交,则活跃事务集为(TX1003)

步骤4:事务TX1003提交更新,更新后在主键索引/二级索引/重做日志中数据如下:

步骤5:事务TX1005执行更新并提交:

UPDATE TB001 
SET C1='BB1111' WHERE ID='AA0001'

更新后在主键索引/二级索引/重做日志中数据如下:

步骤6:事务TX1007执行删除并提交:

DELETE FROM TB0001 
WHERE ID='AA0001'

更新后在主键索引/二级索引/重做日志中数据如下:

步骤7:事务TX99999999999执行查询:

SELECT * 
FROM TB001
WHERE C1='BB0001'

查询如何执行呢?

1、首先当前二级索引IDX_C1上有两条已标记为删除的记录(C1=BB0001,ID=AA001)和(C1=BB1111,ID=AA0001)

2、通过在索引IDX_C1按C1='BB0001'查找可以找到已标记为删除的记录(C1=BB0001,ID=AA001)

3、根据索引记录的ID=AA0001在主键索引上找到已删除记录(ID=AA0001,C1=BB1111,C2=CC1111,TRX=TX1007,RBP=RP1007)

4、步骤3中找到的记录版本为TX1007,超过事务TX99999999999的高水位线TX1005,版本不满足,按照回滚指针RP1007去UNDO日志中查找

5、在UNDO日志中找到(TX1005,RPT=RP1005,ID=AA001,C1=BB1111,C2=CC11111),和步骤3中记录合并得(TX1005,RPT=RP1005,ID=AA001,C1=BB1111,C2=CC11111)

6、步骤5找到记录版本为TX1005,等于事务TX99999999999的高水位线,版本不满足,按照回滚指针RP1005去UNDO日志中查找上一版本

7、在UNDO日志中找到(TX1003,RPT=RP1003,ID=AA001,C1=BB0001),和步骤5中记录合并得(TX1003,RPT=RP1003,ID=AA001,C1=BB0001,C2=CC11111)

8、步骤5找到记录版本为TX1003,虽然高于"低水位线"和低于“高水位线”,但在活跃事务集(TX1003)中,版本不满足,按照回滚指针RP1003去UNDO日志中查找上一版本

9、在UNDO日志中找到(TX1001,RPT=RP1001,ID=AA001,C2=CC001),与步骤7中记录合并得(TX1001,RPT=RP1001,C1=BB0001,ID=AA001,C2=CC001)

10、步骤9找到的记录版本为TX1001等于“低水位线”,版本满足,将记录(TX1001,RPT=RP1001,C1=BB0001,ID=AA001,C2=CC001)返回给查询客户端。

11、查询结束。

原文地址:https://www.cnblogs.com/gaogao67/p/12189872.html