就题主表达这个场景来看,说是数据库基于MVCC技术实现的读已提交隔离级别,完全没有问题。

首先请题主明白一点,MVCC是并发访问控制技术,而可重复读是隔离级别,二者不可划等号。题主说的这个场景是合法且可以存在的,因为MVCC和读已提交隔离级别本来就不是冲突的,不然你想,MySQL同时支持读已提交和可重复读隔离级别,难道只有可重复读用了MVCC,而读已提交没用?不可能的,他们都用了MVCC,只是读取策略存在差异。

发现很多人把MVCC和快照技术混为一谈了,其实快照是基于MVCC发展出来的技术,并不意味着用了MVCC就一定要用快照隔离,只是快照隔离是一种普遍使用的,避免不可重复读和幻读异常的手段罢了。

回到题主的问题:数据库MVCC如何做到可重复读隔离级别?

刚刚也提到了,快照技术是当今主流使用的手段。那么为什么快照可以确保可重复读隔离级别呢?从快照的本质来看,它表达的是数据库历史的某个一致性状态,事务所读取的数据和当前时刻数据库状态没有关系,只和这个一致性状态有关系,也就是读一致性。例如:

t0时刻,数据库中有a=10,b=10,此时这就是一个一致性状态。

t1时刻,某个读事务Tr开始,将t0时刻的一致性状态作为快照,读取a的值=10。

t2时刻,某个写事务Tw开始,为b执行+10,为a执行-10,并提交。此时数据库当前状态为a=0,b=20。

t3时刻,Tr读取b的值。但是由于Tr采用了快照读技术,数据库当前状态和Tr一毛钱关系没有,它只关心t0时刻的状态,所以读取到的值依然是10。此时就算事务Tr再读取a的值也一样,读取的结果依然同样为10。

但其实,说快照技术做到了可重复读隔离级别也不准确,因为快照技术做到的是比可重复读更高的快照隔离级别,它额外解决了幻读这样一个谓词异常。当然快照隔离也不是可串行化,因为快照隔离依然存在写偏序异常,快照技术本身只做到了读一致,避免了读异常的发生,却没有对写进行限制,因此需要额外依赖其他并发控制技术进行冲突检测(比如PG的SSI,以及TO、OOC等技术)。