TiSpark v3.0.3 与 v3.1.3 于 2023/04/22 正式发布,其中有几个新特性值得关注。两个版本新特性基本一致,下文介绍默认基于 v3.1.3。
Set the default value of spark.tispark.telemetry.enable as false
https://github.com/pingcap/tispark/pull/2621
由于安全性原因,包括 TiSpark,TiDB 在内的若干款产品都默认关闭了 telemetry 。
Support probe TiFlash status
https://github.com/pingcap/tispark/pull/2619
TiSpark 曾经从 PD 获取 TiKV 与 TiFlash 状态,并缓存为 regioncache。cache 一般在请求失败后,根据失败种类决定是否失效更新。
这带来了一个问题:目前 PD 的 RPC 接口无法准确感知 TiKV 与 TiFlash 的所有状态。如当挂起 TiFlash,PD 仍返回可用状态。导致请求不断打到不可用的 TiFlash。
基于此,TiSpark 使用 TiFlash 提供的 MPP isalive 接口定期探活,阻止发往不可用 TiFlash 的请求。并在下一次重试时请求其他可用 TiFlash。
题外话,PD 作为单点很可能成为 TiSpark 的瓶颈,目前唯一的策略也只能纵向扩容(提高 CPU/内存规格)。当前 TiDB Cloud 作为 serverless 共享 PD 也会遇到类似问题,他们正计划单独拆出 regioncache 作为可拓展的微服务,希望在将来 TiSpark 也能享受到此带来的好处。
Support service safe point
https://github.com/pingcap/tispark/pull/2634
TiSpark 作为 TiKV 上层应用,基本会与 TiDB 混合使用,因此 TiSpark 与 TiDB 会相互影响,如 TiDB GC 。
在 TiSpark 中都是 snapshot 读,而且 TiSpark 没有事务大小限制。当遇到超过 gc_life_time 的大事务,可能会遇到数据已被 GC 清理的情况。更糟糕的是,由于 TiKV 遇到此时的默认行为不是报错,而是可能返回空/错误的数据,我们很难察觉。
在曾经,我们推荐使用 TiSpark 时,调整 gc_life_time 以推迟 GC。现在 TiSpark 支持 service safe point,用户无需手动调参,TiSpark 会主动推迟 GC。
Service safe point 是 TiDB 暴露的能力。safe point 的含义是:在 safe point 之后的数据不会被 gc 掉用,safe point 会取所有 serviec safe point 的最小值。比如 TiDB safe point = min (minstartts from every TiDB transaction),now-gc_life_time)。
现在 TiSpark 也支持了 serviec safe point,我们暂称为 TiSpark safe point。同样的,TiSpark safe point 会取其所有事务中最小的 start_ts 并注册到 PD。基于此,用户无需手动配置 TiSpark 即可自动推迟 GC。
Support fallback when resolveLockAsync
https://github.com/pingcap/tispark/pull/2651
在 TiDB 中,有一种 async lock,该锁在 async commit 时被加上。async commit 故名思义,二阶段提交中的 commit primary key 与 commit secondary key 会异步进行,事务状态不再由 primary key 决定,而是查询所有 secondary key 状态综合决定。
在 async commit 中还有一个特殊情况——fallback,即由于某些原因回退到二阶段提交。
TiSpark 读遇到锁时会尝试进行 resolve lock 操作,包括 resolve async lock。但曾经,TiSpark 解锁逻辑不完善,缺少了对 fallback 逻辑的处理。这可能会导致 TiSpark 无法感知 fallback,本应回滚的事务反而被提交了。(非常小的概率)。
该 PR 参考 client-go 补充了 fallback 逻辑,完善了resolve async lock 流程。
Optimize ttl
https://github.com/pingcap/tispark/pull/2672
非常小但值得一提的 PR。
TiSpark 写入前,在分配 ID 时会使用 2PC 进行写入,该写入可能会失败(即使是正常情况)。如 2PC 的 min_commit_ts 可能会被读事务推进 ,以达到写不阻塞读的目的。
当分配 ID 的两阶段提交 min_commit_ts 刚好被推进时,TiSpark 会遇到 commit_ts_expired 的错误。TiSpark 存在以下问题导致无法正确处理该错误:
- 当前事务遇到 commit_ts_expired 没有去解锁。
- Lock TTL (3600s)设置时间太长,重试时遇到锁未过期解锁失败。
- 遇到 commit_ts_expired 没有重新生成 commit_ts 重试,等到 Spark 重试或用户重试才能生存新的 commit_ts。
考虑到该问题出现的概率很小,该 PR 暂时只减小 TTL 来让重试成功。
CBO 优化 (v3.0.3)
v3.1.2 已包含此优化
TiSpark 基于 CBO (基于代价的优化器)进行执行计划选择。
https://github.com/pingcap/tispark/pull/2567
该 PR 修复了当开启 TiFlash 时 CBO 无法选择 TiKV index scan 的问题。现在在开启 TiFlash 时 TiSpark 会从 TiKV table scan, TiKV index scan and TiFlash scan 中选择代价最小的。
https://github.com/pingcap/tispark/pull/2588
该 PR 修复了统计信息没有被收集的 Bug,该问题会导致 TiSpark 错误选择执行计划(执行计划会根据统计信息计算代价)。因此在存在该问题的 TiSpark v3.0.0 ~ v3.0.2 中,可能存在性能问题,请大家小心使用。