alter table是否锁表取决于操作类型、mysql版本及显式参数:8.0.12+的add column带not null default默认instant(毫秒级、不锁表),5.7/8.0中无default则触发全表重建锁表,5.6及更早必锁表;始终应显式指定algorithm与lock,并检查长事务。

直接执行 ALTER TABLE 很可能锁表、阻塞业务,尤其在大表或高并发场景下。是否安全,取决于你用什么方式改、改什么、在哪改——不是“能不能”,而是“怎么改才不翻车”。
ADD COLUMN 为什么有时不锁表,有时卡死?
MySQL 对新增字段的处理逻辑差异极大,关键看字段定义和版本:
- MySQL 8.0.12+ 中,
ADD COLUMN带NOT NULL DEFAULT且无依赖计算时,默认走INSTANT算法,只改元数据,毫秒级完成 - MySQL 5.7/8.0 中,
ADD COLUMN若未指定DEFAULT(即NOT NULL但无默认值),会触发全表扫描填充,必须重建表,锁表时间与数据量正相关 - MySQL 5.6 及更早版本,所有
ADD COLUMN都走COPY算法,必然锁表,无例外 - 即使支持
INPLACE,若表上有未提交事务或 MDL 锁冲突,也会卡在等待状态,表现为“看起来没反应”
实操建议:始终显式指定 ALGORITHM=INPLACE 或 ALGORITHM=INSTANT,并加 LOCK=NONE;执行前先查 SELECT COUNT(*) FROM information_schema.innodb_trx WHERE TIME > 60 确认无长事务。
DROP COLUMN 的不可逆性比你想的更彻底
DROP COLUMN 不仅删结构,还立即释放该列所有数据占用的空间,InnoDB 不保留任何回滚段记录——哪怕你在事务里执行,COMMIT 后也完全无法恢复。
- 不能靠
ROLLBACK撤销,也不能靠 binlog 回放还原(因为 DDL 不写行格式 binlog) - 即使使用
pt-online-schema-change工具,它也只是模拟“影子表迁移”,最终仍需执行一次真实DROP COLUMN - 多字段批量删除(如
DROP COLUMN a, DROP COLUMN b)比分开执行更安全——只触发一次表重构,减少中间状态风险
实操建议:生产环境执行前,必须用 mysqldump --no-data 备份表结构,并用 SELECT * FROM table_name LIMIT 10 抽样确认字段内容已无业务引用;删除后立即跑 DESC table_name 验证。
MODIFY 和 CHANGE 的行为差异常被忽略
MODIFY COLUMN 只改类型和约束,不改名;CHANGE COLUMN 必须同时指定旧名和新名,哪怕名字一样。两者底层处理完全不同:
-
MODIFY在扩大VARCHAR长度(如VARCHAR(50) → VARCHAR(200))时,MySQL 5.7+ 支持INPLACE;但缩小长度或转为TEXT就强制COPY -
CHANGE即使只是重命名一个VARCHAR字段,也会触发列重建(除非 MySQL 8.0.29+ 且类型未变),因为它涉及列定义重排 - 对
ENUM或SET类型修改,无论用哪个命令,都必须COPY,且新值列表必须包含所有旧值,否则报错Truncated incorrect ... value
实操建议:纯重命名优先用 CHANGE 并确保新旧名一致;类型变更优先用 MODIFY,并提前在测试库验证 EXPLAIN FORMAT=JSON 输出中 alter_algorithm 是否为 INPLACE。
线上大表改结构,别信“加个 LOCK=NONE 就万事大吉”
即使 MySQL 8.0 支持 INSTANT,也不代表所有操作都零影响。真正危险的是那些看似“轻量”但实际隐含重负载的操作:
-
ADD INDEX在大表上仍可能触发INPLACE,但会显著增加 I/O 和 CPU 使用率,导致从库延迟飙升 -
ALTER TABLE ... ENGINE=InnoDB强制重建表,无论数据量大小,都是全量复制 - 某些 ORM 框架(如 Laravel Migrations)默认不传
ALGORITHM,在低版本 MySQL 上自动退化为COPY,开发环境没问题,上线就崩 - 主从架构下,DDL 执行期间若发生主库切换,新主库可能因未完成 DDL 而拒绝写入,引发雪崩
实操建议:超过 100 万行的表,一律禁用直接 ALTER;改用 pt-online-schema-change 并设置 --max-lag=2 和 --critical-load="Threads_running=30";所有 DDL 必须在低峰期执行,且监控 information_schema.innodb_metrics 中 ddl%lock% 相关指标。
最常被跳过的环节不是语法,而是确认当前 MySQL 版本对应的 ALGORITHM 实际生效行为——查 information_schema.innodb_alter_table 或执行后立刻 SHOW PROCESSLIST 看状态,比任何文档都准。











