mysql 8.0的add column默认“秒级”完成,因其引入instant add column机制,仅修改元数据而不重建表或拷贝数据;但必须同时满足六项硬性条件(唯一操作、末尾追加、字面量/null默认值、dynamic/compressed行格式、无全文索引、innodb引擎),缺一即退化为inplace或copy。

ALTER TABLE ... ADD COLUMN 在 MySQL 8.0 中默认能“秒级”完成,不是因为引擎变快了,而是它**跳过了数据重写**——只要满足条件,就只改元数据,不碰一行数据。
但这个“秒级”非常娇气,稍不注意就退化成和 5.7 一样的全表拷贝。下面直说关键点。
哪些 ADD COLUMN 能走 Instant?必须全满足
MySQL 8.0.12+ 的 INSTANT 算法不是“尽力而为”,而是“全或无”。缺一条,就降级为 INPLACE(仍需遍历每行)或 COPY(重建整张表):
-
ADD COLUMN是语句中唯一操作(不能带DROP COLUMN、MODIFY COLUMN、RENAME COLUMN等) - 新增列必须追加在末尾(
AFTER xxx或不写,默认就是末尾),不能用FIRST - 默认值只能是
NULL或字面量(如DEFAULT 'abc'、DEFAULT 42),不能是表达式(DEFAULT NOW()、DEFAULT UUID()不行) - 表格式必须是
ROW_FORMAT=Dynamic或Compressed(Compact和Redundant不支持) - 表不能有
FULLTEXT索引(哪怕只是加一个TINYINT,有全文索引就强制COPY) - 引擎必须是
InnoDB(MyISAM、临时表完全不支持INSTANT)
为什么明明写了 ALGORITHM=INSTANT 还报错?
显式指定 ALGORITHM=INSTANT 时,MySQL 不会妥协——不满足条件就直接失败,而不是悄悄降级。常见报错:
-
ERROR 3106 (HY000): Invalid DDL statement. Cannot use INSTANT algorithm for this operation.:说明至少违反了一条上述条件 -
ERROR 3104 (HY000): Cannot use INSTANT algorithm for this operation because table has FULLTEXT index.:最常被忽略的坑,删掉全文索引再试 -
ERROR 3105 (HY000): Cannot use INSTANT algorithm for this operation because column is FIRST.:别用FIRST,改用AFTER last_col
验证是否真走了 INSTANT,执行完后看 SHOW CREATE TABLE tbl_name 输出里有没有 ALGORITHM=INSTANT —— 没出现,就是没走。
加字段后查不到新列的值?那是旧数据没填充
INSTANT 加的列对已有行是“逻辑存在、物理缺失”的状态。首次访问旧行的该列时,MySQL 才按默认值动态补上(比如返回 NULL 或 'abc')。这叫 lazy fill,不影响查询结果正确性,但:
- 如果后续要
UPDATE旧行并显式设该列为非默认值,没问题 - 但如果做
SELECT COUNT(*) WHERE new_col IS NOT NULL,可能比预期少——因为旧行还没真正写入该列值 - 想立刻物理写入所有旧数据?只能触发一次
ALTER TABLE ... MODIFY COLUMN ... DEFAULT ...(哪怕 default 值不变),MySQL 就会遍历并填充
用 pt-online-schema-change 或 gh-ost 就别指望 Instant 了
这些工具自己管理影子表,绕开了 MySQL 原生 DDL 流程,INSTANT 特性完全不生效。它们依然会拷贝全量数据,耗时和表大小正相关。如果你真需要秒级加列,就得直连 MySQL 执行原生命令,并确保环境满足全部条件。
最易被忽略的一点:不是“升级到 8.0 就自动秒级”,而是“满足 6 个硬性条件才秒级”。线上加字段前,务必先 SHOW CREATE TABLE 看格式、索引、行格式,再决定要不要先删全文索引或调整默认值写法。











