Async commit 开启后什么情况下发生“事务的外部不一致”、tidb_guarantee_external_consistency 变量如何保证事务的外部一致性?

为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:

【TiDB 版本】

+-----------------------+
| version()             |
+-----------------------+
| 5.7.25-TiDB-v5.0.0-rc |
+-----------------------+

【问题描述】

1. Async commit 开启后什么情况下发生“事务的外部不一致”?

PingCAP 官网 5.0.0-rc 特性介绍 中,指出 tidb_guarantee_external_consistency 变量用来确保外部最终一致性,可是就 2PC 原理来说 TIDB 5.0 的 Async Commit 特性以 2PC Prewrite 阶段完成为标准,Prewrite 的完成也就代表 commit(keys,commit_ts,start_ts)) 函数还没有执行成功,因为这时还没有从 PD 获取 commit_ts;

这个问题会引发 “外部不一致”,当前 txn 对于其他 session 的 txn 来说还没有完成,因为没有 commit_ts,但是对于自己的 session 的 txn 来说却已经执行成功,因为 Prewrite 已经执行完成;其他 session 通过 MVCC 获取数据时会出现 官方文档-参数介绍: tidb_guarantee_external_consistency 中提到的 “如果两个事务修改的内容没有交集,其他事务观测到它们的提交顺序可能与它们实际的提交顺序不一致”,因为不相交的两个 txn 不一定谁先获取的 commit_ts 在前,不一定谁先 prewrite 完成,在某些情况下可能违背 “事务的外部一致性”,即:本 txn 相对于自己 txn 已完成只是没有获取 commit_ts,相对于其他 txn 还没有完成;

以上对于 Async commit 的理解对吗?

2. tidb_guarantee_external_consistency 变量如何保证事务的外部一致性?

Async Commit Issue 链接“so only clients who try to read before that message happens will go through the recovery procedure” 指出普遍情况下,发起 2PC 经历过 prewrite 后会很快提交,所以只有想要读取消息(含有 commit_ts 的事务提交消息)发生之前的客户端会处于 recovery procedure。

  • Async Commit Issue 链接中提到的 recovery procedure 是什么?
  • recovery procedure 可以理解为 tidb_guarantee_external_consistency 开启后,其他 session 查询数据时,类似于遇到锁类似的内部不断重试吗?
  • before that message happens 应该 指在获取 commit_ts 之前发生的数据,如果有其他 session 想要获取数据时只能以 txn 未结束的 TSO 参考 MVCC 获取数据吧?

若提问为性能优化、故障排查类问题,请下载脚本运行。终端输出的打印结果,请务必全选并复制粘贴上传。

别沉,顶一下…

我理解你的问题在这篇文章中有描述到,你可以先参考看下是否能回答你的问题

1. Async commit 开启后什么情况下发生“事务的外部不一致”?

具体地来讲,Async commit 发生外部顺序不一致的情况的例子是:

Support%20Async%20Commit%20PRD

例如:有 3个事务读、写 x 和 y 的值

  • 初始 x 和 y 都是 0
  • T1 时刻,Txn1 和 Txn2 都开启。
  • T2 时刻,Txn1 修改 x 的值为 1,Txn2 修改 y 的值为 2。
  • T3 时刻,Txn1 提交。与此同时,并发地开启另一个事务 Txn3。
  • T4 时刻,Txn1 提交成功后,用户从外部通知 Txn2 提交。
  • T5 时刻,Txn3 可能读取到 x 的值为 0,y 的值为 2。

从提交顺序上,Txn2 在 Txn1 后提交。而从 Txn3 的观测来看,Txn2 早于 Txn1 提交。由于 Txn1 只写 x,Txn2 只写 y,它们在数据库内部没有因果关系。在采用因果一致性的情况下,这两个事务没有全局一致的顺序。

深入到实现细节,Txn1 和 Txn2 的 commit TS 都是从各自涉及的 TiKV 实例本机计算出来的。在上面的情况中,这两个 TiKV 之间没有交互,无法得到一个确定的顺序。

2. tidb_guarantee_external_consistency 变量如何保证事务的外部一致性?

开启后,TiDB 会在用户执行 COMMIT 后,从 PD 获取一个最新的时间戳。这个时间戳会被发到 TiKV 作为允许计算出的最小 commit TS。任何在该事物前提交成功的事务的 commit TS 会小于最新拿到的这个 min commit TS,也就会必定小于最终事务提交的 commit TS,也就能保证事务在外部的顺序了。

3. recovery procedure 是什么?

如果一个 async commit 事务的所有锁都被写入(prewrite),就意味着这个事务提交成功了。Recovery procedure 指,当所有锁都被写入,但没有任何一个锁被提交的情况下,系统将这个事务成功提交的过程。

1赞

非常感谢您的回答,完全解决了我的问题:pray:

最开始还在纠结,开启 async commit 和 tidb_guarantee_external_consistency 后与不开相比,到底哪个效率高;
直到看到了下面的您的 issue 回答

非常感谢您的回答:pray:

除了 recovery procedure 之外,基本已经让我明白了内部的原理;
由于 sticnarf 直接回答了问题,且更全面,我就将他的回答标记为解决方案了!

:+1: