@王军 补充判断依据的完整版:
社区问题 topic/1057704 — TiCDC v8.5.5 主备集群同步反复故障
结论
不是 TiCDC 代码 bug。 是下游连接周期性被杀 + TiCDC 连接池缺少主动回收 + changefeed 被外部停止的复合运维问题。
判断依据
依据 1:重试远未耗尽,changefeed 被外部停止
源码 mysql.go:56 定义 DML sink 最大重试 8 次,退避区间 500ms → 60s 指数抖动。
客户 cdc.log(30 条,410 行):
| 指标 | 实际值 | 自然耗尽应达到 |
|---|---|---|
invalid connection WARN |
11 次(5 个 worker 各自若干次) | 8 × 5 = 40 次 |
| 时间跨度 | 22:05:54 ~ 22:09:00(3 分钟) | ~6 分钟(8 次退避累计) |
| 结束方式 | 22:09:00.263 统一时刻 context canceled | 最后一次重试失败 → changefeed failed |
| worker 受影响 | 5 个(0, 2, 5, 6, 10) | — |
关键铁证:22:09:00.263 这同一毫秒内,5 个 worker 同时收到 context canceled,同时出现 Sink manager exists [error="context canceled"]。源码 txn_dml_sink.go:133-138 过滤 context.Canceled 不上报 errCh,changefeed 不会自动进入 failed 状态。只有外部信号(用户 pause、CDC server 重启、SIGTERM)才能在同一毫秒取消所有 worker 的 context。
依据 2:下游连接被杀的根因链
日志时间线反推:
[~22:03:54] 下游 TiDB 连接首次失效(22:05:54 首次 WARN - duration 2m0.001s 反推)
↓
[22:05:54 ~ 22:07:55] 5 个 worker 各自重试,11 次 WARN "invalid connection"
↓ 每次 duration=2m0s~2m5s(与源码退避策略吻合)
[22:07:51 ~ 22:07:57] 5 次 "failed to rollback txn"(连接已断,rollback 也失败)
↓
[22:09:00.263] 外部 context canceled → 6 次 ERROR "can not retry" + 5 次 flush fail + 2 worker exit
所有 DML 操作均报 invalid connection:BEGIN、COMMIT、SET SESSION tidb_cdc_write_source = 1、REPLACE、DELETE — 说明不是特定 SQL 导致,是连接本身已死。
依据 3:TiCDC 连接池缺少主动回收机制
源码 mysql.go:131-132:
db.SetMaxIdleConns(cfg.WorkerCount + 1)
db.SetMaxOpenConns(cfg.WorkerCount + 1)
// 缺少 db.SetConnMaxLifetime()
// 缺少 db.SetConnMaxIdleTime()
TiCDC 连接池不主动回收旧连接。当下游 MySQL wait_timeout 或中间 LB/NAT/Firewall 的 idle timeout 关闭连接后,TiCDC 不感知,下次复用该死连接 → driver.ErrBadConn(invalid connection)。
运行 2 个月故障 2 次的周期性:如果 LB/NAT idle timeout 为 1~2 小时,低流量时段连接空闲被杀;CDC 复用死连接时刚好触发故障。这个模式与"间歇性、周期性"完全吻合。
依据 4:nightly build 版本风险
cdc.log 堆栈中 tiflow 版本:v0.0.0-20251226072601-0cb0aaf25061(2025-12-26 nightly),不是 v8.5.5 正式 release。nightly 可能包含未发布的变更或回归。
依据 5:历史工单验证(@wiki_ticket KB 反查)
历史工单中 invalid connection 的根因均为下游/网络层问题,无 TiCDC 代码 bug 先例。
对客回复建议
P0 排查(回复用户时先问):
- 22:09:00 前后是否手动 stop/pause 了 changefeed 或重启了 CDC server?
- 确认实际版本:
tiup cluster display,nightly 切回正式 release - 下游 TiDB:
SHOW VARIABLES LIKE 'wait_timeout',确保 ≥ 28800 - 主备间网络设备:LB/NAT/Firewall 的 idle timeout 配置
- 下游是否设了
tidb_restricted_read_only
P1 预防措施:
- sink-url 加
read-timeout=2h延长超时(官方文档建议) - 下游计划维护:先
tiup ctl cdc changefeed pause→ 维护完成 →resume→ 观察 checkpoint lag 归零 - gc-ttl 默认 24h:下游停机超 24h 会导致上游 GC → 链路失效需重做
- 停机超 3 天建议重做同步链路
P2 故障恢复:
tiup ctl cdc changefeed resume --changefeed-id=default.ly-to-fs
# 观察 checkpoint lag 是否回落到 0