​
​

Changefeed DDL 同步




本文档介绍了 TiCDC 同步 DDL 的规则和特殊情况。

DDL 白名单

目前 TiCDC 在同步 DDL 时使用白名单策略,只有在白名单中的 DDL 操作才会被同步到下游系统,不在白名单中的 DDL 操作将不会被 TiCDC 同步。

此外,TiCDC 会根据表中是否具有有效索引以及配置项 force-replicate 是否为 true 来决定是否将 DDL 同步到下游。当 force-replicate=true 时,同步任务会尝试强制同步没有有效索引的表。

以下为 TiCDC 支持同步的 DDL 的列表。该表中出现的缩写字母含义如下:

  • Y:在该条件下可以同步到下游。
  • N:在该条件下不会同步到下游。
DDL存在有效索引无有效索引且 force-replicate 为默认值 false无有效索引且 force-replicate 为 true
CREATE DATABASEYYY
DROP DATABASEYYY
ALTER DATABASE CHARACTER SETYYY
CREATE INDEXYYY
ADD INDEXYYY
DROP INDEXYNY
ADD PRIMARY KEYYYY
DROP PRIMARY KEYYNY
CREATE TABLEYNY
DROP TABLEYNY
ADD COLUMNYNY
DROP COLUMNYNY
TRUNCATE TABLEYNY
MODIFY COLUMNYNY
RENAME TABLEYNY
ALTER COLUMN DEFAULT VALUEYNY
ALTER TABLE COMMENTYNY
RENAME INDEXYNY
ADD PARTITIONYNY
DROP PARTITIONYNY
TRUNCATE PARTITIONYNY
CREATE VIEWYNY
DROP VIEWYNY
ALTER TABLE CHARACTER SETYNY
RECOVER TABLEYNY
REBASE AUTO IDYNY
ALTER TABLE INDEX VISIBILITYYNY
EXCHANGE PARTITIONYNY
REORGANIZE PARTITIONYNY
ALTER TABLE TTLYNY
ALTER TABLE REMOVE TTLYNY

DDL 同步注意事项

创建和添加索引 DDL 的异步执行

虽然 TiCDC 在大多数情况下会按顺序同步 DDL,但如果下游是 TiDB,TiCDC 会异步执行创建和添加索引的 DDL 操作,即 TiCDC 将 ADD INDEX 和 CREATE INDEX DDL 同步到下游执行后,会立刻返回,而不会等待 DDL 操作完成。这样可以减小对 Changefeed 同步延迟的影响,避免阻塞后续的 DML 执行。

当 ADD INDEX 或 CREATE INDEX DDL 操作在下游执行期间,TiCDC 执行同一张表的下一条 DDL 时,这条 DDL 可能长期被阻塞在 queueing 状态,导致其被 TiCDC 重复执行多次,重试时间过长时还会导致同步任务失败。从 v8.4.0 开始,如果拥有下游数据库的 SUPER 权限,TiCDC 会定期执行 ADMIN SHOW DDL JOBS 查询异步执行的 DDL 任务的状态,等到索引创建完成后再继续同步。这期间虽然同步任务的延迟会加剧,但避免了同步任务失败的问题。

Rename table 类型的 DDL 注意事项

TiCDC 根据重命名前后的库表名和过滤规则决定是否同步 Rename DDL。以下示例假设表满足同步要求,且未配置额外的 DDL 事件过滤规则。

一条 DDL 语句内 rename 单个表

如果一条 DDL 语句重命名单个表,则只有旧表名符合过滤规则时,TiCDC 才会同步该 DDL 语句。下面使用具体示例进行说明。

假设你的 changefeed 的配置文件如下:

[filter] rules = ['test.t*']

那么,TiCDC 对该类型 DDL 的处理行为如下表所示:

DDL是否同步原因和处理方式
RENAME TABLE test.t1 TO test.t2同步test.t1 符合 filter 规则
RENAME TABLE test.t1 TO ignore.t1同步test.t1 符合 filter 规则
RENAME TABLE ignore.t1 TO ignore.t2忽略ignore.t1 不符合 filter 规则
RENAME TABLE test.n1 TO test.t1报错,并停止同步。旧表名 test.n1 不符合 filter 规则,但是新表名 test.t1 符合 filter 规则,这是非法操作。请参考错误提示信息进行处理
RENAME TABLE ignore.t1 TO test.t1报错,并停止同步。理由同上

以上规则适用于新老架构。如果旧表名匹配过滤规则而新表名不匹配,TiCDC 会同步 Rename DDL,随后停止同步该表的后续数据变更。如果旧表名不匹配而新表名匹配,TiCDC 会报 CDC:ErrSyncRenameTableFailed 错误,因为仅同步 Rename 无法补齐该表此前未同步的数据。

一条 DDL 语句内 rename 多个表

如果一条 DDL 语句重命名多个表,新架构会按单表 Rename 的规则逐个判断:

  • 如果旧表名匹配过滤规则,TiCDC 会同步对应的重命名步骤。
  • 如果新旧表名均不匹配过滤规则,TiCDC 会忽略该步骤。
  • 如果旧表名不匹配而新表名匹配过滤规则,Changefeed 会报错并停止同步。

此外,老架构还要求每个需要同步的重命名步骤的目标库位于同步范围内,并且不支持同步互换表名的 RENAME TABLE 语句。

假设你的 changefeed 的配置文件如下:

[filter] rules = ['test.t*']

那么,TiCDC 对该类型的处理行为如下表所示:

DDL老架构新架构原因
RENAME TABLE test.t1 TO test.t2, test.t3 TO test.t4同步同步新旧库表名均匹配过滤规则
RENAME TABLE test.t1 TO test.ignore1, test.t3 TO test.ignore2同步同步两种架构都要求旧表名匹配过滤规则,老架构还额外要求目标库在同步范围内。同步 Rename 后,TiCDC 停止同步改名后的表的后续数据变更
RENAME TABLE test.t1 TO ignore.t1, test.t2 TO test.t22报错同步目标库 ignore 不在同步范围内。新架构同步 Rename 后,停止同步 ignore.t1,继续同步 test.t22
RENAME TABLE test.t1 TO test.t2, ignore.t1 TO ignore.t2仅同步 test.t1 的重命名步骤仅同步 test.t1 的重命名步骤ignore.t1 和 ignore.t2 均不匹配过滤规则
RENAME TABLE test.t1 TO test.t2, ignore.t1 TO test.t3报错报错ignore.t1 不匹配而 test.t3 匹配过滤规则
RENAME TABLE test.t1 TO test.t4, test.t3 TO test.t1, test.t4 TO test.t3报错同步通过临时表名 test.t4 交换两个表的名字,新架构保留各个重命名步骤的顺序

新架构会协调一次多表 Rename 涉及的所有表的同步进度,但会将下游 SQL 重建为多条单表 RENAME TABLE 语句。MySQL Sink 执行由分号分隔的多条子语句,Kafka 和 Pulsar Sink 则拆分为单表 DDL 消息。因此,下游执行不保证保留上游单条多表 Rename 语句的原子性。使用临时表名互换表名时,需要保留所有相互依赖的步骤,避免通过过滤规则移除其中的步骤。

DDL 语句注意事项

当在上游执行跨数据库的 DDL 语句(如 CREATE TABLE db1.t1 LIKE t2)时,建议在 DDL 语句中显式地指定所有相关的库名(如 CREATE TABLE db1.t1 LIKE db2.t2)。否则,由于缺少库名信息,跨数据库的 DDL 语句可能无法正确地在下游执行。

DDL SQL 文本的处理

TiCDC 会解析、格式化或重建 DDL SQL,因此同步到下游的 SQL 文本不保证与上游原语句逐字一致。新老架构都会规范关键字大小写、标识符引号、空格和部分同义语法,也都会针对 TiDB 特有语法进行兼容处理。DROP TABLE、DROP VIEW 和 EXCHANGE PARTITION 等 DDL 在两种架构中都有 SQL 重建逻辑。

新架构还可能进行以下处理。除特别注明的 MySQL Sink 改写外,这些处理也会影响支持 DDL 的消息协议中的 SQL 字段。具体输出形式可能随 TiCDC 版本变化。

DDL 或场景新架构的 SQL 文本处理适用条件
单表 Rename统一重建为带完整库表名的 RENAME TABLE db.old_table TO db.new_table包括 ALTER TABLE ... RENAME AS ...、ALTER TABLE ... RENAME TO ... 和普通 RENAME TABLE ... TO ...,未启用表路由时也会改写
多表 Rename按原顺序重建为多条单表 RENAME TABLE,每条子语句带尾部 ;MySQL Sink 接收组合 SQL;Kafka、Pulsar 等逐表输出的路径会将其拆分为多条消息
批量建表拆分后的每条 CREATE TABLE 语句带尾部 ;上游批量建表产生一个包含多张表的 DDL 事件,且下游按单表事件输出
CREATE TABLE ... LIKE ...为 LIKE 引用表补全库名原 SQL 未限定引用表的库名,且 DDL 元数据表明引用表与目标表位于不同库
CREATE VIEW 和 CREATE OR REPLACE VIEW使用 TiDB 存储的视图查询及 DDL 时刻的库表元数据重建 SQL,可能补全表和列引用的库名、规范标识符大小写或补充列别名视图定义中的名称需要解析时;不要求启用表路由
匿名二级索引为 ALTER TABLE ... ADD INDEX/KEY/... 中未指定名称的索引补上上游生成的索引名,包括一条 ALTER TABLE 中的多个变更操作仅在 MySQL Sink 向 MySQL 或 TiDB 执行 DDL 前处理,不适用于 MQ 消息中的 SQL
名称中包含反引号的库、表或分区重建 SQL 时,将名称内的反引号转义为两个反引号包括 Rename、DROP TABLE、DROP VIEW 和 EXCHANGE PARTITION 等需要重建 SQL 的场景
表路由根据路由规则改写库名、表名及相关引用,并重新生成 SQL配置了 target-schema 或 target-table,详情参见表路由的 DDL 行为

例如,假设当前数据库为 db,未启用表路由,且未过滤以下 Rename 事件,单表 Rename 的输出如下。表中省略语句结束分号。

上游 SQL老架构输出新架构输出
ALTER TABLE a RENAME AS bALTER TABLE `a` RENAME AS `b` RENAME TABLE `db`.`a` TO `db`.`b`
ALTER TABLE a RENAME TO bALTER TABLE `a` RENAME AS `b` RENAME TABLE `db`.`a` TO `db`.`b`
RENAME TABLE a TO bRENAME TABLE `a` TO `b` RENAME TABLE `db`.`a` TO `db`.`b`

对于 RENAME TABLE a TO b, c TO d,按单表事件输出时,老架构第一条 SQL 为 RENAME TABLE `db`.`a` TO `db`.`b` ,新架构为 RENAME TABLE `db`.`a` TO `db`.`b`;。尾部分号来自新架构的多表 DDL 拆分处理。

编写下游消费者或比较新老架构输出时,应解析 SQL,并结合 DDL 类型和库表元数据判断其含义,而不是直接比较 SQL 文本。库名、表名、索引名及其大小写仍需按具体场景校验,避免忽略名称解析或表路由错误。

使用 Event Filter 过滤 DDL 事件的注意事项

如果被过滤的 DDL 语句涉及表的创建或删除,TiCDC 只会过滤掉这些 DDL 语句,而不影响 DML 的同步行为。下面使用具体示例进行说明。

假设你的 changefeed 的配置文件如下:

[filter] rules = ['test.t*'] [[filter.event-filters]] matcher = ["test.t1"] # 该过滤规则只应用于 test 库中的 t1 表 ignore-event = ["create table", "drop table", "truncate table", "rename table"]
DDLDDL 行为DML 行为原因
CREATE TABLE test.t1 (id INT, name VARCHAR(50));忽略同步test.t1 符合 Event Filter 过滤规则,CREATE TABLE 事件被忽略,但不影响 DML 事件的同步
CREATE TABLE test.t2 (id INT, name VARCHAR(50));同步同步test.t2 不符合 Event Filter 过滤规则
CREATE TABLE test.ignore (id INT, name VARCHAR(50));忽略忽略test.ignore 符合 Table Filter 过滤规则,因此 DDL 和 DML 事件均被忽略
DROP TABLE test.t1;忽略-test.t1 符合 Event Filter,DROP TABLE 事件被忽略。该表已被删除,TiCDC 不再同步 t1 的 DML 事件
TRUNCATE TABLE test.t1;忽略同步test.t1 符合 Event Filter,TRUNCATE TABLE 事件被忽略,但不影响 DML 事件的同步
RENAME TABLE test.t1 TO test.t2;忽略同步test.t1 符合 Event Filter,RENAME TABLE 事件被忽略,但不影响 DML 事件的同步
RENAME TABLE test.t1 TO test.ignore;忽略忽略test.t1 符合 Event Filter,RENAME TABLE 事件被忽略,test.ignore 符合 Table Filter 过滤规则,因此 DDL 和 DML 事件均被忽略

使用 ignore-sql 过滤多表 Rename 时,需要注意新老架构的匹配输入不同。老架构在拆分为单表 DDL 事件后,使用 ignore-sql 匹配每条 SQL。新架构逐表应用事件过滤规则时,使用 ignore-sql 匹配整个多表重命名操作重建后的 SQL。如果同一条事件过滤规则的 matcher 匹配多张表,ignore-sql 匹配到其中一个重命名步骤,也可能过滤该规则覆盖的其他重命名步骤。切换架构前,应检查此类过滤规则的实际匹配结果。

文档内容是否有帮助?