InnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。它是在事务开始的时候向InnoDB的事务系统申请的,是按申请顺序严格递增的。
每次事务更新数据的时候,都会生成一个新的数据版本,并且把transaction id赋值给这个数据版本的事务ID,记为row trx_id。
在rr 隔离级别下,事务在启动的时候会创建一个基于整库的快照,InnoDB利用了“所有数据都有多个版本”的这个特性,实现了“秒级创建快照”的能力。
InnoDB为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在“活跃”的所有事务ID。“活跃”指的就是,启动了但还没提交。
- 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
- 如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;
- 如果落在黄色部分,那就包括两种情况
a. 若 row trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见;
b. 若 row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。
id = 1,k = 1
事务A 在启动时,事务C 还未开始,处于红色部分,未开始区域,不可见;
事务B 在事务A 启动后启动,处于黄色部分,并且事务B 在事务A 提交后提交,黄色部分第一种情况,不可见。
因此,事务A select 语句的值为1。
来自《MySQL45讲》