pt-online-schema-change常卡在“copy rows”阶段,本质是依赖触发器异步同步数据,写入压力大或网络延迟高时易滞后,需等所有变更追平才原子切换。

pt-online-schema-change 为什么常卡在“copy rows”阶段
本质是它用触发器监听原表写入,再异步同步到新表,一旦原表写入压力大或网络延迟高,copy rows 就会明显滞后,甚至堆积。这不是 bug,是设计使然——它必须等所有变更都追平才能原子切换。
- 常见错误现象:
Copying rows进度长期卡在 99.x%,SHOW PROCESSLIST看到大量INSERT ... SELECT和触发器相关线程 - 关键参数要调:
--chunk-size(默认 1000,高 QPS 下建议压到 100–500)、--max-load(比如Threads_running=25)防止拖垮主库 - 不兼容场景:原表有外键、全文索引、GIS 列;MySQL 8.0+ 的隐藏主键(
_rowid)可能导致触发器行为异常 - 性能影响:全量拷贝期间磁盘 IO 和从库延迟都会升高,尤其当
ALTER涉及TEXT或BLOB字段时,临时表膨胀快
gh-ost 的“无触发器”模式怎么真正避开锁表风险
它不依赖触发器,而是解析 binlog 实时捕获变更,把 DML 转成对影子表的等价操作。这意味着原表完全不受 ALTER 工具自身逻辑干扰,连 SELECT ... FOR UPDATE 都不会被它阻塞。
- 使用前提:MySQL 必须开启
binlog_format=ROW,且server_id唯一;否则gh-ost启动直接报错Cannot find binlog stream - 真正零停机的关键点:切换瞬间只做一次
RENAME TABLE,耗时在毫秒级;而pt-online-schema-change切换前还要等触发器清空 backlog - 容易踩的坑:如果应用层用了
autocommit=0+ 显式事务,且事务跨了 gh-ost 的 binlog 位置点,可能漏同步——这时得加--exact-rowcount强制校验行数 - 兼容性注意:不支持
ENUM/SET类型字段的MODIFY(会报unsupported column type),改列类型得先转成VARCHAR再处理
两个工具在主从延迟场景下的行为差异
主从延迟不是配置问题,而是它们对复制流的依赖方式根本不同。
-
pt-online-schema-change默认不关心从库,只监控主库负载;但如果你加了--check-slave-lag,它会定期查Seconds_Behind_Master,超阈值就暂停拷贝——这反而可能让延迟雪上加霜 -
gh-ost主动消费主库 binlog,不读从库状态;但如果从库延迟严重,它的throttle-control-replicas参数可以指定某台从库来判断是否限速,避免主库被拖慢 - 真实场景中,若从库延迟 > 30 秒,
pt很可能反复暂停/恢复,导致总耗时翻倍;而gh-ost仍能稳定推进,只是最终切换会等从库追上(可配--postpone-cut-over-flag-file手动干预)
什么时候必须选 pt-online-schema-change
不是 gh-ost 更先进就该淘汰 pt,有些边界情况它仍是唯一选择。
- MySQL 5.6 或更低版本:gh-ost 要求 5.7+,因为依赖
performance_schema.table_io_waits_summary_by_index_usage等元数据表 - 需要在线修改视图、存储过程或函数的依赖表结构时:
pt支持--alter-foreign-keys-method=auto自动重建外键约束,gh-ost 完全不处理外键 - DDL 涉及分区表变更(如
REORGANIZE PARTITION):gh-ost 不支持,pt可通过--no-swap-tables模式手动接管流程 - 审计强要求:
pt每一步都输出详细日志(包括 SQL 执行时间、chunk 耗时),适合金融类系统留痕;gh-ost 日志更偏向调试用途










