mysql ≥ 5.7 支持 alter table ... rename index 在线重命名索引,仅修改数据字典、不锁表不重建;≤ 5.6 需 drop + add 两步,存在无索引窗口与性能风险。

MySQL 5.7 及以上版本可以直接用 ALTER TABLE ... RENAME INDEX 修改索引名,不锁表、不重建索引;5.6 及更早版本必须先 DROP INDEX 再 ADD INDEX,存在无索引窗口和性能风险。
MySQL ≥ 5.7:直接重命名,但必须显式指定引擎与锁策略
RENAME INDEX 在 InnoDB 表上是 Online DDL 的 no-rebuild 类型,只改数据字典,不动数据页。但它不会自动兜底——你得自己确保条件满足:
- 执行前先确认引擎:
SHOW CREATE TABLE table_name,确保ENGINE=InnoDB - 强制声明安全参数:
ALTER TABLE table_name RENAME INDEX old_idx TO new_idx, ALGORITHM=INPLACE, LOCK=NONE - 别省略反引号:
`old_idx`和`new_idx`,尤其当索引名含数字、下划线或 MySQL 关键字时 - 不能漏表名:
RENAME INDEX old_idx TO new_idx是非法语法,必须以ALTER TABLE ...开头
MySQL ≤ 5.6:删+建两步走,中间有风险窗口
老版本压根不识别 RENAME INDEX,强行执行会报错:ERROR 1064 (42000): You have an error in your SQL syntax。必须分两步,且不能合并进一条 ALTER TABLE(会报错):
- 先删:
ALTER TABLE table_name DROP INDEX old_idx - 再建:
ALTER TABLE table_name ADD UNIQUE INDEX new_idx (col1, col2)(注意显式加UNIQUE,否则默认建普通索引) - 大表慎操作:ADD 阶段会全量重建索引,IO 高、耗时长,期间写入可能被阻塞
- 无索引窗口真实存在:DROP 后到 ADD 完成前,该字段查询可能陡降,尤其高频 WHERE 或 JOIN 场景
常见错误现象与排查点
即使语法正确,RENAME INDEX 仍可能卡住或失败:
-
Waiting for table metadata lock:说明有长事务(比如未提交的SELECT ... FOR UPDATE)占着 MDL 锁,需查SELECT * FROM information_schema.INNODB_TRX -
ALGORITHM=INPLACE is not supported:可能是 MyISAM 表,或当前表正被慢查询持有MDL_SHARED_READ锁 - 主从复制异常:在
binlog_format=STATEMENT且从库延迟高时,rename 操作可能引发复制中断 - 索引名冲突:
new_idx若已存在(哪怕类型不同,如已有同名FULLTEXT),也会报错
批量改名别硬写 SQL,用 information_schema 自动生成
想统一规范整个库的索引命名?别手写几十条 ALTER TABLE ... RENAME INDEX。先查出目标索引,拼出语句:
SELECT CONCAT('ALTER TABLE `', table_name,'` RENAME INDEX `', index_name,'` TO `', table_name,'_idx_', column_name,'`;')
FROM information_schema.statistics
WHERE table_schema = 'your_db'
AND index_name != 'PRIMARY'
AND seq_in_index = 1;
结果可直接复制执行。注意:该查询只取每个索引的第一列(seq_in_index = 1),若索引是多列组合,需按实际业务逻辑调整拼接逻辑。
真正容易被忽略的是:RENAME INDEX 不改变索引定义本身,但如果你依赖索引名做监控告警、ORM 映射或迁移脚本,改名后这些外部系统必须同步更新——它只是元数据层面的一次轻量修改,但影响可能扩散到整个数据链路。











