TiCDC 故障处理
本文档总结了使用 TiCDC 过程中常见的运行故障及解决方案。
TiCDC 同步任务出现中断
如何判断 TiCDC 同步任务出现中断?
- 通过 Grafana 检查同步任务的
changefeed checkpoint监控项。注意选择正确的changefeed id。如果该值不发生变化或者查看checkpoint lag是否不断增大,可能同步任务出现中断。 - 通过 Grafana 检查
exit error count监控项,该监控项大于 0 代表同步任务出现错误。 - 通过
cdc cli changefeed list和cdc cli changefeed query命令查看同步任务的状态信息。任务状态为stopped代表同步中断,error项会包含具体的错误信息。任务出错后可以在 TiCDC server 日志中搜索error on running processor查看错误堆栈,帮助进一步排查问题。 - 部分极端异常情况下 TiCDC 出现服务重启,可以在 TiCDC server 日志中搜索
FATAL级别的日志排查问题。
如何查看 TiCDC 同步任务是否被人为终止?
可以使用 cdc cli 查询同步任务是否被人为终止。例如:
cdc cli changefeed query --server=http://127.0.0.1:8300 --changefeed-id 28c43ffc-2316-4f4f-a70b-d1a7c59ba79f
上述命令的输出中 state 标志这个同步任务的状态,状态的值和含义参考 TiCDC 同步任务状态。
如何处理 TiCDC 同步任务的中断?
目前已知可能发生的同步中断包括以下场景:
下游持续异常,TiCDC 多次重试后仍然失败。
- 该场景下 TiCDC 会保存任务信息,由于 TiCDC 已经在 PD 中设置的 service GC safepoint,在
gc-ttl的有效期内,同步任务 checkpoint 之后的数据不会被 TiKV GC 清理掉。 - 处理方法:在下游恢复正常后,通过
cdc cli changefeed resume恢复同步任务。
- 该场景下 TiCDC 会保存任务信息,由于 TiCDC 已经在 PD 中设置的 service GC safepoint,在
因下游存在不兼容的 SQL 语句,导致同步不能继续。
- 该场景下 TiCDC 会保存任务信息,由于 TiCDC 已经在 PD 中设置的 service GC safepoint,在
gc-ttl的有效期内,同步任务 checkpoint 之后的数据不会被 TiKV GC 清理掉。 - 处理方法:
- 先通过
cdc cli changefeed query查询同步任务状态信息,记录checkpoint-ts值。 - 使用新的任务配置文件,增加
ignore-txn-start-ts参数跳过指定start-ts对应的事务。 - 通过
cdc cli changefeed pause -c <changefeed-id>暂停同步任务。 - 通过
cdc cli changefeed update -c <changefeed-id> --config <config-file-path>指定新的任务配置文件。 - 通过
cdc cli changefeed resume -c <changefeed-id>恢复同步任务。
- 先通过
- 该场景下 TiCDC 会保存任务信息,由于 TiCDC 已经在 PD 中设置的 service GC safepoint,在
同步任务中断,尝试再次启动后 TiCDC 发生 OOM,应该如何处理?
升级 TiDB 集群和 TiCDC 集群到最新版本。该 OOM 问题在 v4.0.14 及之后的 v4.0 版本,v5.0.2 及之后的 v5.0 版本,更新的版本上已得到缓解。
如何处理 TiCDC 创建同步任务或同步到 MySQL 时遇到 Error 1298: Unknown or incorrect time zone: 'UTC' 错误?
这是因为下游 MySQL 没有加载时区,可以通过 mysql_tzinfo_to_sql 命令加载时区,加载后就可以正常创建任务或同步任务。
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p
显示类似于下面的输出则表示导入已经成功:
Enter password:
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
如果下游是特殊的 MySQL 环境(某种公有云 RDS 或某些 MySQL 衍生版本等),使用上述方式导入时区失败,则可以通过在 Sink URI 中设置 time-zone 为空值来使用下游默认时区,例如:time-zone=""。注意该参数仅对 mysql 和 tidb 类型的 sink 生效。
在使用 MySQL 和 TiDB sink 时,建议显式指定时区,例如:time-zone="Asia/Shanghai"。同时,请确保 TiCDC Server 的 tz 时区配置、Sink URI 中的 time-zone 时区配置和下游数据库的时区配置保持一致。这样可以避免因时区不一致导致数据不一致的问题。
如何处理升级 TiCDC 后配置文件不兼容的问题?
请参阅配置文件兼容注意事项。
TiCDC 启动任务的 start-ts 时间戳与当前时间差距较大,任务执行过程中同步中断,出现错误 [CDC:ErrBufferReachLimit],怎么办?
自 v4.0.9 起可以尝试开启 unified sorter 特性进行同步;或者使用 BR 工具进行一次增量备份和恢复,然后从新的时间点开启 TiCDC 同步任务。TiCDC 将会在后续版本中对该问题进行优化。
当 changefeed 的下游为类 MySQL 数据库时,TiCDC 执行了一个耗时较长的 DDL 语句,阻塞了所有其他 changefeed,应该怎样处理?
- 首先暂停执行耗时较长的 DDL 的 changefeed。此时可以观察到,这个 changefeed 暂停后,其他的 changefeed 不再阻塞了。
- 在 TiCDC log 中搜寻
apply job字段,确认耗时较长的 DDL 的start-ts。 - 手动在下游执行该 DDL 语句,执行完毕后进行下面的操作。
- 修改 changefeed 配置,将上述
start-ts添加到ignore-txn-start-ts配置项中。 - 恢复被暂停的 changefeed。
使用 TiCDC 创建 changefeed 时报错 [tikv:9006]GC life time is shorter than transaction duration, transaction starts at xx, GC safe point is yy,该如何处理?
执行 pd-ctl service-gc-safepoint --pd <pd-addrs> 命令查询当前的 GC safepoint 与 service GC safepoint。如果 GC safepoint 小于 TiCDC changefeed 同步任务的开始时间戳 start-ts,可以直接在 cdc cli create changefeed 命令后加上 --disable-gc-check 参数创建 changefeed。
如果 pd-ctl service-gc-safepoint --pd <pd-addrs> 的结果中没有 gc_worker service_id:
- 如果 PD 的版本 <= v4.0.8,详见 PD issue #3128。
- 如果 PD 是由 v4.0.8 或更低版本滚动升级到新版,详见 PD issue #3366。
- 对于其他情况,请将上述命令执行结果反馈到 AskTUG 论坛。
使用 TiCDC 同步消息到 Kafka 时 Kafka 报错 Message was too large,该如何处理?
遇到此错误时,需要同时检查 TiCDC Kafka Sink URI 中的 max-message-bytes 和接收消息的 Kafka Topic 的 max.message.bytes,确保两者配置兼容。
TiCDC 使用 Sink URI 中的 max-message-bytes 作为发送消息的上限,而 Kafka Topic 的 max.message.bytes 限制接收的记录批次(record batch)的大小(启用压缩时为压缩后的大小)。TiCDC 还会根据默认 Topic 的 max.message.bytes 调整实际发送上限,并预留协议开销。如果配置了 Topic 分发器,数据可能发送到另一个 Topic;实际接收消息的 Topic 也必须允许该消息大小。只修改 Sink URI 或其中一个 Topic,仍可能出现消息过大的错误。
先使用 cdc cli changefeed query 查看当前 Sink URI 中的默认 Topic,并检查 changefeed 配置中的 Topic 分发规则,确认所有可能接收消息的 Topic:
cdc cli changefeed query --server=http://127.0.0.1:8300 --changefeed-id=test-cf
以下以 10 MiB(10485760 字节)为例,将默认 Topic default-topic 和一个分发后的 Topic routed-topic 的上限设置为该值。请根据实际消息大小和现有配置确定目标上限;如果现有上限更高,不要直接将其降低为示例值。将命令中的 Kafka 地址、Topic 名称和上限值替换为实际值。如果 Topic 分发器会将消息发送到多个 Topic,需要修改所有可能接收消息的 Topic;如果没有配置 Topic 分发器,只需修改默认 Topic。
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name default-topic \
--alter --add-config max.message.bytes=10485760
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name routed-topic \
--alter --add-config max.message.bytes=10485760
查询默认 Topic 和所有可能接收消息的分发 Topic,确认各 Topic 的 max.message.bytes 已更新为目标值。以下命令对应上述示例;未配置 Topic 分发器时,只需查询默认 Topic。
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name default-topic --describe
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name routed-topic --describe
然后修改 changefeed 的 Sink URI。--sink-uri 接收完整 URI,更新时需要保留原有的协议、认证和其他参数。以下示例将 max-message-bytes 设置为 10485760;实际使用时请替换为确定的目标值。
若 changefeed 正在运行,先暂停任务,再查询并确认其状态为 stopped。若任务已处于 stopped 或 failed 状态,可直接执行更新命令。
cdc cli changefeed pause --server=http://127.0.0.1:8300 --changefeed-id=test-cf
cdc cli changefeed query --server=http://127.0.0.1:8300 --changefeed-id=test-cf
执行更新命令,检查输出的配置差异,并按提示确认应用:
cdc cli changefeed update --server=http://127.0.0.1:8300 --changefeed-id=test-cf \
--sink-uri='kafka://127.0.0.1:9092/default-topic?protocol=canal-json&max-message-bytes=10485760'
确认更新成功后,再恢复任务:
cdc cli changefeed resume --server=http://127.0.0.1:8300 --changefeed-id=test-cf
恢复任务后,执行以下命令,确认查询结果中的 Sink URI 包含更新后的 max-message-bytes 参数,且 changefeed 状态恢复为 normal:
cdc cli changefeed query --server=http://127.0.0.1:8300 --changefeed-id=test-cf
间隔一段时间重复查询,确认 checkpoint-ts 持续推进,并检查 TiCDC 日志中是否再次出现消息过大的错误。
TiCDC 同步时,在下游执行 DDL 语句失败会有什么表现,如何恢复?
如果某条 DDL 语句执行失败,同步任务 (changefeed) 会自动停止,checkpoint-ts 断点时间戳为该条出错 DDL 语句的结束时间戳 (finish-ts)。如果希望让 TiCDC 在下游重试执行这条 DDL 语句,可以使用 cdc cli changefeed resume 恢复同步任务。例如:
cdc cli changefeed resume -c test-cf --server=http://127.0.0.1:8300
如果希望跳过这条出错的 DDL 语句,可以通过配置 ignore-txn-start-ts 参数跳过指定的 start-ts 对应的事务。例如:
- 首先在 TiCDC 日志中搜寻
apply job字段,确认耗时较长的 DDL 操作的start-ts。 - 修改 changefeed 配置,将上述
start-ts添加到ignore-txn-start-ts配置项中。 - 恢复被暂停的 changefeed。
cdc cli changefeed remove --server=http://127.0.0.1:8300 --changefeed-id simple-replication-task
cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri="mysql://root:123456@127.0.0.1:3306/" --changefeed-id="simple-replication-task" --sort-engine="unified" --start-ts 415241823337054210
使用 TiCDC 同步消息到 Kafka 时报错 kafka: client has run out of available brokers to talk to: EOF,该如何处理?
该问题通常是由于 TiCDC 与 Kafka 集群连接失败导致。你可以通过检查 Kafka 的日志以及网络状况来排查。一个常见的原因是在创建同步任务时没有指定正确的 kafka-version 参数,导致 TiCDC 内部的 Kafka client 在访问 Kafka server 时使用了错误的 Kafka API 版本。你可以通过配置 --sink-uri 指定正确的 kafka-version 参数来修复。例如:
cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri "kafka://127.0.0.1:9092/test?topic=test&protocol=open-protocol&kafka-version=2.4.0"