instant加列仅在特定add column场景下生效,需同时满足innodb引擎、dynamic/compressed行格式、无fulltext索引、字面量默认值、单操作语句及末尾添加等六条件,缺一即退化为inplace或copy;显式指定algorithm=instant可避免静默降级,唯一验证方式是show create table输出含algorithm=instant字样。

INSTANT 加列不是“优化表”的通用手段,它只在特定 ALTER TABLE ... ADD COLUMN 场景下跳过数据重写——用错条件,反而引发锁表、I/O飙升、主从延迟。是否启用,取决于你这张表当前的结构和你要加的字段。
确认表是否满足 INSTANT 硬性条件
不逐条验证,就等于默认走 COPY 或 INPLACE。常见漏检项:
- 引擎必须是
InnoDB(MyISAM、临时表直接报错) - 行格式必须是
Dynamic或Compressed(注意:ROW_FORMAT=COMPRESSED不支持;查真实值用SELECT ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'db/tbl') - 表不能有任何
FULLTEXT索引(存在即强制COPY,哪怕只加一个TINYINT) - 默认值只能是字面量(如
DEFAULT 'ok'、DEFAULT 1)或显式DEFAULT NULL(DEFAULT NOW()、DEFAULT (id + 1)全部拒绝) - 语句只能含
ADD COLUMN单一操作(混DROP INDEX、MODIFY COLUMN、逗号分隔多列、ADD INDEX都会退化)
显式指定 ALGORITHM=INSTANT 而非依赖默认行为
MySQL 默认可能选 INPLACE,而你想要的是秒级响应。显式指定的好处是:失败即报错,不静默降级。
执行时务必写成:
ALTER TABLE t ADD COLUMN status TINYINT DEFAULT 0, ALGORITHM=INSTANT;
而不是:
ALTER TABLE t ADD COLUMN status TINYINT DEFAULT 0;
典型错误反馈:
-
ERROR 3104 (HY000): Cannot use INSTANT algorithm for this operation because table has FULLTEXT index.→ 先删全文索引 -
ERROR 3105 (HY000): ... column is FIRST.→ 改用AFTER last_col_name或不写位置(8.0.28 及以下版本不支持FIRST) -
ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported...→ 至少一条硬条件未满足,不是版本问题
验证是否真走了 INSTANT
别信耗时,也别信自己写了 ALGORITHM=INSTANT —— 唯一可靠方式是执行后立刻查:
SHOW CREATE TABLE t 输出中必须出现 ALGORITHM=INSTANT 字样。没出现,就是退化了。
补充验证:查 information_schema.INNODB_METRICS 表里的 dml_rows_inserted 计数器,如果加字段期间该值明显上涨,说明正在写新行,已退化为 INPLACE 或 COPY。
加完字段后,旧数据“看不见”新列值?这是设计,不是 bug
INSTANT 加的列对已有行是“逻辑存在、物理缺失”状态。首次读取旧行该列时,MySQL 才按默认值动态补上(比如返回 NULL 或 'abc'),这叫 lazy fill。
这意味着:
-
SELECT *返回默认值,结果正确,但不是真的写入磁盘 - 后续
UPDATE某行时,该行才真正补全新列(写入实际值) - 如果你依赖新列做
WHERE条件或建索引,没问题;但别误以为“所有旧行都已填充”,它们仍保持原始物理结构
INSTANT 只保住了“加列”这一步的毫秒级响应,它不加速建索引、不缓解主从延迟、不跳过崩溃恢复。一旦你把“业务快速上线”当成“系统恢复变快”,就混淆了 DDL 效率和故障恢复这两个完全不同的维度。











