一、背景
某业务系统仍在使用 TiDB 4.0,而该版本已于 2024 年 4 月 2 日终止维护(EOL)。为保障系统稳定性和未来可持续性,决定通过“搭建备库 + 数据同步链路”的方式实现平滑升级。我们搭建了从 TiDB 4.0 到 TiDB 7.1 的 TiDB-Binlog 同步链路,并稳定运行了一个月,备库无明显延迟。
升级切换后,为保障回滚能力,同时使用 TiCDC 从 7.1 向旧集群(4.0)进行反向同步,作为“逃生路径”:
二、踩的第一个坑
切换至 7.1 主库后,业务高峰期间写入量增大,TiCDC 同步链路出现严重延迟。首先需判断瓶颈是出现在 TiCDC 自身还是下游集群。首先观察 grafana 监控 TiCDC > Lag analyze > Changefeed resolved ts lag,判断上游 TiDB 集群与 TiCDC 之间是否有瓶颈,目前正常:
Changefeed resolved ts lag:这个指标代表了上游 TiDB 集群与 TiCDC 节点之间的数据延迟,延迟以时间为单位。该指标能够反映 Changefeed 拉取上游数据变更的能力,当 lag 上升时,说明 Changefeed 无法及时地拉取上游产生的数据变更。
继续观察监控 TiCDC > Lag analyze > Changefeed checkpoint lag,判断 TiCDC 和下游集群之间是否有瓶颈,当前值很高,表明瓶颈可能出在下游:
Changefeed checkpoint lag:这个指标代表上游 TiDB 集群和下游系统之间的数据复制延迟,延迟以时间为单位。该指标反映了 Changefeed 整体的数据同步状况是否健康,通常情况下,lag 越小,说明同步任务状态越好。而当 lag 上升时,通常说明 Changefeed 的同步能力或者下游系统的消费能力无法匹配上游的写入速度。
进一步检查监控 Sink-General > Memory Quota,TiCDC Changefeed 的配置 memory-quota 默认 1GB,指定该 Changefeed 在 Capture Server 中内存配额的上限。对于超额使用部分,会在运行中被 Go runtime 优先回收。memory-sink-used 用满了 1GB,这意味着 TiCDC 内部 sink 写入缓存已满,数据无法及时写入下游,说明瓶颈就在下游:
排查下游集群 Duration、网络、CPU、IO 都不高,TiCDC 在下游的语句攒批行为也没问题。那下游瓶颈到底在哪里呢?排查下游所有监控发现 Transaction > Commit Token Wait Duration 指标异常,该指标代表事务提交时的流控队列等待时间。当出现较长等待时,代表提交事务过大,正在限流:
对于事务相关操作,一个事务在提交时,可能影响几百个 region,单个事务并行度受 tidb_committer_concurrency
系统变量限制(高版本默认128,4.0版本默认只有16),影响 region 较多的事务,无法一次性下发所有请求,会出现等待,此时监控 Transaction > Commit Token Wait Duration 会比较高。
因为 4.0 版本早在 2024-04-02 已 EOL,使得这个参数容易被遗忘,成为性能瓶颈。在 4.0 版本中 committer-concurrency 默认只有 16,高版本默认值从 16 修改为 128,并且由 tidb_committer_concurrency
系统变量控制。
server_configs:
tidb:
performance.committer-concurrency: 16
下游改为如下后,下游监控 Transaction > Commit Token Wait Duration 降到1秒内,同步延迟得到极大缓解:
server_configs:
tidb:
performance.committer-concurrency: 128
三、踩的第二个坑
切换升级完后,在上游 7.1 版本执行 DDL,然后 7.1 TiCDC 到 4.0 同步中断,例如:
-- 上游 7.1>
create table dd_test( stkeffect decimal(32,3));
Query OK, 0 rows affected (0.10 sec)
-- 上游 7.1>
alter table dd_test
modify column stkeffect bigint;
Query OK, 0 rows affected (0.10 sec)
-- 同步到下游 4.0 报错:
ERROR 8200 (HY000): Unsupported modify column: type bigint(20) not match origin decimal(32,3)
报错原因是下游 4.0 不支持 DECIMAL 精度修改,属于版本间 DDL 兼容性差异,官方说明文档:https://docs.pingcap.com/zh/tidb/v7.1/sql-statement-modify-column/。为了保持有逃生库,把下游集群 4.0 原地升级到高版本可解决。
四、踩的第三个坑
同步在上游无任何特殊操作的时候,TiCDC changefeed 偶尔会卡住不推进,了解到 7.1 版本 TiCDC 依然有因为上游 TiKV 卡主 changefeed 的问题,这是已知问题,后续版本 TiCDC 计划进行重构解决。
可以做如下尝试:
- pause 然后再 resume cdc 任务,等待观察一段时间;
- 如果第一步没效果,尝试重启 TiCDC 节点;
tiup cluster restart <cluster-name> -N <ticdc-node>
3.如果第二步没效果,经过多方谨慎评估后,低峰期滚动重启上游集群 TiKV。
五、小结
- EOL 的版本务必尽早升级,否则易埋下同步及兼容性等隐患。请参考:https://cn.pingcap.com/tidb-release-support-policy/
- TiCDC 延迟诊断需系统性排查:分清上游拉取与下游写入的瓶颈
- 低版本默认参数可能成为性能瓶颈,特别是
committer-concurrency
- DDL 操作,存在数据同步的集群需谨慎评估版本兼容性
- 7.1 版本 TiCDC changefeed 可能会卡住,重启大法有效