RENAME TABLE会卡住线上服务,因其持有元数据锁(MDL)全表级锁定,阻塞所有对原表名和新表名的DML/DDL及SELECT操作;锁等待时间取决于最长未提交事务,而非表大小。

不能直接用 RENAME TABLE 在高并发写入场景下操作,必须控制锁等待时间、验证依赖、并预留回退路径。
为什么 RENAME TABLE 会卡住线上服务
它会持有元数据锁(MDL),阻塞所有对原表名和新表名的 DML/DDL,哪怕只是 SELECT。锁释放前,所有相关查询排队——不是语句慢,是被强制挂起。
常见现象包括:
- 应用报错
Lock wait timeout exceeded或长时间无响应 -
SHOW PROCESSLIST里大量线程状态为Waiting for table metadata lock - 主从复制延迟突增(尤其当重命名在主库执行后,从库重放时也需等锁)
关键点:锁等待时间取决于当前最长未提交事务,而非表大小。一张 100GB 的表,RENAME TABLE 本身毫秒级完成,但若有个 5 分钟没提交的事务,你就得等满 5 分钟。
执行前必须检查的三件事
漏掉任意一项都可能引发故障:
-
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'your_db' AND OBJECT_NAME IN ('old_table', 'new_table');—— 确认没有残留 MDL 占用 -
SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 'old_table';—— 查外键依赖,避免重命名后约束失效 -
SELECT * FROM information_schema.VIEWS WHERE VIEW_DEFINITION LIKE '%old_table%';—— 找出所有引用该表的视图,后续要手动改VIEW_DEFINITION
特别注意:MySQL 8.0 默认 lower_case_table_names=0,Linux 下表名大小写敏感。如果开发环境设为 1,而生产是 0,RENAME TABLE user_info TO User_Info 可能查不到原表,报 ERROR 1146。
安全执行的实操步骤(含超时防护)
不追求“一步到位”,而是分阶段可控推进:
- 先在低峰期执行:
SET SESSION lock_wait_timeout = 3;(单位秒),再跑RENAME TABLE old_table TO new_table;。超时就失败,不硬扛 - 导入前加
SET FOREIGN_KEY_CHECKS=0;到 dump 文件开头(mysqldump默认已加),避免导入时外键校验拖慢速度 - 如果表有全文索引或空间索引,
RENAME TABLE会失败,需先DROP INDEX,重命名后再重建 - 操作后立刻验证:
SELECT COUNT(*) FROM new_table;和SELECT COUNT(*) FROM old_table;应都返回 0(后者应不存在);再查information_schema.TABLES确认新表存在且ENGINE、ROW_FORMAT一致
真正容易被忽略的是权限映射:重命名不影响 mysql.tables_priv 或 mysql.columns_priv 中基于旧表名的细粒度权限。如果业务用了列级权限,必须手动更新这些系统表。


















