gh-ost专用于单表在线ALTER TABLE结构变更,不支持库级或实例级迁移;其核心价值是在割接窗口内安全、可控地完成大表DDL操作,避免锁表中断业务。

gh-ost 不是用来做「数据库割接迁移」的,它只负责单表在线 ALTER TABLE —— 也就是结构变更,不是库级或实例级的数据迁移。如果你要迁移整个数据库(比如从旧集群切到新集群、跨云、升级版本等),gh-ost 帮不上忙,得用 mysqldump、mydumper、Percona XtraBackup 或 MySQL Clone Plugin 这类工具。
但现实中,很多所谓“割接迁移”项目里,真正卡点的是**大表结构变更**:比如上线新字段、改列类型、删冗余索引——这些操作在割接窗口期内必须完成,又不能锁表。这时候 gh-ost 才是关键辅助角色。
下面说清楚怎么让它真正帮上割接的忙。
确认 gh-ost 能否介入当前割接场景
先排除硬性不兼容项,避免启动就失败:
-
binlog_format必须为ROW,且binlog_row_image=FULL(MINIMAL或NOBLOB会导致数据不一致) - 目标表必须有主键或非空唯一键;含
NULL值的唯一键默认被拒绝,需加--allow-nullable-unique-key并人工确认无实际NULL - 不支持外键和触发器——如果表有外键,得先
DROP FOREIGN KEY(割接前评估好业务影响) - MySQL 版本 ≥ 5.7;RDS 用户注意:阿里云需加
--aliyun-rds,AWS RDS 默认支持但需开启log_bin和binlog_format=ROW
割接前必须做的三件事
别跳过校验,否则割接当天才发现问题就晚了:
- 在从库上跑一次
--test-on-replica:它会停复制、切换表两次(原表 ↔ ghost 表),让你直接比对数据一致性。这是唯一能提前暴露主从延迟、字符集隐式转换、JSON 字段截断等问题的方式 - 用
--dry-run检查权限和路径:它不写数据,只建临时表、连 binlog、查元数据。输出末尾若出现All migration prerequisites are met才算过关 - 手动执行一次
SELECT COUNT(*)+SELECT MIN(pk), MAX(pk),确认主键连续性。gh-ost 依赖主键范围分片复制,主键跳变(如自增 ID 被批量插入打散)会导致进度卡住或重复写入
割接窗口内执行的关键控制点
真正执行时,--execute 只是开始,重点在过程干预能力:
- 限流必须主动设:
--max-load="Threads_running=20"+--critical-load="Threads_running=100"。别依赖默认值,割接期监控大盘的Threads_running和Innodb_row_lock_time_avg,实时调低--throttle-control-replicas的阈值 - cut-over 阶段有秒级锁表(
RENAME TABLE),但可人工干预:发POST http://localhost:6060/throttle暂停迁移,等业务低峰再POST /unthrottle继续。这个 API 在割接倒计时最后 5 分钟特别有用 - 别让
gh-ost自己决定 cut-over 时间。加--cut-over-exponential-backoff防止重试风暴,并用--cut-over-lock-timeout-seconds=3缩短锁等待上限,避免阻塞应用请求
割接后最容易被忽略的收尾动作
很多人以为 rename 完就结束了,其实还有两个隐患点:
-
_xxx_ghc表(变更日志表)不会自动删,得手动DROP TABLE;它虽小,但长期残留会影响SHOW TABLES输出和某些备份脚本逻辑 - 如果用了
--initially-drop-old-table,旧表被删了,但_xxx_del表名可能还留着(失败回滚时生成)。割接后扫一遍SHOW TABLES LIKE '%_del',确认是否真需要保留 - 最重要:检查
gh-ost进程是否彻底退出。残留进程会持续拉取 binlog,占用网络和 CPU,且下次同表迁移时因临时表冲突直接报错
gh-ost 把最危险的大表 DDL 变成可控、可观、可中断的操作。它的价值不在“快”,而在“敢在割接窗口里动”。


















