MySQL 5.7+真支持LOCK=NONE的操作包括:ADD COLUMN(5.7.5+,无NOT NULL且无默认值)、增大VARCHAR长度(5.7.23+更稳定)、ADD/DROP INDEX(非FULLTEXT首次创建)、RENAME COLUMN(5.7.6+)和RENAME INDEX;但受外键、行格式、长事务等影响易自动降级为COPY并锁表。

能在线,但不是所有 ALTER TABLE 都真正在线——必须结合 ALGORITHM=INPLACE 和 LOCK=NONE 显式指定,并用执行过程验证是否生效。
哪些操作在 MySQL 5.7+ 真支持 LOCK=NONE?
别只看文档列表,得看实际执行时是否真的不阻塞写入。以下操作在满足前提条件下可做到 LOCK=NONE:
-
ADD COLUMN(5.7.5+),但字段不能带NOT NULL且无默认值,否则会降级为COPY并报错ERROR 1846 (HY000): ALGORITHM=INPLACE is not supported - 增大
VARCHAR长度(如VARCHAR(50) → VARCHAR(100)),5.7.23+ 更稳定;缩小长度必重建表 -
ADD INDEX/DROP INDEX(不含FULLTEXT首次创建) -
RENAME COLUMN(5.7.6+)、RENAME INDEX
注意:即使语法合法,若表含外键、使用 COMPACT 行格式、或列定义触发隐式转换,MySQL 仍可能悄悄回退到 ALGORITHM=COPY。
为什么写了 ALGORITHM=INPLACE 还被锁表?
两个最常见原因:自动降级 + 外部阻塞。
- MySQL 内部判断不满足原地修改条件(比如加
NOT NULL列但存在空值、改类型导致行溢出),会无视你写的ALGORITHM=INPLACE,直接切到COPY模式并加LOCK=EXCLUSIVE - 长事务未提交,持有
MDL锁:SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'your_table';可查;SELECT * FROM information_schema.innodb_trx WHERE TIME > 60;可定位超时事务
执行前务必清掉活跃长事务,否则 DDL 会卡在 waiting for meta data lock 状态,看起来像“假死”。
怎么确认 ALTER 真正在线执行了?
别信 Query OK,要看并发表现和系统视图反馈:
- 开两个会话:一个执行
ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE;另一个持续INSERT INTO your_table () VALUES ();,观察是否被阻塞或超时 - 查进度:
SELECT * FROM information_schema.innodb_alter_table;—— 若有记录且state是copy to tmp table,说明已退化;若无记录,大概率是纯元数据变更 - 监控
SHOW PROCESSLIST,状态出现altering table是正常,但若长时间停在Waiting for table metadata lock就要立刻排查
真正危险的不是慢,而是“看似在线、实则锁表”的伪在线操作——它会在业务高峰突然把所有写请求拖垮。


















