📣
TiDB Cloud Premium 开放公测中。为企业级工作负载提供无限扩展、即时弹性伸缩和高级安全保障。立即体验 →

TiCDC 表路由 从 v8.5.7 开始引入




TiCDC 表路由 (Table Routing) 允许你通过 changefeed 配置,将上游表映射到指定的下游库名或表名。该功能仅适用于 TiCDC 新架构,不支持 TiCDC 老架构

表路由只会改变 TiCDC 输出到下游的库名和表名,不会改变行数据、列名、表结构、表过滤规则、Topic 分发规则、Partition 分发规则或列选择规则。

使用场景

表路由适用于以下场景:

  • sales.orders 同步到 archive.sales_orders,或同步到符合其他下游命名规范的表。
  • 将多个源库同步到同一个目标库,并通过保持目标表名唯一区分源库,例如将 tenant_001.orders 同步到 tenant_mirror.tenant_001_orders
  • 构建迁移、容灾、归档或影子 Changefeed,避免写入与上游同名的下游对象。
  • 向 MQ 消费程序或存储服务暴露稳定的库表名。

配置表路由

配置前,请先启用 TiCDC 新架构。详情参见 newarch

以下示例将 sales.orders 路由到 archive.sales_orders

[sink] [[sink.dispatchers]] matcher = ["sales.orders"] target-schema = "archive" target-table = "{schema}_{table}"

Changefeed 启动后,sales.orders 的 DML 和 DDL 事件会写入下游的 archive.sales_orders

配置字段

你可以通过 sink.dispatchers 的以下字段配置表路由功能。

字段描述
matcher匹配上游库表。语法与表库过滤语法相同,包括 sales.* 这类通配符匹配,以及 !sales.tmp_* 这类排除匹配。
target-schema指定下游库名。如果不设置该字段,TiCDC 保持上游库名不变。
target-table指定下游表名。如果不设置该字段,TiCDC 保持上游表名不变。

匹配行为如下:

  • 只有设置了 target-schematarget-tablesink.dispatchers 规则才会参与表路由。
  • 如果一张表匹配多条表路由规则,只有 sink.dispatchers 中第一条匹配的规则会生效。
  • matcher 始终匹配上游库表名,而不是路由后的目标库表名。
  • Changefeed 配置项 case-sensitive 只影响表路由的 matcher 是否大小写敏感,不会改写 {schema}{table} 展开结果的大小写。详情参见 case-sensitive

占位符

你可以在 target-schematarget-table 中使用以下占位符:

占位符描述
{schema}上游库名,保留实际匹配到的库名大小写。
{table}上游表名,保留实际匹配到的表名大小写。

target-schematarget-table 的值只能包含字面文本、{schema}{table}。如果使用 {db} 这类未知占位符,TiCDC 会拒绝该 Changefeed 配置,并返回 CDC:ErrInvalidTableRoutingRule 错误。

以源表 sales.orders 为例:

配置目标表
target-schema = "archive"archive.orders
target-table = "{table}_bak"sales.orders_bak
target-schema = "{schema}_mirror"sales_mirror.orders
target-schema = "archive"target-table = "{schema}_{table}"archive.sales_orders

示例

路由一个库中的所有表

以下配置将 sales 库中的所有表路由到 archive 库,并在目标表名后追加 _bak

[filter] rules = ["sales.*"] [sink] [[sink.dispatchers]] matcher = ["sales.*"] target-schema = "archive" target-table = "{table}_bak"

路由结果示例如下:

  • sales.orders 会路由到 archive.orders_bak
  • sales.order_items 会路由到 archive.order_items_bak

将多个库路由到同一个目标库

将多个库路由到同一个目标库时,建议在 target-table 中包含 {schema},以确保目标表名唯一。

[filter] rules = ["sales.*", "crm.*", "finance.*"] [sink] [[sink.dispatchers]] matcher = ["sales.*", "crm.*", "finance.*"] target-schema = "archive" target-table = "{schema}_{table}"

路由结果示例如下:

  • sales.orders 会路由到 archive.sales_orders
  • crm.orders 会路由到 archive.crm_orders
  • finance.orders 会路由到 archive.finance_orders

同时使用表路由和 Kafka Sink Topic、Partition 分发器

同一条 dispatcher 规则可以同时包含表路由字段和已有的分发字段:

[filter] rules = ["sales.orders"] [sink] [[sink.dispatchers]] matcher = ["sales.orders"] topic = "order-events" partition = "index-value" target-schema = "public" target-table = "orders"

在以上示例中,表路由将下游数据中暴露的库表名改为 public.orders

表路由不会改变 Topic 或 Partition 的分发结果,topicpartition 分发器仍然按照上游表 sales.orders 进行匹配和分发计算。

输出行为

Sink行为
MySQL SinkDDL 和 DML 语句会写入路由后的目标库表。开启 Redo 功能时,执行 redo apply 会将事件回放到路由后的目标表。
Kafka Sink 和 Pulsar Sink协议中的 payload 字段值和 DDL 事件中的 query 字段值使用路由后的目标库表名;编码协议中的 schematable 字段值也会使用路由后的目标库表名。
Cloud Storage SinkTiCDC 根据路由后的目标库表名生成对应的存储路径、schema 文件、表定义文件和数据文件。

DDL 行为

启用表路由后,TiCDC 会改写 DDL 语句,使结构化 DDL 元数据和 SQL 文本中的库表名保持一致。

例如,如果配置以下规则:

[[sink.dispatchers]] matcher = ["sales.*"] target-schema = "archive" target-table = "{table}_routed"

TiCDC 会将以下上游 DDL:

RENAME TABLE `sales`.`temp_table` TO `sales`.`renamed_table`;

改写为以下下游 DDL:

RENAME TABLE `archive`.`temp_table_routed` TO `archive`.`renamed_table_routed`;

如果 DDL 语句中包含表引用,且这些表引用匹配表路由规则,TiCDC 也会改写被引用的表名。例如,CREATE VIEW 语句中的表引用,以及 ALTER TABLE 语句中的外键引用都可以被改写。

对于 CREATE DATABASEDROP DATABASEALTER DATABASE ... CHARACTER SET/COLLATE 这类库级 DDL,如果库名匹配表路由规则,TiCDC 会改写库名。如果同一个上游库匹配多条表路由规则,且这些规则解析出的目标库名不同,TiCDC 无法为该库级 DDL 确定唯一目标库,Changefeed 会返回表路由错误。

创建或更新 Changefeed 时,TiCDC 会基于当前同步范围内的表检查目标表冲突。运行期间,TiCDC 会在同步 CREATE TABLERENAME TABLEDROP TABLEDROP DATABASE 等 DDL 时更新冲突检测状态。库级 DDL 是否能确定唯一目标库,会在同步对应 DDL 时判断。

路由冲突检测

当两张不同的上游表在同一个 Changefeed 内被路由到同一个下游 (schema, table) 时,会发生路由冲突。TiCDC 不支持将多张上游表合并到同一张下游表。

例如,以下配置可能导致冲突:

[filter] rules = ["sales.*", "crm.*"] [sink] [[sink.dispatchers]] matcher = ["sales.*"] target-schema = "archive" target-table = "{table}" [[sink.dispatchers]] matcher = ["crm.*"] target-schema = "archive" target-table = "{table}"

如果 sales.orderscrm.orders 都在同步范围内,这两张表都会被路由到 archive.orders。TiCDC 会拒绝创建或更新 Changefeed,并返回 CDC:ErrTableRouteConflict 错误。

Changefeed 运行期间,如果 CREATE TABLERENAME TABLE 等 DDL 导致两张在当前同步范围内的上游表被路由到同一张目标表,Changefeed 会失败并返回 CDC:ErrTableRouteConflict 错误。

如果上游表被删除或重命名,TiCDC 会解除该上游表与目标表之间的路由关系。之后,新的上游表可以继续使用该目标表,但在同一时刻同一个目标表只能对应一张正在被当前 Changefeed 同步的上游表。

故障排查

现象可能原因解决方法
创建或更新 Changefeed 时报 CDC:ErrInvalidTableRoutingRule 错误。matcher 语法无效,或 target-schematarget-table 包含未知占位符或不匹配的大括号。检查 matcher 是否符合表库过滤语法,并确保 target-schematarget-table 只使用字面文本、{schema}{table}
MQ Topic 名仍然使用上游库表名。表路由不会改变 Topic 或 Partition 分发规则。如果需要修改 Topic 名,请在 sink.dispatchers 中单独配置 topic
DDL 同步时报 CDC:ErrTableRoutingFailed 错误。该 DDL 无法安全地进行表路由改写,或库级 DDL 存在目标库歧义。检查 DDL 类型和路由规则。对于库级 DDL,确保同一个上游库只能解析到一个目标库。
Changefeed 运行中失败并报 CDC:ErrTableRouteConflict 错误。新建表或重命名表后,两个不同的上游表被路由到同一个下游表。调整表路由规则或上游 DDL,确保单个 Changefeed 内每个目标表在同一时刻只对应一张正在被当前 Changefeed 同步的上游表。

相关文档

文档内容是否有帮助?