TiDB Bug List=

Issue

https://github.com/pingcap/tidb/issues/56809

Impact

如果使用了 stale read,则有一定风险影响到 Async Commit / 1PC 事务的线性一致性。在这种情况下,Async Commit / 1PC 事务可能会以过大的 commit_ts 提交,导致改事务所写入的数据,对另一个开始时间严格晚于当前事务成功提交时间的读操作不可见。用户的应用读到这些不一致的结果并使用之后,有可能因此继续写入更多有错误的数据。

Root Cause

当使用 stale read 时(无论使用哪种语法),TiDB 并未保证读用的 ts 不会超过 PD 曾分配过的最大 ts (read_ts <= pd_allocated_max_ts)。所以在一些情况下,stale read 可能会使用一个未来的 ts (超过 PD 分配过的任何 ts)来进行。可能的情况包括但不限于:

  • 用户手动指定了读取的数据的时间
  • 物理时钟存在漂移
  • PD 的写入延迟比较高,造成分配 ts 和物理时间之间存在 lag。

当发送到 TiKV 的 stale read 请求未能成功处理、TiDB 因此以普通 leader read 模式重试该读请求时,新的请求不会带有 stale_read flag,以告知 TiKV 该请求应当以非 stale read 的通常模式来进行处理。

对于发送到 TiKV 的非 stale read 请求,需要推动 max_ts 到当前请求的 read_ts。这里的 max_ts 将被用于计算 Async Commit / 1PC 事务的 commit_ts,其应当被保证永远小于等于 PD 曾经分配过的最大 ts。然而,此时就有可能因为一个 stale read 操作而被推进到一个未来的 ts,从而引发问题。

Diagnostic Steps

  • 确认集群中使用了 stale read。如果可以确认用户从未使用 stale read,那么就和该问题无关。
  • 可以确认(或疑似)Async Commit / 1PC 事务有时存在线性一致性被破坏的情况:Async Commit / 1PC 事务写入的数据在成功提交后,有时不会对紧接着的读语句立即可见。如果有办法找到这种异常的 Async Commit / 1PC 事务的具体数据的话,可以发现它的 commit_ts 的 logical 部分总是等于 1。
  • 遇到这一现象的概率可能会非常低、所以可能非常难以复现。即使集群中发生了这种现象,也未必总能有办法从中检查到。

如果观察到下列现象,则可以增加符合该问题的判断的置信度:

在 TiDB 的日志中,可能会看到这一错误:

Retrying aggressive locking with ForUpdateTS (…) less than previous LockedWithConflictTS (…)

该报错信息中的 LockedWithConflictTS 所指的 ts 的 logical 部分总是等于 1。

  • 注意该问题发生时未必一定会引起这种报错。因此找不到这种报错并不意味着不是这个问题。

可以确认集群中存在时钟漂移、或者 PD 存在写入性能问题。

如需检查 ts 的 logical 部分的数值,可使用 pd-ctl tso 命令。TiDB 日志中可以看到的错误 example:

// TiDB related error log

Error 1105 (HY000): Txn 453423637808807957 Retrying aggressive locking with ForUpdateTS (453423637808807963) less than previous LockedWithConflictTS (453423637831352321)

tiup ctl:v7.5.1 pd tso 453423637831352321

// get logic of LockedWithConflictTS

Starting component ctl: /Users/wuxuelian/.tiup/components/ctl/v7.5.1/ctl pd tso 453423637831352321

system: 2024-10-23 01:58:31.405 -0700 PDT

logic: 1

Resolution

升级到该问题已经被修复的新版本。

Workaround

  • 如果有可能,可以考虑停止使用 stale read。
  • 如果不能停用 stale read,那么我们并没有其它手段来严格地保证不触发这一问题。不过,如果可以保证如下几点,那么触发该问题的概率微乎其微:
    • 避免使用 stale read 读太新的数据(即读的时间太过接近当前时间)。
    • 确保部署集群的机器上的系统时间精确且稳定。
    • 确保 PD 性能良好。

Affected Versions

  • v6.5.0~v6.5.11
  • v7.1.0~v7.1.5
  • v7.5.0~v7.5.4
  • v8.1.0~v8.1.1