本文档旨在帮助用户在使用阿里云数据管理DMS的无锁结构变更功能时,快速诊断和解决遇到的常见报错。通过本指南,您可以了解各类报错的根本原因,并获得清晰的处置建议。
核心解决思路总结
在深入具体问题前,请理解无锁变更的几个核心原则,这有助于您从根本上避免问题:
选择低峰期:无锁变更的本质是“在线数据复制与回放”,源表的高并发写入是导致延迟和失败的最主要原因。因此,尽可能在业务低峰期执行变更是最普适、最有效的解决方案。
排查长事务/大查询:变更的最后一步需要获取表的元数据锁进行切换。任何未提交的长事务或正在运行的大查询都会持有锁,导致变更超时失败。
使用原生DDL作为备选:当表结构(如无主键、有外键/触发器/分区)或DDL操作(如重命名、混合操作)不被无锁变更支持时,最直接的办法是临时关闭实例的“无锁结构变更”选项,采用原生DDL方式执行。
保持SQL简洁单一:避免在一个DDL语句中执行多种类型的操作(如同时添加UK和修改列),将其拆分为多个独立的DDL语句能显著提高成功率。
常见问题及解决方案
错误类型 | 原因分析 | 解决方案 |
因源表 TPS 大,DMS 增量回放延迟过高,表变更失败 |
|
|
无法获取原表上的 MDL 锁(已尝试 5 次) | 原表存在大事务、长查询、悬挂事务等,阻塞 DMS 获取元数据锁 |
|
| 原表在对一个数据区间进行拷贝的时候,会对拷贝的目标区间增加一个共享的读锁,如果刚好原表区间有一个未提交事务或者悬挂事务等,会导致读锁添加失败,进而任务中断。 |
|
未支持 - 不支持不包含 [主键/唯一索引] 的变更! | 表无主键(PK)或唯一索引(UK),DMS 无锁变更依赖 PK/UK | 关闭实例“无锁结构变更”选项,改用原生 DDL 执行 |
任务终止 - 直接执行 DDL 失败! | 原生 DDL 尝试 6 次仍未获取到锁,通常因大事务/长查询/悬挂事务 |
|
未支持 - 必须开启 PolarDB 的 Binlog 服务! | PolarDB 实例未开启 Binlog | 按文档开启Binlog功能 |
任务终止 - [数据校验失败] | 原因:DMS执行时,数据校验模块发现数据不一致,进而中断了任务。可能的原因:
| 改用原生 DDL 执行 |
任务终止 - 直接执行DDL失败! | 用户主动中断了原生 DDL 执行 | 重新发起任务(建议低峰期) |
未支持 - 不支持包含主表外键的变更!请暂时先关闭实例上的无锁结构变更选项,采用原生DDL执行。 | 表上存在外键或触发器 | 关闭“无锁结构变更”,改用原生 DDL |
未支持 - 不支持包含从表外键的变更!请暂时先关闭实例上的无锁结构变更选项,采用原生DDL执行。 | ||
未支持 - 不支持包含触发器的变更!请暂时先关闭实例上的无锁结构变更选项,采用原生DDL执行。 | ||
任务终止 - ALTER 后的目标表没有相同的主键信息! | DDL 删除了原表的主键或唯一索引 | 改用原生 DDL 执行 |
暂时不支持 Unique Key 与其他操作混合的 DDL | 由于增加UK一定不能采用DMS无锁变更执行,所以DMS会降级采用原生无锁执行。但DDL中增加UK和其他原生无锁无法执行的SQL混合在一起了,导致最终任何一种方式都无法无锁执行。 | 拆分为两条 DDL: |
| 索引字段长度超过 InnoDB 限制(767 字节) | 修改 DDL,使用前缀索引(如 |
| ||
| DDL 语句逻辑错误(如 NOT NULL 列设默认 NULL) | 修正 DDL 语法 |
| DMS 使用账号权限不足 | 授予 |
未支持 - 仅支持ROW格式日志,请开启Binlog的ROW模式后再重试。 | Binlog格式不对,未开启ROW模式,可能是MIXED模式。 | 开启ROW模式后,建议KILL老连接,或者重启/切换实例以达到KILL老连接的目的。因为写入binlog格式是会话级别的配置,全局切换到ROW模式,老连接仍然还是MIXED模式,binlog中还可能出现MIXED格式的日志,引起变更失败。 |
Binlog订阅链路中断(可能原因:回放延迟过高),请低峰期重试!底层报错:不支持, Binlog中识别到非ROW格式的DML SQL: <SQL片段> | 实例全局配置已经是ROW模式,但是仍然有MIXED格式的会话在往binlog中写入DML变更日志,不满足DMS无锁结构变更要求,进而引起任务中断。 | 避免MIXED格式的DML变更日志写入binlog中,DMS仅支持ROW格式的日志。 |
任务终止 - Alter后的UK包含可以为NULL的列,此类索引会导致脏数据产生!请暂时先关闭实例上的无锁结构变更选项,采用原生DDL执行。 | DMS 要求 UK/PK 字段非空,否则可能产生脏数据 | 改用原生 DDL 执行,或修改 UK 定义为 NOT NULL |
id 是自增列,但存在 | MySQL 允许 | 改用原生 DDL,或清理 |
未支持 - 不支持 ALTER TABLE 同时 RENAME 表 | DMS 不支持 rename 与其他变更混合 | 拆分 DDL:先 rename,再 alter(或反之) |
未支持 - 当前增量中存在无法执行的UK/PK变更!请暂时先关闭实例上的无锁结构变更选项,采用原生DDL执行。 | DMS无锁变更依赖的主键或者UK的值发生了更新,一般有几种情况:
| 改用原生 DDL 执行 |
DMS 不支持表分区变更 | 分区操作不在 DMS 无锁支持范围内 | 改用原生 DDL 执行 |
任务终止 - | 用户SQL问题 | 修正 SQL |
| ||
任务终止 - | ||
任务终止 - | ||
|