为了防止图10-3中的瞬时不一致现象,支持分布式事务的强一致性,我们需要全局范围内的事务号和快照,以保证全局MVCC和快照的一致性。在openGauss中,GTM负责提供和分发全局的事务号和快照。对于任何一个读事务,其都需要到GTM上获取全局快照;对于任何一个写事务,其都需要到GTM上获取全局事务号。
在图10-3中加入GTM,并考虑两阶段提交流程之后,分布式读-写并发事务的流程如图10-19所示。对于读事务来说,由于写事务在其从GTM获取的快照中,因此即使写事务在不同DN上的提交顺序和读事务的执行顺序不同,也不会造成不一致的可见性判断和不一致的读取结果。

图10-19 读-写并发下全局事务号和快照的分发流程示意图
细心的读者会发现,在图10-19的两阶段提交流程中,写事务T1在各个DN上完成准备阶段之后,首先第一步是到GTM上结束T1事务(将T1从全局快照中移除),然后第二步再到各个DN上进行提交阶段。在这种情况下,如果查询事务T2是在第一步和第二步之间在GTM上获取快照,并到各个DN上执行查询的话,那么T2事务读到的T1事务插入的记录v1和v2,它们xmin对应的XID1已经不在T2事务获取到的全局快照中,因此v1和v2的可见性判断会完全基于T1事务的提交状态。然而,此时XID1对应的T1事务在各个DN上可能还没有全部或部分完成提交阶段,那么就会出现各个DN上可见性不一致的情况。
为了防止上面这种问题出现,在openGauss中采用本地二阶段事务补偿机制。如图10-20所示,对于在DN上读取到的记录,如果其xmin或者xmax已经不在快照中,但是它们对应的写事务还在准备阶段,那么查询事务将会等到这些写事务在DN本地完成提交阶段之后,再进行可见性判断。考虑到通过两阶段提交协议,可以保证各个DN上事务最终的提交或回滚状态一定是一致的,因此在这种情况下各个DN上记录的可见性判断也一定是一致的。

图10-20 读-写并发下本地两阶段事务补偿流程示意图




