rename index在innodb中确实不锁表,但需满足引擎为innodb且显式声明algorithm=inplace, lock=none;它仅修改数据字典,不重写数据页,全程允许并发dml。

RENAME INDEX 确实不锁表,但只限于 InnoDB + 显式声明
MySQL 8.0 中 RENAME INDEX 操作本身属于 Online DDL 的 no-rebuild 类型,它只修改数据字典(.frm 文件元信息),不触碰行数据、不重建索引结构、不重排记录。所以只要满足两个前提:存储引擎是 InnoDB,且未被其他长事务或显式锁阻塞,它就能全程保持 LOCK=NONE —— 即允许并发 INSERT/UPDATE/DELETE。
但注意:MySQL 不会自动为你加安全兜底。如果你没显式写 ALGORITHM=INPLACE, LOCK=NONE,而当前表正被某个慢查询持有 MDL_SHARED_READ 锁,或者你用的是 MyISAM(不支持 Online DDL),那命令会直接报错或退化成阻塞行为。
实操建议:
- 执行前先确认:
SHOW CREATE TABLE t1,确保ENGINE=InnoDB - 强制声明:
ALTER TABLE t1 RENAME INDEX idx_old TO idx_new, ALGORITHM=INPLACE, LOCK=NONE - 避免在主从延迟高、binlog_format=STATEMENT 的环境下执行(可能引发从库复制中断)
为什么 MODIFY COLUMN 或 CHANGE COLUMN 就不行?
RENAME INDEX 和 MODIFY COLUMN 的本质区别在于是否修改“行格式”。前者不动磁盘上的任何数据页;后者哪怕只是改个 COMMENT 或把 VARCHAR(255) 改成 VARCHAR(256),MySQL 都必须重写所有聚簇索引页(因为字段长度影响行头结构和页内偏移计算),这就触发了 rebuild 流程,强制走 COPY 算法或至少要求 LOCK=SHARED。
常见错误现象:
- 执行
ALTER TABLE t1 MODIFY COLUMN c1 VARCHAR(256) COMMENT 'new'时卡住,show processlist 显示Waiting for table metadata lock - 明明加了
LOCK=NONE,却报错:ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY - 表上有活跃的长事务(比如未提交的
SELECT ... FOR UPDATE),导致 rename 也被挂起
RENAME INDEX 在哪些场景下仍会失败?
即使语法正确、引擎合规,以下情况仍会导致 RENAME INDEX 失败或降级:
- 目标索引名已存在(会报
ERROR 1022 (HY000): Can't write; duplicate key in table) - 原索引名不存在(报
ERROR 1091 (42000): Can't DROP 'xxx'; check that column/key exists) - 表正在被
pt-online-schema-change或gh-ost操作中(它们会加全局 MDL 锁) - 使用了不可见索引(
INVISIBLE)但未在语句中显式指定,MySQL 8.0 默认忽略不可见索引的 rename 请求
性能影响极小:整个操作通常在毫秒级完成,IOPS 几乎无变化,也不生成大 binlog event(仅一条 DDL 日志)。
容易被忽略的关键点:rename 不等于 drop + add
有人习惯用 DROP INDEX + ADD INDEX 模拟重命名,这是危险操作:两步之间存在窗口期,索引实际消失,查询计划可能劣化甚至报错 Unknown column in 'where clause'(如果 optimizer 用了被删索引的 hint)。而 RENAME INDEX 是原子操作,字典变更一步到位。
另一个隐藏风险:如果该索引被外键引用(比如是 FOREIGN KEY ... REFERENCES 的 target),MySQL 8.0 允许 rename,但外键约束名不会同步更新 —— 你需要额外执行 ALTER TABLE ... DROP FOREIGN KEY ... 再重建,否则后续 SHOW CREATE TABLE 里看到的还是旧名。











