instant算法加字段毫秒级不锁表,但需同时满足六条件:单add column操作、末尾添加、字面量默认值、innodb引擎、dynamic/compressed行格式、无fulltext索引;任一不满足即退化。

因为对千万级以上的表执行 ALTER TABLE ... ADD COLUMN 时,它能把耗时从几分钟甚至几小时压到毫秒级,且全程不锁表、不写磁盘、不触发主从延迟——但前提是,你得让它真正走 INSTANT。
INSTANT 真正生效的六个硬性条件
MySQL 不会“尽力而为”,缺一即退化。常见误判点全在这里:
-
ADD COLUMN必须是语句中唯一操作:不能和DROP COLUMN、ADD INDEX、MODIFY COLUMN写在同一句里,哪怕用逗号分隔也不行 - 新增列必须追加在末尾:
FIRST被直接拒绝;AFTER last_col或不写(默认行为)才合规 - 默认值只能是字面量或
NULL:DEFAULT 'abc'、DEFAULT 42、DEFAULT NULL可以;DEFAULT NOW()、DEFAULT (id + 1)、DEFAULT UUID()全部不支持 - 表必须是
InnoDB引擎:MyISAM、Memory、临时表、数据字典表(如mysql.ibd中的系统表)一律不支持 - 行格式必须是
Dynamic或Compressed:ROW_FORMAT=COMPACT或REDUNDANT会静默降级;注意COMPRESSED(带KEY_BLOCK_SIZE)也不行 - 表不能有任何
FULLTEXT索引:哪怕只有一条ALTER TABLE t ADD FULLTEXT(c1)历史记录,也永久失效,必须先DROP INDEX
为什么显式写 ALGORITHM=INSTANT 反而报错?
这不是 bug,是 MySQL 的严格校验机制——它宁可失败,也不悄悄降级。典型报错及对应原因:
-
ERROR 3106 (HY000): Invalid DDL statement. Cannot use INSTANT algorithm for this operation.→ 至少违反一条上述条件,比如混用了其他 DDL 操作 -
ERROR 3104 (HY000): Cannot use INSTANT algorithm for this operation because table has FULLTEXT index.→ 最常被忽略的坑,查SHOW CREATE TABLE t就能确认 -
ERROR 3105 (HY000): Cannot use INSTANT algorithm for this operation because column is FIRST.→ 改成AFTER xxx或删掉FIRST -
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation.→ 引擎不是 InnoDB,或行格式是COMPACT,或表是压缩表
怎么确认新加的列真的走了 INSTANT?
别信执行时间,也别信自己写的 ALGORITHM=INSTANT ——唯一可靠方式是查元数据:
- 执行
SHOW CREATE TABLE t,输出中必须出现ALGORITHM=INSTANT字样才算成功;没出现,就是退化了 - 若输出里只有
ALGORITHM=INPLACE或压根没提ALGORITHM,说明已退化为 INPLACE(需遍历每行)或 COPY(全表重建) - 补充验证:查
information_schema.INNODB_METRICS中的dml_rows_inserted计数,加字段期间该值暴涨,说明正在写新行,INSTANT 已失效
INSTANT 的核心脆弱点在于:它依赖“物理行不变”这一前提,所以任何可能破坏该前提的设计(比如全文索引、压缩格式、表达式默认值)都会被立即拦截。真正落地时,最常栽在隐式主键(8.0.12–8.27)、FULLTEXT 索引残留、以及误以为 DEFAULT NOW() 是字面量这三处。











