pt-online-schema-change能绕过mysql原生ddl锁瓶颈,因其不直接执行alter table,而是通过影子表+触发器机制实现在线变更:原表全程可读写,仅rename阶段毫秒级锁表;而原生ddl在prepare/commit阶段易因长事务持有mdl共享锁而阻塞数小时甚至一年。

pt-online-schema-change 为什么能绕过 MySQL 原生 DDL 的锁瓶颈
因为 pt-online-schema-change 不在原表上直接执行 ALTER TABLE,而是用“影子表 + 触发器”机制规避长时元数据锁。原表始终可读写,真正锁表只发生在最后 rename 阶段(毫秒级),而原生 ALTER TABLE 在 Prepare 和 Commit 阶段都可能因等待 MDL 锁卡住——尤其当有长事务持有共享锁时,lock_wait_timeout 默认是 31536000 秒(一年),新请求全排队阻塞。
哪些 ALTER 操作必须用 pt-osc,哪些可以直接走原生 Online DDL
不是所有变更都适合用 pt-online-schema-change。MySQL 8.0.12+ 对加列支持 ALGORITHM=INSTANT,此时直接 ALTER TABLE ... ADD COLUMN ... ALGORITHM=INSTANT 更快更轻量;但以下操作仍强烈依赖 pt-osc:
-
MODIFY COLUMN改类型(如VARCHAR(50) → VARCHAR(200)超出字节编码边界) -
DROP COLUMN(原生不支持 INSTANT 删除列) -
CHANGE COLUMN重命名+改类型 - 修改字符集或 collation(如
utf8mb4_0900_as_cs→utf8mb4_bin) - 大表上
ENGINE=InnoDB(即使已是 InnoDB,也用于OPTIMIZE TABLE场景)
执行前必须检查的 4 个硬性条件
pt-online-schema-change 启动时会做预检,任一失败即中止,不是靠报错后回滚:
- 目标表必须有主键或唯一非空索引(否则无法可靠同步增量数据)
- 表不能已有任何触发器(它自己要建 INSERT/UPDATE/DELETE 三个 AFTER 触发器)
- 不能存在外键约束引用该表(除非加
--alter-foreign-keys-method=auto) - 从库延迟不能超过
--max-lag(默认 1s),否则暂停拷贝(防主从断裂)
常见错误:Cannot create triggers on table `db`.`t`: ERROR 1419 (HY000): You do not have the SUPER privilege —— 这不是权限不够,而是 MySQL 5.7+ 默认 sql_mode 含 NO_AUTO_CREATE_USER 且 log_bin_trust_function_creators=OFF,需显式设为 ON。
关键参数怎么调才不翻车
默认参数在高并发生产环境大概率出问题,必须按负载调整:
-
--chunk-size:默认 1000 行,对亿级表建议调到 5000–10000,减少 chunk 扫描次数,但别超 5w,否则单次事务过大易超innodb_lock_wait_timeout -
--max-load:如H=10,U=20表示当从库复制线程延迟 >10s 或主库 Threads_running >20 时暂停,避免雪崩 -
--critical-load:如H=30,达到即终止,防止 DBA 被告警淹没后忽略 -
--set-vars:务必覆盖默认值,例如--set-vars="innodb_lock_wait_timeout=50,lock_wait_timeout=30",避免被其他事务拖死
最容易被忽略的一点:rename 阶段虽短,但若此时恰好有慢查询正在查该表元数据(比如 SELECT * FROM information_schema.TABLES),也可能被卡住几秒——这不是 pt-osc 的锅,但线上得盯住 SHOW PROCESSLIST 里状态为 Waiting for table metadata lock 的线程。











