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 回答

https://github.com/tikv/tikv/issues/8589#issuecomment-686889081

非常感谢您的回答:pray:

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

:+1:

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