pt-online-schema-change通过影子表、触发器和分块拷贝实现无锁DDL;主表持续可读写,每个chunk仅毫秒级锁表,但依赖主键或唯一索引,需严格配置--alter、--execute等关键参数。

为什么 pt-online-schema-change 能避开锁表
它不直接 ALTER TABLE,而是通过创建影子表(_tablename_new)、触发器和重放增量变更来实现。主表始终可读写,DDL 过程中所有 DML 都被触发器捕获并同步到新表。真正耗时的拷贝数据阶段是分 chunk 进行的,每个 chunk 只锁几毫秒,对业务几乎无感。
但要注意:触发器本身有开销,高并发写入下可能轻微拖慢主表性能;如果主表没主键或唯一索引,pt-online-schema-change 会直接报错退出,因为它依赖该索引分片扫描。
pt-online-schema-change 必须加的关键参数
漏掉这些,轻则失败,重则误删数据:
-
--alter:必须用双引号包裹,例如"ADD COLUMN c2 INT DEFAULT 0";里面不能出现;或换行 -
--execute:没有它只是预演,不会真正执行;预演阶段会检查外键、触发器、主键等,但不改结构 -
--chunk-size:默认 1000 行,大表建议调小(如500),避免单次锁太久;太小又增加网络和事务开销 -
--max-load:例如"Threads_running=25",超过就暂停拷贝,防止 DB 负载飙升 -
--critical-load:例如"Threads_running=50",达到即中止,避免雪崩
常见失败场景与对应解法
执行时报错 Cannot detect any unique index on table `db`.`t1`:说明表缺失主键或唯一非空索引。解决办法只有两个:ALTER TABLE t1 ADD PRIMARY KEY (id)(需评估业务影响),或改用 gh-ost(它支持无主键表,但逻辑不同)。
执行中卡住,日志显示 Waiting for the new table to catch up:通常是主从延迟大,或从库 IO 压力高。加 --check-slave-lag 和 --max-lag 参数可缓解,例如 --check-slave-lag h=slave-host --max-lag 5s。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
触发器残留:异常中断后,原表上可能残留 pt_osc_db_t1_del/ins/upd 触发器。务必手动清理:DROP TRIGGER IF EXISTS pt_osc_db_t1_del;(把 db 和 t1 替换成实际值)。
替换完成后的清理与验证要点
成功后,工具会自动 RENAME TABLE 并删除旧表,但以下三件事必须人工确认:
- 查
SHOW CREATE TABLE t1,核对字段、索引、字符集是否符合预期 - 运行
SELECT COUNT(*)对比新旧表行数(注意:触发器同步期间可能有极少量不一致,用pt-table-checksum更准) - 检查监控中的
Threads_created、Innodb_row_lock_time_avg是否回归正常——曾有案例因触发器未清干净,导致后续写入持续抖动
最易被忽略的是:如果原表有外键引用其他表,pt-online-schema-change 不会自动更新外键定义,你得在 --alter 中显式加上 ADD CONSTRAINT ... FOREIGN KEY,否则新表外键丢失。










