mysql 8.0默认不启用algorithm=instant,仅当满足全部严苛条件(如innodb表、末尾/任意位加删列、字面量默认值、无全文索引等)时才生效;显式指定algorithm=instant可避免静默降级为inplace/copy,确保秒级执行并及时报错定位问题。

MySQL 8.0 的 ALTER TABLE 默认已倾向使用高效算法,所谓“建议使用 ALGORITHM 优化”其实是误读——真正要做的,是明确指定 ALGORITHM 和 LOCK,避免 MySQL 自动降级到低效路径。
ALGORITHM=INSTANT 不是默认启用的,但支持条件苛刻
添加或删除列时,MySQL 8.0.12+ 才支持 ALGORITHM=INSTANT,但它只在满足全部条件时才生效:
- 操作必须是
ADD COLUMN或DROP COLUMN(MODIFY COLUMN、CHANGE COLUMN均不支持) - 不能修改列的 NULL/NOT NULL 属性(比如从
INT NULL改成INT NOT NULL就强制退化为INPLACE) - 不能带
ALGORITHM=COPY或显式LOCK=SHARED等冲突子句 - 表引擎必须是 InnoDB,且未启用
innodb_file_per_table=OFF
一旦不满足任一条件,MySQL 会静默降级为 ALGORITHM=INPLACE,而你可能完全没意识到——这正是耗时从 0.8 秒跳到 14 秒的根本原因。
ALGORITHM=INPLACE 在 8.0 中行为更激进,容易爆磁盘
MySQL 8.0 的 ALGORITHM=INPLACE 重建索引时,会触发 B+ 树重组和填充因子重调(默认约 15/16),导致临时空间占用达原表 2–3 倍。这不是 bug,是设计使然:
- 老版本(如 5.7)的 “inplace” 更保守,页合并少、空间增长小
- 8.0 启用
innodb_defragment=ON后,ALTER TABLE ... ENGINE=InnoDB或OPTIMIZE TABLE实际等价于全索引重建 - 若表所在实例是
innodb_file_per_table=OFF,重建索引会写入系统表空间,无法释放空间——这是线上事故高发点
执行前务必确认空闲空间:SELECT table_schema, table_name, round(((data_length + index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.tables WHERE table_schema = 'mydb' ORDER BY size_mb DESC LIMIT 5;
大表加字段别硬扛,LOCK=NONE 不等于零影响
即使指定了 ALGORITHM=INPLACE, LOCK=NONE,对超大表(千万级以上)仍可能引发严重问题:
-
LOCK=NONE仅保证 DML 不被阻塞,但 DDL 过程中会持续持有 MDL 锁,阻塞后续 DDL(如另一个ALTER会被挂起) - I/O 和 CPU 消耗陡增,可能拖慢同实例其他查询,尤其当磁盘吞吐已达瓶颈时
- 主从复制延迟会同步放大:主库执行 5 分钟,从库可能积压 10 分钟以上
- 对亿级表,应优先考虑
gh-ost或pt-online-schema-change,它们通过影子表+binlog 回放实现真正无锁
真正安全的做法是:先查 SHOW CREATE TABLE 确认当前 ROW_FORMAT 和存储格式;再用 ANALYZE TABLE 刷新统计信息(升级后最常被忽略);最后按数据量分级选方案——100 万行以下直接 ALGORITHM=INSTANT,1000 万以上绕过原生 DDL。
复杂点在于:ALGORITHM 不是开关,而是权衡。它背后绑定的是锁粒度、空间策略、I/O 模式甚至 binlog 格式(ALGORITHM=COPY 要求 binlog_format=ROW)。不看执行计划、不查磁盘余量、不验主从延迟就敲下 ALTER,等于把数据库当玩具。











