mysql 8.0 的 add column 卡住是因为不满足 instant 条件而退化为 copy 或 inplace,需满足末尾加列、非 text/blob/json/geometry 类型、无 default 表达式、innodb 引擎等限制。

MySQL 8.0 的 ADD COLUMN 为什么还会卡住?
不是所有 ADD COLUMN 都能“在线”——只有满足特定条件时,MySQL 8.0 才真正走 INSTANT 算法,否则仍会触发表拷贝或元数据锁等待。
常见卡住现象:ALTER TABLE t1 ADD COLUMN c1 INT 执行数分钟不返回,SHOW PROCESSLIST 显示状态为 Waiting for table metadata lock,同时业务查询开始堆积。
- 必须加在表末尾(不能用
AFTER xxx或FIRST) - 列类型不能是
TEXT、BLOB、JSON、GEOMETRY - 不能带
DEFAULT表达式(如DEFAULT (uuid())),常量默认值可以(DEFAULT 0) - 表引擎必须是
InnoDB,且innodb_file_format= Barracuda(5.7+ 默认满足)
怎么确认你的 ADD COLUMN 走的是 INSTANT?
执行完 DDL 后立刻查 INFORMATION_SCHEMA.INNODB_TABLES 或用 SHOW CREATE TABLE 观察是否出现 ALGORITHM=INSTANT 并非可靠依据——MySQL 不会在语句里显式写出它。
真正有效的验证方式是看执行耗时与磁盘 I/O:
- 对千万行表,INSTANT 操作通常在毫秒级完成;若耗时 >1s,基本已退化为
COPY或INPLACE - 执行前后对比
SHOW GLOBAL STATUS LIKE 'Innodb_data_writes',INSTANT 几乎不增加写次数 - 开启
performance_schema后查events_statements_history_long,看SQL_TEXT对应的TIMER_WAIT是否极小
ALGORITHM=INSTANT 不是万能开关
显式写 ALGORITHM=INSTANT 不会让不兼容的操作强行变快,反而会直接报错:
ERROR 3104 (HY000): Cannot use ALGORITHM=INSTANT for this operation. Try ALGORITHM=INPLACE.
这意味着你写的 DDL 本身不满足 INSTANT 条件,MySQL 拒绝降级执行,而非自动 fallback。
- 想强制尝试更轻量级方案,改用
ALGORITHM=INPLACE(但仍有锁表风险) -
ALGORITHM=COPY一定全表锁,且期间无法写入,线上慎用 - MySQL 8.0.29+ 支持
LOCK=NONE与ALGORITHM=INSTANT组合,但仅限 INSTANT 场景;其他算法下LOCK=NONE会被忽略
线上加列前必须做的三件事
别只盯着语法对不对,真实阻塞往往来自隐性依赖和并发冲突。
- 检查是否有长事务未提交:
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5,活跃超过 30 秒的事务大概率会阻塞 DDL 元数据锁获取 - 确认没人在对该表做
SELECT ... FOR UPDATE或INSERT ... SELECT类操作——这类语句会持有共享元数据锁,DDL 需要排他锁 - 在从库上先试跑:
SET SESSION SQL_LOG_BIN=0;+ DDL,避免主从延迟放大问题;但注意这会跳过 binlog,仅用于验证语法和性能
INSTANT 加列看似简单,但一旦遇到带触发器、外键、全文索引或分区表的场景,规则会立刻变复杂——这些边界情况不会报错,但会静默退化,得靠监控和经验提前识别。











