从库执行DDL会导致全局MDL等待,因SQL线程需排他元数据锁,阻塞所有对该表的读写及DDL操作,必须定位并终止持有锁的源头事务,而非直接KILL ALTER线程。

不能靠“从库先改再切主”来规避锁表风险。这种操作在绝大多数情况下会引发主从 GTID 错乱、binlog 位置跳变、SQL 线程 crash,甚至导致从库重放失败后永久中断同步。
为什么从库执行 ALTER TABLE 仍会卡住主库?
MySQL 的 DDL 复制不是“只传结果”,而是“传语句 + 重放”。即使你在从库上手动执行 ALTER TABLE,只要没停 SQL_THREAD,该语句就会被写入从库的 binlog(如果 log_slave_updates=ON),再传回主库重放——形成闭环污染。
- 更常见的情况是:主库执行了
ALTER TABLE ... ALGORITHM=INPLACE,但 binlog 记录为COPY模式(比如改VARCHAR长度、加NOT NULL且含 NULL 值),从库 SQL 线程只能重建整表,全程加 MDL 锁,阻塞所有查询 -
binlog_row_image=MINIMAL开启时,某些 DDL 的 row event 缺失字段,从库报错Last_SQL_Errno: 1785 - GTID 模式下,若中途执行
SET GLOBAL sql_log_bin = 0,gtid_executed在主从间无法对齐,后续START SLAVE直接失败
pt-online-schema-change 必须显式控制从库行为
pt-online-schema-change 默认只连主库,对从库完全无感。漏掉关键参数,会导致“主库结构已更新,从库还在用旧表”的静默不一致。
- 必须加
--recursion-method=none:禁用自动探测拓扑,避免误连二级从库 - 必须指定监控目标从库:
--check-slave-lag=h=10.0.1.2,u=repl,p=xxx,P=3306,延迟超阈值(如 30 秒)自动暂停拷贝 - 必须提供从库账号:
--slave-user=repl --slave-password=xxx,否则跳过SELECT COUNT(*)校验,你根本不知道主从是否真一致
示例命令:pt-online-schema-change D=test,t=orders --alter "ADD COLUMN flag TINYINT DEFAULT 0" --recursion-method=none --check-slave-lag=h=10.0.1.2,u=repl,p=xxx --slave-user=repl --slave-password=xxx --execute
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
ALGORITHM=INPLACE + LOCK=NONE 不等于“零影响”
即使 MySQL 8.0+ 支持末尾加字段这类真正 INPLACE 操作,仍需满足三重前提,缺一不可:
- 主从版本完全一致(比如都是 8.0.33),且都开启
binlog_format=ROW - DDL 执行前,确认
Seconds_Behind_Master归零,并在执行中持续盯紧该值;延迟回升说明从库 SQL 线程开始积压 - 执行后必须校验 GTID:主库执行
SELECT @@global.gtid_executed,从库执行同一条语句,结果必须完全相等,不能只是“包含”
一旦涉及 MODIFY COLUMN、索引重建、列顺序调整或非末尾加字段,InnoDB 仍可能退化为 COPY 模式,从库照样卡死。
真正危险的不是“能不能改”,而是改的过程中没人盯着 SHOW PROCESSLIST 里有没有 Waiting for table metadata lock,以及从库 SHOW SLAVE STATUS 里 Seconds_Behind_Master 是否突然归零又飙升——这两个信号往往意味着复制已进入不可逆的故障链。

















