
gh-ost 的 approve-renames 并不用于审核列名变更,它只控制是否自动执行表重命名(RENAME TABLE)操作,与列定义(如列名、类型、默认值等)的变更完全无关。
approve-renames 的真实作用
该参数仅影响 gh-ost 最后一步:将影子表(_xxx_gho)重命名为目标表名,并将原表改名为 _xxx_del。启用后,gh-ost 不再等待人工确认,而是自动完成这组原子性重命名操作。
- 设为
true:重命名自动执行,适合已充分验证、可接受零停机风险的场景 - 设为
false(默认):重命名暂停,需手动调用gh-ost --execute或发送APPROVE命令才继续 - 无论是否启用,列结构变更(ADD/DROP/CHANGE COLUMN)都在迁移前就已固化在影子表 DDL 中,不会在重命名时动态调整
列名变更本身没有内置安全审核机制
gh-ost 不校验你传入的 DDL 是否合理——它只是忠实地把你的 --alter 语句应用到影子表上。例如:
-
--alter="CHANGE COLUMN old_name new_name VARCHAR(100)"会被直接执行,不检查old_name是否存在、new_name是否与现有列冲突 - 若列名拼错或类型不兼容(如从
INT改为ENUM且含非法值),错误会在影子表构建阶段暴露(如CREATE TABLE ... AS SELECT失败),而非重命名时 - 无语法/语义预检、无列依赖分析、无权限模拟验证
保障列变更安全的可行做法
必须依赖外部流程补足 gh-ost 的能力缺口:
- 在执行 gh-ost 前,用
pt-online-schema-change --dry-run或本地 MySQL 实例预跑 DDL,验证语法与基本兼容性 - 结合
information_schema.COLUMNS对比新旧表结构,确认列名、类型、NULL 属性、默认值等变更符合预期 - 对敏感变更(如重命名主键、删除非空列)增加人工审批环节,嵌入到部署流水线中(如 GitOps PR 检查 + DBA 确认)
- 利用 gh-ost 的
--test-on-replica和--postpone-cut-over-flag-file在从库充分验证后再切主,降低线上风险
为什么容易误解 approve-renames 与列安全相关
因为重命名是整个变更的“临门一脚”,而列名变更常出现在 --alter 中,两者在同一个命令里出现,容易让人误以为批准重命名 = 批准全部变更。实际上:
- 列结构已在迁移启动时锁定,重命名只是切换表引用
- 真正决定列是否变更的是
--alter内容,不是approve-renames - 出问题大概率发生在迁移中(数据复制异常)或迁移前(DDL 错误),而非重命名瞬间










