MVCC
提示
- MVCC(多版本并发控制)指的就是在使用READ COMMITTD、REPEATABLE READ这两种隔离级别的事务在执行普通的SELECT操作时访问记录的版本链的过程。使不同的事务读写、写读并发执行,提升系统性能。
- 事务利用
MVCC
进行的读取操作称之为一致性读
。所有普通的SELECT
语句(plain SELECT
)在READ COMMITTED
、REPEATABLE READ
隔离级别下都算是一致性读
。
版本链
Innodb的行格式中包含两个隐藏列,分别是trx_id
和roll_pointer
,如果没有主键或唯一索引也会创建隐藏列row_id
。
- trx_id
每次一个事务对某条聚簇索引记录进行改动时,都会把该事务的事务id
赋值给trx_id
隐藏列。
只有在事务对表中的记录做改动时(增删改)才会为这个事务分配一个唯一的
事务id
。整个系统中分配的事务id
值是一个递增的数字。先被分配id
的事务得到的是较小的事务id
,后被分配id
的事务得到的是较大的事务id
。
- roll_pointer
每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志
中,然后这个隐藏列就相当于一个指针
,可以通过它来找到该记录修改前的信息。
undo日志
被存放到了类型为FIL_PAGE_UNDO_LOG
的页面中。
对记录每次更新后,都会将旧值放到一条undo日志
中,就算是该记录的一个旧版本,随着更新次数的增多,所有的版本都会被roll_pointer
属性连接成一个链表,我们把这个链表称之为版本链
,版本链的头节点就是当前记录最新的值。另外,每个版本中还包含生成该版本时对应的事务id
。
ReadView
概念
m_ids
:表示在生成ReadView
时当前系统中活跃的读写事务的事务id
列表。min_trx_id
:表示在生成ReadView
时当前系统中活跃的读写事务中最小的事务id
,也是m_ids
中的最小值。max_trx_id
:表示生成ReadView
时系统中应该分配给下一个事务的id
值。注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。
creator_trx_id
:表示生成该ReadView
的事务的事务id
。只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。
规则
规则 | 结果 |
---|---|
trx_id = creator_trx_id | 着当前事务在访问它自己修改过的记录,所以该版本可以被当前事务访问。 |
trx_id < min_trx_id | 当前事务在生成ReadView之前已提交(即不活跃),所以可以访问 |
trx_id >= max_trx_id | 当前事务在生成ReadView后才开启,所以不能访问 |
trx_id >= min_trx_id & trx_id < max_trx_id | 如果当前事务id在m_ids中,说明该事务仍活跃,则不能被访问,不在m_ids中则可以访问 |
依次和版本链中(包含页面中的那条数据)的数据依次进行比对,找到符合的数据就返回并退出比对。
生成时间
READ COMMITTED(
每次SELECT前都生成一个ReadView
)REPEATABLE READ(
在第一次SELECT的时候生成一个ReadView
)