主库执行Online DDL时从库会出问题,因其binlog记录方式导致从库被迫重建表、锁表或MDL阻塞;pt-osc需加--recursion-method=none、--check-slave-lag和--slave-user三参数保障主从一致;GTID模式下须校验gtid_executed完全相等且禁用sql_log_bin=0。
主从环境下的在线架构变更,本质是让变更在主库生效的同时,不破坏从库同步链路、不引发数据不一致。这不是“能不能做”的问题,而是“怎么做才不出错”的问题——直接在主库跑 ALTER TABLE 很可能让从库卡住甚至中断复制。
MySQL 的 Online DDL 在主库上看似无锁,但它的 binlog 记录方式决定了从库能否安全重放:
ADD COLUMN)在 5.6+ 中支持 ALGORITHM=INPLACE,但 binlog 里仍以 ALTER TABLE ... ALGORITHM=COPY 形式写入(尤其当 server_id 不匹配或参数未显式指定时),导致从库被迫重建表、锁表、延迟飙升ALTER COLUMN ... SET DEFAULT)在 8.0.23+ 才真正无锁;旧版本即使主库不锁,从库 SQL 线程执行时仍会获取元数据锁(MDL),阻塞其他查询binlog_row_image=MINIMAL 时,某些 DDL 的 row event 可能缺失关键字段,触发从库 Last_SQL_Errno: 1785(事务依赖冲突)用 pt-online-schema-change 是更稳妥的选择,但它默认只操作主库,对从库毫无感知。不加约束就跑,极易导致主从结构不一致:
--recursion-method=none:禁用自动探测从库,避免工具误判拓扑后连错节点--check-slave-lag=h=slave_host,u=user,p=pass,P=3306:显式指定一个从库并持续监控 Seconds_Behind_Master,一旦延迟 >30 秒自动暂停复制,防止追不上--slave-user 和 --slave-password:确保工具能在从库上执行 SELECT COUNT(*) 校验,否则校验跳过,一致性无保障漏掉任意一个,都可能出现“主库改完了,从库还在同步老结构”的静默故障。
开启 GTID 后,DDL 的原子性和可追溯性提升,但代价是校验逻辑更严格:
pt-online-schema-change 前,先在主库运行 SELECT @@global.gtid_executed;,记录当前 GTID 集合;变更完成后,在从库查 SELECT @@global.gtid_executed;,确认两者完全一致(不是“包含”,而是“相等”)SET GLOBAL sql_log_bin = 0 —— GTID 要求所有变更必须记 binlog,绕过日志会导致从库无法识别事务边界,后续 WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 失效很多团队只关注表结构,却忘了索引在主从间并非“自动镜像”。尤其是以下情况:
ALGORITHM=INPLACE, LOCK=NONE 添加了二级索引,但从库因磁盘 I/O 压力大,SQL 线程重放该 DDL 时降级为 COPY,耗时数分钟,期间 SHOW PROCESSLIST 显示 altering table,但应用无感知innodb_adaptive_hash_index=OFF,而主库为 ON,导致同样 DDL 在从库执行更慢,延迟累积SHOW INDEX FROM tbl_name,发现新索引存在,但 Cardinality 为 0——说明统计信息未更新,需手动 ANALYZE TABLE,否则查询计划可能退化真正完成一次在线架构变更,不是看到主库返回 success 就结束,而是确认从库的 Slave_SQL_Running_State 回到 Waiting for next chunk,且 Seconds_Behind_Master 稳定归零至少 60 秒。