dm同步上游mysql分库修改字段时报错,如何跳过该报错

【 TiDB 使用环境】生产环境
【 TiDB 版本】8.5.1
【复现路径】
tidb负责同步上游mysql的数据。上游mysql为分表的order0,order1,order2,order3,同步到tidb的order库中

研发给order0.1库的表新增字段,
order0执行sql为:
ALTER TABLE t_order_$i MODIFY COLUMN mercode VARCHAR(80) NOT NULL DEFAULT ‘0’ COMMENT ‘渠道商户号’"

order1执行sql为:

ALTER TABLE posx_prd.t_order
MODIFY COLUMN mercode VARCHAR(80)
DEFAULT ‘0’ NOT NULL COMMENT ‘渠道商户号’

order0和order1对比差异
CHARACTER SET UTF8MB4
COLLATE utf8mb4_0900_ai_ci
导致 DM 在做 online DDL 一致性校验时失败。
【遇到的问题:问题现象及影响】
[tidb@monitor208 ~]$ tiup dmctl --master-addr 192.168.138.210:8261 query-status test1

A new version of dmctl is available: v8.5.1 → v8.5.6

To update this component:   tiup update dmctl
To update all components:   tiup update --all

Starting component dmctl: /home/tidb/.tiup/components/dmctl/v8.5.1/dmctl/dmctl --master-addr 192.168.138.210:8261 query-status test1
{
“result”: true,
“msg”: “”,
“sources”: [
{
“result”: true,
“msg”: “”,
“sourceStatus”: {
“source”: “wangpu-01”,
“worker”: “dm-192.168.138.212-8262”,
“result”: null,
“relayStatus”: null
},
“subTaskStatus”: [
{
“name”: “test1”,
“stage”: “Paused”,
“unit”: “Sync”,
“result”: {
“isCanceled”: false,
“errors”: [
{
“ErrCode”: 36008,
“ErrClass”: “sync-unit”,
“ErrScope”: “internal”,
“ErrLevel”: “high”,
“Message”: “startLocation: [position: (mysql-bin.003462, 451605667), gtid-set: b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137:2189273139-2192077573], endLocation: [position: (mysql-bin.003462, 451605937), gtid-set: b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137:2189273139-2192077574], origin SQL: [/* ApplicationName=DBeaver 22.3.4 - SQLEditor \u003cScript-7.sql\u003e */ \r\nalter table t_order_1\r\n modify mercode varchar(80) default ‘0’ not null comment ‘渠道商户号’]: detect inconsistent DDL sequence from source [first-location: position: (mysql-bin.003462, 451605667), gtid-set: b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137:2189273139-2192077573 ddls: [ALTER TABLE posx_prd.t_order MODIFY COLUMN mercode VARCHAR(80) DEFAULT ‘0’ NOT NULL COMMENT ‘渠道商户号’] source: posx_prd.t_order_1], right DDL sequence should be [first-location: position: (mysql-bin.003458, 238386347), gtid-set: b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137 ddls: [ALTER TABLE posx_prd.t_order MODIFY COLUMN mercode VARCHAR(80) CHARACTER SET UTF8MB4 COLLATE utf8mb4_0900_ai_ci DEFAULT ‘0’ NOT NULL COMMENT ‘渠道商户号’] source: posx_prd.t_order_0]”,
“RawCause”: “”,
“Workaround”: “Please use show-ddl-locks command for more details.”
}
],
“detail”: null
},
“unresolvedDDLLockID”: “”,
“sync”: {
“totalEvents”: “523252”,
“totalTps”: “401”,
“recentTps”: “0”,
“masterBinlog”: “(mysql-bin.003468, 313408819)”,
“masterBinlogGtid”: “b5082f3c-43e9-11ef-b134-0c42a1475886:1-2195714025”,
“syncerBinlog”: “(mysql-bin.003458, 238386347)”,
“syncerBinlogGtid”: “b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137”,
“blockingDDLs”: [
],
“unresolvedGroups”: [
{
“target”: “posx_prd.t_order”,
“DDLs”: [
“ALTER TABLE posx_prd.t_order MODIFY COLUMN mercode VARCHAR(80) CHARACTER SET UTF8MB4 COLLATE utf8mb4_0900_ai_ci DEFAULT ‘0’ NOT NULL COMMENT ‘渠道商户号’”
],
“firstLocation”: “position: (mysql-bin.003458, 238386347), gtid-set: b5082f3c-43e9-11ef-b134-0c42a1475886:1-2189273137”,
“synced”: [
posx_prd.t_order_0
],
“unsynced”: [
posx_prd.t_order_15”,
posx_prd.t_order_7”,
posx_prd.t_order_9”,
posx_prd.t_order_16”,
posx_prd.t_order_17”,
posx_prd.t_order_27”,
posx_prd.t_order_45”,
posx_prd.t_order_56”,
posx_prd.t_order_13”,
posx_prd.t_order_20”,
posx_prd.t_order_31”,
posx_prd.t_order_38”,
posx_prd.t_order_4”,
posx_prd.t_order_40”,
posx_prd.t_order_14”,
posx_prd.t_order_19”,
posx_prd.t_order_24”,
posx_prd.t_order_10”,
posx_prd.t_order_26”,
posx_prd.t_order_28”,
posx_prd.t_order_44”,
posx_prd.t_order_63”,
posx_prd.t_order_23”,
posx_prd.t_order_35”,
posx_prd.t_order_50”,
posx_prd.t_order_2”,
posx_prd.t_order_32”,
posx_prd.t_order_47”,
posx_prd.t_order_8”,
posx_prd.t_order_11”,
posx_prd.t_order_36”,
posx_prd.t_order_49”,
posx_prd.t_order_1”,
posx_prd.t_order_30”,
posx_prd.t_order_39”,
posx_prd.t_order_33”,
posx_prd.t_order_43”,
posx_prd.t_order_52”,
posx_prd.t_order_59”,
posx_prd.t_order_29”,
posx_prd.t_order_34”,
posx_prd.t_order_57”,
posx_prd.t_order_6”,
posx_prd.t_order_5”,
posx_prd.t_order_21”,
posx_prd.t_order_3”,
posx_prd.t_order_41”,
posx_prd.t_order_53”,
posx_prd.t_order_54”,
posx_prd.t_order_55”,
posx_prd.t_order_58”,
posx_prd.t_order_22”,
posx_prd.t_order_25”,
posx_prd.t_order_48”,
posx_prd.t_order_61”,
posx_prd.t_order_12”,
posx_prd.t_order_18”,
posx_prd.t_order_37”,
posx_prd.t_order_42”,
posx_prd.t_order_46”,
posx_prd.t_order_51”,
posx_prd.t_order_60”,
posx_prd.t_order_62
]
}
],
“synced”: false,
“binlogType”: “remote”,
“secondsBehindMaster”: “0”,
“blockDDLOwner”: “”,
“conflictMsg”: “”,
“totalRows”: “523252”,
“totalRps”: “401”,
“recentRps”: “0”
},
“validation”: null
}
]
}
]
}

使用 tiup dmctl --master-addr 192.168.138.210:8261 handle-error test1 skip 跳过 后 过一会又报错了,而且不同步,这个大佬如何跳过这个报错,让数据继续同步

上游不同分表执行的 DDL 不一致,后续分表执行相同 DDL 时仍会触发校验。导致这样

下游手动补一次正确 DDL → DM 跳过报错 DDL → 继续跑。

下游重建一下ddl语句不久ok了

将所有分表的不一致 DDL 统一替换为已经同步过的 DDL

1 个赞

我也碰到了。

大佬们上游的ddl只在两个分表执行了,现在这个DDL不执行了要回退去了,这样上游下游都回退回去,可行吗

大佬们上游的ddl只在两个分表执行了,现在这个DDL不执行了要回退去了,这样上游下游都回退回去,可行吗,会不会报错

AI 梳理:

社区帖子汇总报告:DM v8.5.1 分表 DDL 不一致(ErrCode 36008)

帖子:https://pingkai.cn/tidbcommunity/forum/t/topic/1055145
综合来源:@ticket-analysis 初步分析、@tidb源码解读 官方文档验证、@wiki_ticket 历史案例


问题概述

  • 环境:DM v8.5.1,64 张分表(order0~order63)合并同步到下游 posx_prd.t_order
  • 问题:使用 DBeaver 对 order0 和 order1 执行 MODIFY COLUMN mercode,DBeaver 自动追加了 CHARACTER SET UTF8MB4 COLLATE utf8mb4_0900_ai_ci,导致两条 DDL 不一致
  • 报错ErrCode 36008 — detect inconsistent DDL sequence
  • 当前状态:order0 的 DDL 已同步到下游(synced),order1 被 DM 拦截

根因

DM 对分表合并场景会做 DDL 一致性校验 — 所有分表的 DDL 语句必须完全相同。DBeaver 对同一列操作在不同连接上生成了不同的 charset/collate 子句,打破了这一约束。


解决方案(按推荐优先级)

方案一:binlog skip 跳过 DDL(推荐,操作最简单)

适用场景:不需要这个 MODIFY COLUMN 变更,直接跳过

tiup dmctl --master-addr 192.168.138.210:8261 binlog skip test1
# 分表场景可能需要多次执行,直到 query-status 不再报错
tiup dmctl --master-addr 192.168.138.210:8261 query-status test1

如果需要上下游回退该 DDL,继续执行方案一补充步骤。

方案二:Event Filter + binlog skip(推荐,适合需要回退 DDL 的场景)

适用场景:需要上下游同时回退 DDL,且不想反复报 36008

Step 1:在 DM 任务配置中添加 Event Filter

filters:
  skip-mercode-ddl:
    schema-pattern: "posx_prd"
    table-pattern: "t_order"
    events: ["alter table"]
    sql-pattern: [".*MODIFY\\s+COLUMN\\s+mercode.*", ".*CHANGE\\s+mercode.*"]
    action: Ignore

Step 2:重启任务使配置生效

tiup dmctl --master-addr 192.168.138.210:8261 stop-task test1
tiup dmctl --master-addr 192.168.138.210:8261 start-task test1-task.yaml

Step 3:binlog skip 清除已拦截的事件

tiup dmctl --master-addr 192.168.138.210:8261 binlog skip test1
# 可能需要多次,直到无报错

Step 4:下游 TiDB 回退

ALTER TABLE posx_prd.t_order MODIFY COLUMN mercode <原始类型>;

Step 5:上游 MySQL 回退(order0 和 order1)

ALTER TABLE order0 MODIFY COLUMN mercode <原始类型>;
ALTER TABLE order1 MODIFY COLUMN mercode <原始类型>;

Event Filter 会自动过滤回退 DDL 的 binlog 事件,避免再次触发 36008。

Step 6:验证 & 清理

# 确认 DM 正常
tiup dmctl --master-addr 192.168.138.210:8261 query-status test1

# 确认表结构
SHOW CREATE TABLE posx_prd.t_order;

回退完成后建议移除 Event Filter,避免影响后续正常 DDL 同步。

方案三:binlog replace 统一 DDL(适合需要保留 MODIFY COLUMN 功能)

适用场景:希望保留 mercode 字段修改,但需要统一 DDL 语句

tiup dmctl --master-addr 192.168.138.210:8261 \
  binlog replace test1 \
  "ALTER TABLE posx_prd.t_order MODIFY COLUMN mercode VARCHAR(80) NOT NULL DEFAULT '0' COMMENT '渠道商户号'"

分表场景需要对每个执行过不一致 DDL 的分表逐一 replace。

方案四:完全重置任务(兜底方案)

适用场景:多次 skip/replace 后状态混乱无法恢复

tiup dmctl --master-addr 192.168.138.210:8261 stop-task test1
# --remove-meta 清除旧 checkpoint,或使用新 task name
tiup dmctl --master-addr 192.168.138.210:8261 start-task --remove-meta test1-task.yaml

注意:DM 没有 reset-task 命令,正确方式是 stop-task + start-task --remove-meta


风险提示

风险 说明 缓解
TiDB collation 兼容性 涉及 utf8mb4_0900_ai_ci 时需 TiDB 开启 new_collation_enabled SHOW VARIABLES LIKE 'new_collation_enabled' 确认为 ON
多次 skip 分表场景可能需执行数十次 binlog skip 循环执行直到 query-status 无报错
上游 DDL 工具 DBeaver 等工具可能自动追加 charset/collate 使用命令行或脚本执行 DDL,确保语句完全一致
62 张未变更分表 回退 DDL 也会触发一致性检查 使用 Event Filter(方案二)自动过滤

这个回答比较科学