pt-online-schema-change并非语法替代,而是绕开元数据锁的唯一可行方案;它通过影子表、触发器和分块拷贝将长锁拆为毫秒级短锁,全程原表可读写,避免Waiting for table metadata lock。
pt-online-schema-change 不是“替代 ALTER TABLE 的更好语法”,而是当原生 DDL 会锁死业务时,唯一能继续推进的路径。MySQL 对大表执行 ALTER TABLE 时,多数结构变更(如改字段类型、删列、加唯一索引、调整字符集)在 5.7 及更早版本中仍触发 ALGORITHM=COPY。10GB 表可能卡住几十分钟,期间所有写入排队等待 Waiting for table metadata lock,连 SELECT 在可重复读隔离级别下都可能被阻塞。即使 MySQL 8.0.12+ 支持 ALGORITHM=INSTANT,也仅限新增无默认值、非 NOT NULL 的列——其他操作照旧拷贝全表。pt-online-schema-change 的价值,是把“一次长锁”拆成“无数毫秒级短锁”,靠影子表 + 触发器 + 分块拷贝绕开元数据锁瓶颈,而不是靠 MySQL 自身的 Online DDL 能力。pt-online-schema-change 完全不走 MySQL 原生 DDL 流程:它新建空表 _t_new(秒级完成,只改元数据);
在原表上建 INSERT/UPDATE/DELETE 三类触发器,捕获所有增量变更;
按主键分块拷贝历史数据(每次只锁几行,不是整表);
最后用 RENAME TABLE 原子替换(微秒级,业务无感)。
整个过程 SHOW PROCESSLIST 里看不到长时间 Waiting for table metadata lock,原表始终可读可写。
以下操作在 MySQL 8.0 中仍需全表拷贝或无法安全执行:
MODIFY COLUMN 字段类型(如 VARCHAR(100) → VARCHAR(500),若涉及字节编码变化)DROP COLUMN)ADD UNIQUE INDEX)CONVERT TO CHARACTER SET utf8mb4)ALTER 会一直等它释放 MDL,哪怕只是个没 COMMIT 的 SELECT)pt-online-schema-change 默认参数只适合测试环境。线上大表必须预检并调参:
Cannot chunk table `db`.`t`: no primary key or unique not-null index)Triggers exist on the table)TRIGGER、REPLICATION SLAVE、PROCESS 权限(仅 SELECT/INSERT/UPDATE/DELETE 不够)--dry-run 先试:建影子表、验权限、试触发器,不拷数据也不改名--max-load="Threads_running=25"(超载暂停)、--critical-load="Threads_running=50"(超限退出)、--max-lag=1(从库延迟超 1 秒停同步)一是外键:若表被其他表引用,不加 --alter-foreign-keys-method=auto 或 rebuild_constraints,RENAME 阶段直接失败;
二是 --chunk-size 手动设死:它该由 --chunk-time=0.5 动态反推,硬设成 10000 容易导致单次锁行太久,拖慢主表写入;
真正关键的是控制每批耗时(--chunk-time),不是行数。