在线 DDL 是什么
MySQL 8.0 的在线 DDL 通过 ALGORITHM 与 LOCK 两个子句声明要求:ALGORITHM=INSTANT 表示只改元数据、秒级完成;ALGORITHM=INPLACE 表示在线重建,允许并发 DML;LOCK=NONE 声明不锁表,条件不满足时语句直接失败,而不是悄悄锁表执行。把这些子句显式写出来,等于把「不锁表」变成一句可以验证的承诺。
基本信息
| ALGORITHM=INSTANT | 只修改元数据,8.0.12 起支持多数加列场景 |
|---|---|
| ALGORITHM=INPLACE | 在线重建表或索引,允许并发 DML |
| LOCK=NONE | 声明式要求,不满足则直接报错而不是锁表 |
| LOCK=SHARED / EXCLUSIVE | 显式允许更弱的并发能力 |
| 收尾阶段 | ALTER 结束前仍需短暂持有排他元数据锁 |
典型使用场景
- 大表加列时保证业务不中断
- 加索引时要求全程不锁表
- 执行前探测某个变更是否支持在线方式
- 评估升级到 8.0 之后哪些 DDL 能秒级完成
- 排查 DDL 执行期间业务出现卡顿的原因
安全写法
安全写法
-- 加列:8.0.12 起支持 INSTANT
ALTER TABLE appdb.orders ADD COLUMN memo VARCHAR(200), ALGORITHM=INSTANT;
-- 加索引:要求不锁表,做不到就直接失败
ALTER TABLE appdb.orders ADD INDEX idx_status (status), ALGORITHM=INPLACE, LOCK=NONE;
-- 探测式执行:先用严格条件跑一次,失败说明要换方案
ALTER TABLE appdb.orders MODIFY COLUMN status VARCHAR(32), ALGORITHM=INPLACE, LOCK=NONE;
-- 观察执行进度(8.0)
SELECT * FROM performance_schema.events_stages_current;取值与建议
| 取值 | 含义 | 使用建议 |
|---|---|---|
| INSTANT | 只改元数据,秒级完成 | 加列时优先尝试 |
| INPLACE | 在线重建表或索引 | 加索引的常规选择 |
| COPY | 需要重建整张表 | 并发能力最差,尽量避免 |
| LOCK=NONE | 允许并发读写 | 写出来才能真正验证承诺 |
| LOCK=SHARED | 允许并发读 | 写入会被阻塞,慎用 |
无论选择哪种算法,ALTER 的最后阶段仍需短暂持有排他元数据锁。一旦实例上存在长事务,这几秒也会被拖成长时间等待,所以依旧要避开业务高峰。
显式写 LOCK=NONE 的最大好处是失败即止:算法不支持时不锁表,等不了就直接报错,这比默默锁表执行要安全得多。
频繁增删列会把行格式推到上限:INSTANT 加列存在次数与行格式方面的限制,经过多轮变更之后需要重建表,才能继续享受秒级加列。