mysql 8.0秒级加列需严格满足五条件:innodb引擎、row_format非compressed、无fulltext索引、单ddl语句、无隐式主键(8.0.12–8.0.27),且algorithm=instant仅修改元数据,不触碰磁盘数据行。

它不是“自动变快”,而是只要条件全满足,ADD COLUMN 就真能毫秒完成、不锁表、不重建数据——但漏掉任意一个硬性限制,就会 fallback 到慢几小时的 INPLACE 或更糟的 COPY。
ALGORITHM=INSTANT 失败的五个常见原因
报错 ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported 时,别急着升级版本,先查这五点:
- 引擎不是
InnoDB:MyISAM、Memory、CSV 表一律不支持 - 行格式是
COMPRESSED或设置了KEY_BLOCK_SIZE > 0;DYNAMIC和COMPACT可以,但COMPRESSED不行 - 表上存在
FULLTEXT索引:哪怕只有一条,INSTANT就直接禁用 - 单条
ALTER TABLE里混了其他 DDL:比如ADD COLUMN+ADD INDEX,逗号分隔也不行 - MySQL 8.0.12–8.0.27 中,表没有显式主键且无
NOT NULL UNIQUE列(即隐式主键)
如何验证当前表是否真正支持 INSTANT
不能只看 MySQL 版本号,必须查运行时真实状态:
- 执行
SHOW CREATE TABLE t1,确认引擎为InnoDB,且无FULLTEXT索引 - 查真实行格式:
SELECT ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'database/t1'(注意库名小写+斜杠) - 检查是否压缩:
SELECT KEY_BLOCK_SIZE FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'database/t1',非 0 即不支持 - 临时表、系统表(如
mysql.*)、数据字典表空间里的表,全部不支持INSTANT
INSTANT 实际改了什么,又没改什么
它只动三处元数据,不动一行用户数据:
- 在
mysql.ibd和innodb_sys_columns等系统表中插入新列定义(类型、默认值、偏移位置) - 在表的 instant columns 元信息区生成一个“虚拟默认值描述符”,每张表最多存 64 次 instant 操作记录
- 后续
INSERT时,InnoDB 动态填充缺失列;SELECT时按需拼接老行与新列定义——物理存储里老数据依然没有这个字段
这意味着 DESCRIBE t1 立刻可见新列,但 SELECT * FROM t1 对旧行返回的是默认值,不是补全,是运行时合成。
指定 ALGORITHM=INSTANT 的实操建议
不推荐依赖“自动 fallback”,应显式控制行为:
- 加字段时强制加
, ALGORITHM=INSTANT:失败就立刻报错,避免静默降级到慢操作 - 不要和
LOCK=NONE同时用:ALGORITHM=INSTANT本身已隐含零锁,加LOCK参数会直接报错 - MySQL 8.0.29+ 支持
FIRST/AFTER定位加列,但前提是整条语句仍只做列变更,不混其他操作 - 云环境要注意主从参数一致性:
loose_innodb_instant_ddl_enabled必须两边都开启,否则主库成功、从库复制中断
最易被忽略的一点:INSTANT 只保证“加列快”,但后续如果对这张表执行 DROP COLUMN、MODIFY COLUMN 或任何重建类操作,instant 元信息区可能被清空或失效,下次加列未必还能走 instant 路径。











