MySQL 8.0秒级加列需严格满足六项硬性条件:InnoDB引擎、ROW_FORMAT非COMPRESSED、无FULLTEXT索引、单DDL语句、末尾追加、默认值为字面量或NULL;缺一则退化为INPLACE或COPY,导致锁表数分钟。

能秒加,但必须满足全部硬性条件——缺一即退化为 INPLACE 或 COPY,锁表几分钟不是夸张。
ALGORITHM=INSTANT 报错 ERROR 1845 怎么快速定位原因
这不是版本问题,而是 INSTANT 算法被明确拒绝。常见触发点有:
- 表引擎不是
InnoDB(MyISAM、Memory、临时表全不支持) -
ROW_FORMAT=COMPRESSED或KEY_BLOCK_SIZE > 0(哪怕只设了KEY_BLOCK_SIZE=1也不行) - 表上存在过
FULLTEXT索引(历史残留也作废,SHOW CREATE TABLE里能看到) - 语句混用了其他 DDL 操作,比如
ADD COLUMN和ADD INDEX写在同一句,逗号分隔也不行 - MySQL 8.0.12–8.0.27 版本中,表有隐式主键(建表时没写
PRIMARY KEY,且无NOT NULL UNIQUE列)
验证方式:先查引擎和行格式:SHOW CREATE TABLE t1;再确认真实行格式:SELECT ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'db_name/t1'(库名小写+斜杠)。
为什么显式写 ALGORITHM=INSTANT 反而更安全
MySQL 默认会“悄悄降级”——不满足 INSTANT 条件时,自动 fallback 到 INPLACE 或 COPY,你看到执行成功,实际已锁表数分钟。显式指定后,它宁可失败也不妥协:
- 报错信息更精准:
ERROR 3104直接告诉你“因为有 FULLTEXT 索引”,ERROR 3105明确说“不能用 FIRST” - 避免业务窗口期误操作:你立刻知道要删全文索引、改默认值、或拆成单独语句
- 强制你检查元数据:执行完必须看
SHOW CREATE TABLE输出里是否真出现ALGORITHM=INSTANT字样——没出现就是没走
加列位置控制:AFTER 和 FIRST 在不同小版本的行为差异
别信“8.0 就支持任意位置”,版本间行为割裂严重:
- 8.0.28 及以下:
AFTER col_name或FIRST会直接报错ERROR 3106,INSTANT 只允许末尾追加 - 8.0.29–8.0.33(含主流云 RDS 20230630+ 小版本):支持
AFTER和FIRST,但仅限空表,或表中所有行已包含 instant 元信息(即之前已用 INSTANT 加/删过列) - 无论哪个版本,
DEFAULT NOW()、DEFAULT UUID()、DEFAULT (id + 1)都不被接受,只认字面量或NULL
稳妥做法:对非空表,统一用 AFTER last_col_name 定位到末尾,避免版本兼容风险。
行版本数(TOTAL_ROW_VERSIONS)超限怎么办
每次 ADD COLUMN 或 DROP COLUMN 都消耗一个行版本,上限是 64(MySQL 9.1 才升到 255)。超限后 INSTANT 永久失效,必须重建表重置:
- 查当前用量:
SELECT TOTAL_ROW_VERSIONS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = 'db_name/t1' - 重建表命令:
ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=COPY(注意:这会锁表、拷贝数据,需业务低峰执行) - 重建后
TOTAL_ROW_VERSIONS归零,INSTANT 可重新启用
真正容易被忽略的是:这个限制是 per-table 的,且不随数据删除而减少——哪怕你删光所有行,版本计数仍保留。线上高频变更字段的表,得定期盯这个指标。











