TiDB 2PC 优化 Async Commit 是否会导致多个事务拥有相同的提交时间戳

看了Async Commit这篇博客后有个疑惑,文中提到:

TiDB 的每一次快照读都会更新 TiKV 上的 Max TS

综上所述,每个 key 的 Min Commit TS 取 prewrite 时的 Max TS + 1 和 prewrite 前从 PD 获取的时间戳的最大值,事务的 Commit TS 取所有 key 的 Min Commit TS 的最大值,就能够同时保证快照隔离和线性一致性。

我的疑惑是:这种情况下,事务的 Commit TS 来源于某个 key 的 Min Commit TS,也就可能来源于某个 Max TS + 1,这样会不会导致多个事务拥有相同的 Commit TS,会有什么影响?

2022/5/2 补充:麻烦各位了解Async Commit后再做回复,从PD生成的时间戳是唯一的,但是事务的提交时间戳是经由计算得到的,并非在提交的时候直接从PD取一个时间戳作为其提交时间戳

补充个人理解:我认为两个事务拥有相同的提交时间戳是有可能的,但是这种情况只会发生在两个事务的prewrite过程在时间轴上有所重叠的时候,此时是无法为两个事务定序的,也就是说它两个之间的大小关系可以任意,所以从这个角度看,它们拥有相同的提交时间戳应该是没什么影响

举一个例子的话:
5:T1在A取到了prewrite ts为5,发送给A和B执行prewrite(实际上会+1后发送)
6:T2在C取到了prewrite ts为6,发送给B和C执行prewrite
8:T3在B开始,拿到了start ts为8,B的max ts更新为8
9:B在此时收到了T1和T2的prewrite request,计算得到的min commit ts均为9
最后T1和T3都以9作为提交时间戳

3 个赞

不会啊,时间戳是PD产生,leader维护的递增序号

2 个赞

这种优化下,多个事务的 Commit TS 有没有可能来自于一个 TiKV 上的 Max TS + 1?

2 个赞

不会,tso从pd获取,每次事务获取都会导致tso递增,不会有不同事务获得相同start_ts的情况。max_ts时间就是当前最大事务的开始ts。在prewrite时会从pd再获取一次ts,就能保证提交的事务不会有相同的ts,每次获取都会递增。
应该是这么个过程

4 个赞

感谢你详细的回复!
不过根据博客所述,Max TS 应该是每个 TiKV 各自维护一份
个人感觉,只有访问到该 TiKV 的快照读请求才会更新其本地维护的 Max TS,多个 TiKV 维护的 Max TS 可能不一致,并且事务到达 TiKV 的 prewrite ts 可能比本地维护的 Max TS 小

2 个赞

看起来max_ts是以region为单位维护的,不同的事务访问不同的region,max_ts不一致应该也不会影响事务一致性




以下是根据自己理解,不一定正确,最重要的是min commit ts的约束保证

2 个赞

TSO 是单调递增的,只有 PD 的 leader 会维护…

1 个赞

再次感谢你的回复!
我觉得我想清楚了,两个事务拥有相同的提交时间戳是有可能的,但是这种情况只会发生在两个事务的prewrite过程在时间轴上有所重叠的时候,此时是无法为两个事务定序的,也就是说它两个之间的大小关系可以任意,所以从这个角度看,它们拥有相同的提交时间戳应该是没什么影响

举一个例子的话:
5:T1在A取到了prewrite ts为5,发送给A和B执行prewrite(实际上会+1后发送)
6:T2在C取到了prewrite ts为6,发送给B和C执行prewrite
8:T3在B开始,拿到了start ts为8,B的max ts更新为8
9:B在此时收到了T1和T2的prewrite request,计算得到的min commit ts均为9
最后T1和T3都以9作为提交时间戳

1 个赞

时间戳是PD预先申请好的,惟一

2 个赞

时间戳是PD产生,类似发号器不会重复

1 个赞

1 个赞

是的,这正是我举例中括号里所表达的内容

+1是为了保证线性一致性中的循序性要求,具体可见博客

不+1可能会导致 当前要提交的事务 与 该事务prewrite之前已经提交了的事务 拥有相同的提交时间戳,即两个prewrite过程在时间轴上没有重叠的事务拥有了相同的提交时间戳,破坏了线性一致性

学习了:grin::grin:

我认为不会,正常情况下,T1、T2事务是由自己来完成提交的,这种情况不一样。
即使到了你假设的T1、T2都在prewrite完成后都挂了,由T3来完成,我认为也是按事务来的,比如先读到T1相关的行,这时候T3会通过两向指向,找到所有T1的相关行并完成提交动作,然后才是读到T2的行,完成T2的提交,两次提交都是在获取TSO的,所以不一样。

不会,因为tso是预分的。你可以理解每一个tso是一个实体

不好意思,我认为你并没有理解我的举例,T3仅仅是为了更新在B上维护的max ts

T3只需要做到在T1,T2的prewrite请求到达B之前,把B上维护的max ts抬高一定程度即可,以使得T1,T2在计算最终提交提交戳的时候都选择了B上维护的max ts+1

没明白,现在还有没有疑问:joy:,如果没哟,建议标记一下,如果还有疑问,我其实不建议再按照自己的理解,来举例说明,建议再对照一下原文,再看一遍

1 个赞

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