共计 1201 个字符,预计需要花费 4 分钟才能阅读完成。
MVCC
顺便聊聊 MVCC(多版本并发管制)。在 mysql 中,RC(已提交读)和 RR(可反复读)隔离级别下,借助 MVCC 机制,能够解决查问时不同事务间的并发读写问题。
零碎版本号
零碎里保护一个零碎版本号,这个版本号在每次创立一个事务时就会自增。每个事务会保护一个事务版本号 transaction id(以下简称事务 id),这个版本号就是取自创立事务时的零碎版本号。
版本链
每行数据会保护 2 个虚构列,一个是版本号 TRX_ID,每次事务创立或者更新某个行数据的时候,就会把事务 id 赋值给该行的 TRX_ID,代表这个版本的行数据是我这个事务批改的; 一个是回滚指针 ROLL_PTR,指向前一次的版本,所有历史版本的记录都会存在 undo log 里(相干 log 的概念前面会提到)。 留神,这里仅仅是事务批改行数据就会对 TRX_ID 赋值,而不是要提交事务才执行操作。咱们须要搞清楚一个概念,所谓的版本,就是每次对行数据进行批改,mysql 都会新增一个批改后的记录版本,而后用 ROLL_PTR 指向上一个版本 。所以,在 mysql 中会有多个不同版本的行数据,因为回滚指针的存在造成一个版本链。
readview
一个事务在进行查问时,会创立一个快照 readview(RC 和 RR 不同,RR 隔离级别会在事务第一次查问时生成一个快照,事务的后续查问都应用这个快照,RC 级别则是事务每次查问都会生成快照 ),它会存储系统中其余所有未提交沉闷事务 id 的汇合 m_ids
那么 mysql 是怎么利用上述的构件去实现 MVCC 呢?大略有以下四种状况:
1. 被拜访行数据版本的 TRX_ID 如果小于 m_ids 中最小的事务 id m_up_limit_id,则创立这个版本数据的事务是在以后事务创立 readview 前就提交了的,所以能够被以后事务拜访
2. 被拜访行数据版本的 TRX_ID 如果大于 m_ids 中最大的事务 id m_low_limit_id,则创立这个版本数据的事务是在以后事务创立 readview 后才开启,所以不能够被以后事务拜访
3. 被拜访行数据版本的 TRX_ID 如果介于 m_ids 中最小和最大事务 id 之间,判断一下是否存在于 m_ids 中。如果存在,则阐明创立这个版本数据的事务在以后事务创立 readview 时依然沉闷,所以不能够被以后事务拜访;反之,则这个版本数据的事务是在以后事务创立 readview 前就提交了的,所以能够被以后事务拜访。
4. 被拜访行数据版本的 TRX_ID 如果等于 m_ids 中最大或最小的事务 id,则以后事务开启时,创立这个版本数据的事务还未提交,也不能被以后事务拜访
顺便提一下,有两点须要留神:
1. 事务拜访仅仅是针对单个版本而言的,行数据版本不能被以后事务拜访并不意味着行数据之前的版本不能被拜访,因为之前版本的事务 id 可能是满足被拜访的条件的
2. 以后事务 id 等于行数据版本的事务 id 的时候,必定能够被以后事务拜访,因为该版本就是以后事务创立的