真正“零停机”的Online DDL操作包括:ADD COLUMN(末尾,MySQL 8.0.12+,ALGORITHM=INSTANT)、DROP INDEX、ADD INDEX(默认INPLACE,支持LOCK=NONE);而MODIFY/CHANGE COLUMN多触发COPY锁表,ADD PRIMARY KEY虽INPLACE但需排序并持SHARED锁。

MySQL 8.0+ 的 Online DDL 能做到真正“零停机”,但前提是选对操作类型、参数和时机;盲目加 ALGORITHM=INPLACE 不等于不锁表,反而可能因并发冲突导致语句直接失败。
哪些 ALTER TABLE 操作能真正在线执行?
不是所有 ALTER TABLE 都支持并发读写。关键看操作是否属于 Instant 或 In-Place 类型:
-
ADD COLUMN在末尾位置(MySQL 8.0.12+)→ALGORITHM=INSTANT,只改元数据,毫秒级完成,LOCK=DEFAULT即可,无需额外指定 -
DROP INDEX、ADD INDEX→ 默认走ALGORITHM=INPLACE,支持LOCK=NONE(允许 SELECT + DML),但建索引过程仍会占用 I/O 和 CPU,高负载时可能拖慢查询 -
MODIFY COLUMN或CHANGE COLUMN→ 大概率触发ALGORITHM=COPY,全程锁表,尤其在大表上极易超时或夯住复制延迟 -
ADD PRIMARY KEY→ 虽属INPLACE,但需全表排序,期间仍持SHARED锁(允许读,阻塞写),实际业务中常卡在写入高峰段
ALGORITHM 和 LOCK 参数怎么配才安全?
这两个参数不是“开了就稳”,而是相互制约的开关:
-
ALGORITHM=INSTANT只支持极少数操作(如末尾加列),且强制要求LOCK=DEFAULT;你写LOCK=NONE会报错ER_ALTER_OPERATION_NOT_SUPPORTED -
ALGORITHM=INPLACE时,LOCK=NONE是最宽松选项,但前提是表上没有长事务或未提交的 DML——否则ALTER会立即失败,而不是排队等待 -
LOCK=SHARED看似折中,实则容易被忽略:它允许SELECT,但会拒绝所有INSERT/UPDATE/DELETE,若应用层没做重试,可能直接报错Lock wait timeout exceeded - 别迷信
ALGORITHM=COPY降级——它本质是创建临时表再 rename,期间表不可写,且磁盘空间要翻倍,仅适合低峰期小表救急
为什么线上执行还是卡住了?常见陷阱有哪些?
即使语法完全正确,Online DDL 仍可能在生产环境突然变慢甚至阻塞,原因往往不在 SQL 本身:
- 主从复制延迟高时,
ALTER TABLE会在从库回放阶段卡住,表现为“主库已返回,但从库迟迟不同步”——这不是锁表,是复制线程被 DDL 元数据锁阻塞 - 表上有未提交的事务(哪怕只是个空
BEGIN),会导致LOCK=NONE模式直接失败,错误信息是ER_TABLE_NOT_LOCKED或更模糊的Lock wait timeout - 使用
pt-online-schema-change时,如果触发器未清理干净(比如中途 kill -9),残留触发器会让后续 DML 变慢,且错误日志里不显眼 - MySQL 8.0.33+ 对
ADD COLUMN的 Instant 支持有隐式限制:不能加NOT NULL且无DEFAULT值的列,否则自动 fallback 到INPLACE,而你可能根本没意识到
真正影响在线 DDL 效果的,从来不是那行 ALTER TABLE 本身,而是它执行前后的上下文:事务状态、复制链路、磁盘压力、甚至客户端连接池的超时配置。一个 ADD COLUMN 操作在测试库秒级完成,在线上却 hang 住两分钟,大概率不是语法问题,而是某条慢查询正持有 MDL 锁没释放。


















