mysql 5.7真正无锁的alter操作仅限:add column(null且带默认值)、add/drop index(非fulltext首次)、rename column(≥5.7.6);其余大表变更必须用pt-online-schema-change。

MySQL 5.7 原生 ALTER TABLE 对大表几乎必然触发全表拷贝或长时元数据锁,不能直接用于生产大表变更;真正安全的方案只有两个:能用 ALGORITHM=INPLACE, LOCK=NONE 的极少数操作(如加 NULL 列、增索引),其余一律走 pt-online-schema-change(pt-osc)。
哪些 ALTER 操作在 5.7 真正无锁?
别信“Online DDL”字面意思——5.7 中只有特定组合才实际不锁表。关键看执行后是否出现 Waiting for table metadata lock 或 Copying to tmp table:
-
ADD COLUMN带默认值且允许为NULL:可INPLACE, LOCK=NONE,例如ALTER TABLE t ADD COLUMN remark TEXT DEFAULT '' -
ADD COLUMN声明NOT NULL但没给默认值:强制降级为COPY,报错ERROR 1846 (HY000): ALGORITHM=INPLACE is not supported -
ADD INDEX/DROP INDEX:全部支持INPLACE,DML 并发无压力,但首次建FULLTEXT索引仍可能卡写 -
MODIFY COLUMN增大VARCHAR长度(如VARCHAR(50) → VARCHAR(100)):仅当字符集字节不变(≤255 或 ≥256)时才安全;改类型(INT → BIGINT)大概率重建 -
DROP COLUMN、CHANGE COLUMN、RENAME COLUMN(5.7.6+):前两者必重建;后者是元数据操作,可LOCK=NONE,但需确认小版本 ≥ 5.7.6
为什么 pt-online-schema-change 是 5.7 大表变更的事实标准?
因为 MySQL 5.7 的 INPLACE 支持太窄,而 pt-osc 绕过了引擎层限制,靠影子表 + 触发器 + 分块同步实现业务零感知。但它不是“免检”,漏掉任一前提就会失败或丢数据:
- 原表必须有主键或唯一非空索引,否则报错:
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不够) -
binlog_format必须为ROW,否则触发器无法捕获变更;若当前是MIXED或STATEMENT,需提前全局修改 - 若表被外键引用,必须加
--alter-foreign-keys-method=auto,否则RENAME阶段失败
执行 pt-osc 时最容易踩的五个坑
很多翻车不是命令写错,而是环境没控住、收尾没清干净:
- 磁盘空间不足:影子表 + 原表临时索引 + binlog 日志可能导致磁盘使用翻倍,执行前确保
tmpdir和数据目录剩余空间 ≥ 原表大小 × 1.5 - 从库延迟超标:
pt-osc默认等待从库追平才切换,若Seconds_Behind_Master > 1又没设--max-lag,会无限卡住 - 异常中断后残留触发器:如
pt_osc_db_t1_del、pt_osc_db_t1_ins,必须手动清理:DROP TRIGGER IF EXISTS pt_osc_db_t1_del(把db和t1替成实际值) -
--chunk-time=0.5比--chunk-size更可控:前者让工具动态调整每次拷贝行数以维持 0.3–0.5 秒耗时;后者固定行数,在负载波动时易打爆 IO - 替换完成后只查
COUNT(*)不可靠:触发器同步有毫秒级延迟,必须用pt-table-checksum校验数据一致性
生产执行前必须做的三件事
跳过任何一项,等于把风险直接交给线上:
- 先在从库或影子环境跑一次完整命令加
--dry-run,验证语法、权限、触发器创建是否成功,不拷数据也不启同步 - 执行前查
performance_schema.metadata_locks,确认无长事务阻塞:SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'your_table'; - 高峰期禁用:即使参数调得再稳,
pt-osc也会明显拉升 CPU、IO 和网络压力;建议安排在业务低谷,且全程盯SHOW PROCESSLIST和Threads_running
最麻烦的不是命令怎么写,而是判断该不该用 pt-osc —— 如果表没主键、有外键又不敢动从库、或者磁盘只剩 20%,那就得先解决这些前置问题,而不是硬上 --execute。











