首页/数据/数据库速查/在线 DDL 与锁选项(ALGORITHM/LOCK)
性能与调优57 条

在线 DDL 与锁选项(ALGORITHM/LOCK)

8.0 在线 DDL 用 ALGORITHM=INPLACE/INSTANT 与 LOCK=NONE 声明要求:显式写出让「不锁表」成为可验证的承诺,执行前用 LOCK 子句探测是否可行。

数据库速查数据更新于 2026-10-13

在线 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 加列存在次数与行格式方面的限制,经过多轮变更之后需要重建表,才能继续享受秒级加列。

易错点

  • 省略 LOCK 子句:按默认策略可能锁表,自以为在线实则全表阻塞
  • 在存在长事务的实例上执行 DDL:收尾阶段等元数据锁,一等就是很久
  • 不看版本直接套用 INSTANT:老版本不支持,语句直接报错
  • 把在线 DDL 当成零影响:重建期间 IO 与 CPU 压力都会明显上升

数据来源与参考

  • MySQL 8.0 Reference Manual: Online DDL Operations

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌