DDL 对复制链路的影响是什么
DDL 在复制链路中始终以语句形式重放到从库,即使主库使用 ROW 格式:这意味着从库执行 DDL 时会申请独占的元数据锁(MDL),只要该表上还有未结束的长查询或长事务,applier 就被挡住,整个复制开始积压。在线 DDL(INPLACE、INSTANT)能减少 DDL 期间的阻塞时间,但收尾阶段仍要拿短暂的表锁。
基本信息
| 适用版本 | MySQL 5.7 / 8.0(8.0 支持原子 DDL 与 INSTANT 加列) |
|---|---|
| 重放方式 | DDL 以语句重放,从库同样执行一次 |
| 关键锁 | 元数据锁(MDL),DDL 需要独占,与长查询互斥 |
| 相关参数 | lock_wait_timeout、metadata_locks 视图 |
| 8.0 改进 | 原子 DDL 保证 DDL 整体成功或失败,减少主从不一致窗口 |
| 风险点 | 从库挂着小时级报表查询时执行 DDL |
典型使用场景
- 大表加字段前的窗口评估:确认从库没有长查询与备份任务
- 排查复制延迟:发现 applier 卡在 Waiting for table metadata lock
- gh-ost / pt-osc 改表:评估其收尾阶段的锁等待与复制影响
- 发布流程规范化:DDL 上线需通知从库使用方与报表任务
- 主从结构漂移排查:某次 DDL 被跳过或失败留下的隐患
执行前观察与准备
执行前观察与准备
-- 源端执行前检查:有无超长事务或查询
SHOW PROCESSLIST;
SELECT trx_id, trx_started, trx_rows_locked FROM information_schema.INNODB_TRX ORDER BY trx_started;
SHOW VARIABLES LIKE 'lock_wait_timeout';
-- 从库观察 applier 是否被 MDL 卡住
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'orders';
SELECT * FROM performance_schema.metadata_lock_info\G
-- 查看从库正在重放的语句
SHOW REPLICA STATUS\G -- 关注 Replica_SQL_Running_State降低影响的实践
降低影响的实践
# 1) 选择低峰窗口,并提前通知从库使用方暂停报表任务
# 2) 能 INSTANT 的加列操作优先用 INSTANT(仅 8.0 且满足条件)
ALTER TABLE orders ADD COLUMN remark VARCHAR(64) DEFAULT NULL, ALGORITHM=INSTANT;
# 3) 大表改表用 gh-ost / pt-osc,并评估其收尾阶段的锁
# 4) 限制从库查询时间,避免长查询把 DDL 锁成事故
SET SESSION max_execution_time = 30000; # 单位毫秒影响因素对照
| 因素 | 影响 | 缓解方式 |
|---|---|---|
| 从库长查询 | DDL 等待 MDL,applier 停住,relay 积压 | 限制查询时长、错峰执行 |
| 从库备份任务 | 备份期间的锁等待会阻塞 DDL | 备份与 DDL 不同窗口 |
| 级联从库 | 延迟逐级放大,链路整体变慢 | 逐级观察状态后逐级执行 |
| 在线 DDL 收尾 | 仍需短暂表锁 | 预留窗口,监控锁等待 |
| 跳过 DDL | 结构漂移,ROW 重放会错列 | 结构变更必须全链路同步 |
从库上执行重查询建议设置 max_execution_time 或用只读延迟从库承载:给报表类查询限定时间上限是防止「一条查询把 DDL 锁成事故」最直接的手段。
不要为了让复制「快速通过」而跳过 DDL 或临时关闭复制执行结构变更:跳过的结构差异会在后续 ROW 重放时引发错列或报错,属于典型的人为埋雷,修复成本远高于当时等一会儿。