关于因果一致性事务的疑问

https://docs.pingcap.com/zh/tidb/stable/transaction-overview#无因果关系的事务之间的逻辑顺序与物理提交顺序不保证一致

官方文档中,对于因果一致性事务的描述如上面链接所示,其中一个特性给出的范例如下,这里说事务3可能读到id = 1的值为2但是id = 2的值为0,但是事务3是一个普通事务,它的BEGIN是在事务1和事务2的COMMIT之前,SI隔离级别下应该看不到事务1和事务2的修改才对,这里应该怎么理解?

快照隔离的关键是快照时间戳(start ts)和提交时间戳(commit ts)

官方文档中有一句关键陈述:

因果一致性的事务在提交时无需向 PD 获取时间戳,所以提交延迟更低。

以及更具体一些的描述:

在线性一致性的情况下,如果事务 2 在事务 1 提交完成后提交,逻辑上事务 2 就应该在事务 1 后发生。
因果一致性弱于线性一致性。在因果一致性的情况下,只有事务 1 和事务 2 加锁或写入的数据有交集时(即事务 1 和事务 2 存在数据库可知的因果关系时),才能保证事务的提交顺序与事务的发生顺序保持一致。目前暂不支持传入数据库外部的因果关系。

线性一致性要求事务在提交时向 PD 获取一个全局时间戳,从而提供实时性和循序性保证,使得如果事务 1 提交完成后,事务 2 再执行提交,事务 1 的 commit ts 就会小于事务 2 的 commit ts。

因果一致性不从 PD 获取全局时间戳,也就无法保证上一点。可以简单理解为事务的 commit ts 可以前移,举个例子,在 5 这个时间点执行提交,但是最终以 3 作为其 commit ts。

虽然 commit ts 可以前移,但要合理地前移,从而保证正确性。当两个事务之间存在数据库可知的因果关系时,commit ts 的前移就有了限制,在文档给出的有因果关系的例子中,事务 1 和事务 2 在 id=1 的记录上存在因果,1 前 2 后,所以尽管 T1 和 T2 的 commit ts 都可以前移,但前移后仍要保证 T2 commit ts > T1 commit ts。

对于无因果关系的事务的例子中,T1 和 T2 的 commit ts 前移到哪儿无法确定,有可能前移后 T2 commit ts > T1 commit ts,也有可能 T2 commit ts < T1 commit ts。它们的 commit ts 和 T3 的 start ts 之间的关系也无法确定,如果前移后的结果是 T2 commit ts < T3 start ts < T1 commit ts,那么就会出现文档所说的这种情况。

强调 T3 在 T1 提交前开始,是因为 commit ts 只能前移,而 start ts 仍然要从 PD 取全局时间戳,如果 T3 在 T1 提交后开始,那 T3 一定能读取到 T1 的修改,如果 T3 在 T2 提交后开始, 那 T3 一定能读到 T1 和 T2 的修改。

因果一致性事务只在启用 Async Commit 特性和一阶段提交特性时生效。具体原理可以参考这篇博客 Async Commit 原理介绍丨 TiDB 5.0 新特性 | PingCAP

2 个赞

感谢你的回复,看了这篇关于Async Commit原理介绍的文件,大致理解了。

想再请教一下,因果一致性事务的commit ts有没有具体的逻辑,这个时间戳是从哪儿里得来的?

没仔细看代码,根据文档和博客所述,在Async Commit优化下,因果一致性只是没有在prewrite前从PD取时间戳,那么计算commit ts的方法应该是该事务涉及到的各个region的max ts+1的最大值

这个“计算commit ts的方法应该是该事务涉及到的各个region的max ts+1的最大值” 是从代码中看到的吗,还是有文档说明?

Async Commit 原理介绍丨 TiDB 5.0 新特性 | PingCAP
这篇博客中在如何确定事务的 Commit TS这一节有大致说明,由于这篇博客倾向于在设计层面分析,和代码层面上可能有所出入。

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。