MySQL 8.0.23前,主库ALGORITHM=INPLACE的DDL在从库可能降级为COPY模式,因binlog记录不全导致整表重建、MDL锁阻塞;需检查Slave_SQL_Running_State、binlog_row_image=FULL及GTID一致性。

主库执行ALGORITHM=INPLACE,从库仍卡住altering table
这不是主库没在线,而是从库回放时被迫降级为COPY模式。MySQL 8.0.23之前改列默认值、utf8mb4下VARCHAR从255→500、加NOT NULL但字段含NULL值——这些操作在主库走INPLACE,binlog里却记成ALGORITHM=COPY,从库SQL线程一读就重建整表、加MDL锁、阻塞所有查询。
关键判断点:SHOW SLAVE STATUS\G中Slave_SQL_Running_State若长期停在altering table,且Seconds_Behind_Master跳变归零再飙升,基本就是这个原因。
- 检查
binlog_row_image是否为FULL(SELECT @@binlog_row_image),MINIMAL模式下某些DDL的row event缺失字段,从库可能报Last_SQL_Errno: 1785 - 确认主库执行DDL时显式指定
LOCK=NONE,否则MySQL默认用LOCK=SHARED,从库等MDL锁期间延迟会剧烈抖动 - GTID模式下,若DDL前后执行过
SET GLOBAL sql_log_bin = 0,从库gtid_executed会断层,后续同步直接中断
pt-online-schema-change漏掉关键参数导致主从结构不一致
pt-osc默认只连主库,对从库完全无感。漏掉任意一个关键参数,都可能出现“主库结构已更新、从库还在用旧表”的静默故障。
必须加的三个参数:
-
--recursion-method=none:禁用自动探测从库拓扑,避免工具误连二级从库而非直连主库 -
--check-slave-lag=h=10.0.1.2,u=repl,p=xxx,P=3306:显式指定一个从库并持续监控延迟,一旦Seconds_Behind_Master > 30秒自动暂停拷贝 -
--slave-user=repl --slave-password=xxx:确保能在从库执行SELECT COUNT(*)校验数据一致性;不加则跳过校验,你根本不知道主从是否真一致
示例命令:pt-online-schema-change D=test,t=user --alter "ADD COLUMN status 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)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
gh-ost不依赖触发器,但对binlog和索引有硬性要求
gh-ost靠监听binlog做增量同步,不创建触发器,规避了GTID模式下触发器兼容性问题,但也带来新约束。
- 主库必须开启
binlog_row_image=FULL(MySQL 5.6.22+),否则无法捕获完整变更字段 - 表必须有唯一可排序索引(主键或带
NOT NULL的唯一索引),gh-ost靠它分块读取,否则报错Cannot find a unique key - 不能在从库上执行——
gh-ost需要直连主库解析binlog,--host指向从库会失败 -
--alter参数里只写DDL内容,如"ADD COLUMN status TINYINT DEFAULT 0",不能带ALTER TABLE t1
典型命令:gh-ost --host=10.0.1.1 --user=root --password=xxx --database=test --table=user --alter="ADD COLUMN status TINYINT DEFAULT 0" --assume-rbr --allow-on-master --max-load="Threads_running=150" --critical-load="Threads_running=200" --chunk-size=1000 --execute
原生命令停SQL线程手动同步,最容易被忽略的验证点
用STOP SLAVE SQL_THREAD + 主库DDL + 从库手动执行,看似可控,但两个验证点90%的人会跳过:
- 变更前,在主库执行
SELECT @@global.gtid_executed,记下返回值(如aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1-100) - 变更完成后,在从库执行同一条语句,结果必须和主库**一字不差**;多一段或少一段GTID,说明有事务被跳过或重复执行
- 检查
SHOW SLAVE STATUS\G中Exec_Master_Log_Pos是否推进、Slave_SQL_Running_State是否为Slave has read all relay log,而不仅是Yes
GTID让DDL可追溯,但也让校验更严格——不是“包含”就行,必须完全相等。这点在MySQL 8.0.27+启用slave_ddl_exec_mode=IDEMPOTENT后更关键,从库会忽略重复DDL,掩盖上游本应失败的操作。

















