线上大表ALTER TABLE极大概率锁表拖慢业务甚至雪崩,必须结合操作类型、存储引擎、MySQL版本及参数综合判断是否真正在线;大表变更应优先使用pt-online-schema-change或gh-ost等工具替代原生命令。

直接对线上大表执行 ALTER TABLE 极大概率会锁表、拖慢业务、甚至引发雪崩——这不是危言耸听,而是 MySQL 5.6 到 8.0 各版本都存在的真实风险。
判断当前操作是否真能“在线”执行
别信“MySQL 支持 Online DDL”这种笼统说法。真正决定是否阻塞的,是具体操作 + 存储引擎 + 版本 + 参数组合。例如:
-
ADD COLUMN在 MySQL 8.0+ 中若为NULL或带DEFAULT值,多数情况走INSTANT算法,仅改元数据,秒级完成;但 MySQL 5.7 就可能触发INPLACE并短暂加SHARED锁(允许读、阻塞写) -
MODIFY COLUMN phone VARCHAR(11)看似只是缩容,实际会全表扫描校验数据是否超长,强制ALGORITHM=COPY,锁表数小时 - 哪怕只是
RENAME COLUMN,在 MySQL 8.0.4 以下必须用CHANGE COLUMN,且要重写整列定义,一不留神就漏写NOT NULL或默认值,导致语法报错或约束丢失
实操建议:先加参数测试可行性,不加 FORCE 让 MySQL 自判:ALTER TABLE t1 ADD COLUMN c1 INT, ALGORITHM=INPLACE, LOCK=NONE;。若报错 ALGORITHM=INPLACE is not supported,说明必须重建表,立刻停手。
大表(>100 万行)必须绕过原生 ALTER
即便 MySQL 8.0 声称支持 INSTANT,一旦涉及数据迁移(如改类型、设 NOT NULL)、或磁盘 I/O 负载高,ALTER 仍可能卡住 performance_schema 的等待事件,拖垮从库复制。这时必须换方案:
- 优先选
pt-online-schema-change:它通过影子表 + 触发器同步,业务完全无感;但要求主库 binlog 格式为ROW,且需预留 ≥1.5 倍表空间(原表 + 新表 + _old 表) - 次选
gh-ost:无触发器,靠心跳和 binlog 解析做增量同步,更轻量,适合高并发写场景;但它不支持外键,且切换阶段依赖RENAME TABLE,需确保没有长事务持有原表元数据锁 - 禁用直接
ALTER的红线场景:修改主键、缩小VARCHAR、添加自增列、删除有索引/外键的字段——这些无论版本多新,一律触发全表拷贝
注意:pt-osc 默认会在切换前检查 Threads_running > 25,若业务高峰时运行,它会自动暂停,这点比硬上 ALTER 安全得多。
变更前必须验证的五个硬性条件
跳过任何一项,等于把生产环境当测试库用:
- 查表大小:
SELECT (DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024 AS size_mb FROM information_schema.TABLES WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t1';—— 若 >5GB,别信“试试看” - 确认无长事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60;—— 有结果就等它结束,否则 DDL 会被挂起 - 核对外键依赖:
SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t1' AND REFERENCED_TABLE_NAME IS NOT NULL; - 备份结构而非全量数据:
mysqldump --no-data --single-transaction db t1 > t1_struct.sql—— 比 dump 全表快十倍,回滚时可快速重建空表 - 检查从库延迟:
SHOW SLAVE STATUS\G看Seconds_Behind_Master—— 若 >60 秒,先治从库,再动主库
最易被忽略的一点:即使用了 pt-osc,它创建的触发器会增加主库 CPU 开销约 5%~15%,而这个开销在监控大盘里往往不显眼,直到某次慢查询堆积爆发才被发现。


















