MySQL 8.0+ 的 ALTER TABLE 变快是因为 Instant DDL 在满足条件时跳过表重建,仅更新元数据,毫秒级完成;但仅支持特定操作且需版本 ≥ 8.0.12。

MySQL 8.0+ 的 ALTER TABLE 为什么突然变快了?
因为 Instant DDL 在多数加列、改注释、重命名列等操作中跳过了表重建。它不改数据字典外的物理结构,只在 INFORMATION_SCHEMA 和表元数据文件(.frm 或数据字典表)里记一笔,毫秒级完成。
但前提是:操作必须满足「instant」条件,且 MySQL 版本 ≥ 8.0.12(推荐 ≥ 8.0.29,修复了早期多个元数据锁竞争 bug)。
- 只支持
ADD COLUMN(末尾)、DROP COLUMN(非主键/索引列)、RENAME COLUMN、ALTER COLUMN ... SET DEFAULT、ALTER COLUMN ... DROP DEFAULT、CHANGE COLUMN ... COMMENT、MODIFY COLUMN ... COMMENT - 不能有全文索引、空间索引、生成列、CHECK 约束(8.0.16+ 支持部分 CHECK)、外键(含父表/子表上的外键)
-
ADD COLUMN必须加在最后位置;若加到中间或开头,强制转为 inplace 或 copy 模式 - 执行前可用
SHOW CREATE TABLE检查是否含禁用对象,避免误判
怎么确认某次 ALTER TABLE 是否走 Instant?
看 ALTER 语句返回后的 Query OK 行——如果末尾带 (0.00 sec) 且没有 “Records: X Duplicates: Y Warnings: Z”,大概率是 instant;但更可靠的是查 information_schema.INNODB_TABLES 或启用 innodb_print_ddl_logs=ON 查错误日志。
- 执行后立即查:
SELECT NAME, INSTANT_COLS FROM information_schema.INNODB_TABLES WHERE NAME LIKE 'db_name/table_name',非 NULL 值表示该表已有 instant 列变更历史 - 开启日志后,DDL 完成时会输出类似
[Note] InnoDB: Instant ADD COLUMN `c2`的记录 - 注意:即使单条语句是 instant,连续执行多条
ALTER仍可能被合并或降级——MySQL 不保证事务内所有 DDL 都 instant
ALGORITHM=INSTANT 是不是万能开关?
不是。显式指定 ALGORITHM=INSTANT 只起校验作用:不满足条件就直接报错 ER_ALTER_OPERATION_NOT_SUPPORTED,不会退化到其他模式。
- 常见报错:
ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE—— 说明操作本身不支持 instant,比如DROP PRIMARY KEY或ADD INDEX - 指定
ALGORITHM=DEFAULT(默认)才会按规则自动选 instant / inplace / copy;想强制保速,得先验证操作类型是否在白名单里 - 线上批量变更时,别依赖
ALGORITHM=INSTANT来兜底,它不解决锁表问题,只是让“不锁表”的操作真正不锁表
Instant DDL 的隐藏代价:元数据膨胀与查询兼容性
每次 instant 变更都会在数据字典里新增一行版本记录,长期高频加减列会导致 mysql.table_stats 和 mysql.index_stats 膨胀,影响 ANALYZE TABLE 性能;更关键的是,老客户端或 ORM(如某些 PyMySQL 0.9- 版本)读取 SHOW COLUMNS 时可能漏掉刚 instant 加入的列。
- 定期清理无用统计:用
ANALYZE TABLE+FLUSH TABLES组合缓解,但无法删除历史 instant 版本元数据 - 应用层务必用
DESCRIBE table_name或SELECT * FROM information_schema.COLUMNS校验列是否存在,别信缓存的字段列表 - 跨大版本升级(如 5.7 → 8.0)后首次 DDL,即使语法合法,也可能因字典格式不兼容触发隐式 rebuild——务必在低峰期试跑
Instant 不是银弹,它把“快”限定在非常具体的变更子集里;一旦操作越界,MySQL 会沉默地退回 inplace,而你可能根本没留意执行时间从 0.01 秒变成了 120 秒。










