mysql ≥ 5.7(innodb表)可用alter table rename index安全重命名索引,不锁表、不重建,但须显式指定algorithm=inplace和lock=none,并确保索引名存在且不冲突;≤5.6则需drop+add两步,存在无索引窗口与性能风险。

MySQL ≥ 5.7(InnoDB 表)可以直接用 ALTER TABLE ... RENAME INDEX 安全重命名索引,不锁表、不重建、不影响并发读写——但前提是显式声明参数且避开几个关键陷阱。
确认版本与引擎是否支持 Online DDL
不是所有 MySQL 版本都认 RENAME INDEX,也不是所有引擎都能免锁执行:
- 执行
SELECT VERSION();确认 ≥ 5.7;低于 5.6 的版本会直接报错ERROR 1064 (42000) - 运行
SHOW CREATE TABLE table_name;检查ENGINE=InnoDB;MyISAM 或 Memory 表不支持ALGORITHM=INPLACE,强行加参数会退化成阻塞操作 - 若表正在被 pt-online-schema-change 或 gh-ost 占用,也会因全局 MDL 锁导致 rename 卡住
必须显式指定 ALGORITHM 和 LOCK 参数
MySQL 不会自动兜底。即使语法正确,漏掉安全参数就可能降级为锁表操作:
- 正确写法:
ALTER TABLE `t1` RENAME INDEX `idx_old` TO `idx_new`, ALGORITHM=INPLACE, LOCK=NONE; - 不写
ALGORITHM=INPLACE:MySQL 可能尝试 COPY 算法,触发全量重建 - 不写
LOCK=NONE:默认行为可能升级为LOCK=SHARED,阻塞写入 - 反引号不能省:
`idx_old`和`idx_new`必须包裹,尤其当索引名含数字、下划线或关键字(如order)时
避开常见失败场景
即使满足版本和引擎条件,以下情况仍会导致 rename 失败或静默卡住:
-
ERROR 1022 (HY000):目标索引名idx_new已存在(哪怕类型不同,比如已有同名 FULLTEXT) -
ERROR 1091 (42000):原索引名idx_old不存在,或拼写错误(注意大小写敏感性取决于lower_case_table_names设置) - 卡在
Waiting for table metadata lock:说明有长事务(如未提交的SELECT ... FOR UPDATE)持有 MDL 锁,需查information_schema.INNODB_TRX并协调清理 - 主从复制异常:
binlog_format=STATEMENT+ 高延迟从库时,rename 可能中断复制;建议先切为ROW格式再操作
老版本(≤ 5.6)只能 DROP + ADD,但得控制风险窗口
无法避免重建,但可以最小化影响:
- 必须分两步,且不能合并进一条
ALTER TABLE(否则报错ERROR 1064) - 第一步:
ALTER TABLE `t1` DROP INDEX `idx_old`;—— 此刻索引消失,高频查询可能陡降 - 第二步:
ALTER TABLE `t1` ADD UNIQUE INDEX `idx_new` (`col1`, `col2`);—— 注意显式加UNIQUE,否则默认建普通索引 - 大表慎用:ADD 阶段 IO 高、耗时长,期间写入可能被阻塞;建议配合
pt-online-schema-change或选低峰期执行
真正容易被忽略的是:rename 操作本身不改数据,但它的元数据变更会立刻生效——应用层缓存、ORM 映射、慢日志分析脚本里硬编码的索引名,都可能因此失效。别只盯着 SQL 是否成功,得同步检查下游依赖。











