MySQL 5.7.23 起永久移除 RENAME DATABASE,因存在数据字典不一致、权限残留等风险;唯一安全替代方案是 mysqldump 导出 + 创建新库 + 导入,并需显式指定字符集、包含例程与触发器、禁用外键检查。

MySQL 为什么不能直接 RENAME DATABASE
MySQL 5.7 及更早版本曾短暂支持 RENAME DATABASE,但因存在数据字典不一致、权限残留、触发器/存储过程未自动更新等严重风险,官方在 5.7.23 中**永久移除了该语句**。执行会报错:ERROR 1064 (42000): You have an error in your SQL syntax 或直接提示 Unknown command。别再找兼容开关或隐藏参数——它真没了。
安全可靠的替代方案:导出 + 创建 + 导入
这是唯一被 MySQL 官方文档认可、生产环境通用的做法。核心逻辑是用 mysqldump 拉取原库结构与数据,再新建同名(目标名)数据库并导入。关键不是“快”,而是“不丢权限、不漏对象、不破依赖”。
实操要点:
- 先确认原库编码和排序规则:
SHOW CREATE DATABASE `old_db`;,新建库时显式指定,避免字符集隐式转换导致乱码 - 导出时加
--routines --triggers --events,否则存储过程、触发器、事件不会被包含 - 用
--skip-extended-insert可提升可读性(调试用),但会显著拖慢导入速度;生产环境建议去掉 - 导入前务必关闭外键检查:
SET FOREIGN_KEY_CHECKS=0;,否则可能因表顺序问题失败
示例命令流:
mysqldump -u root -p --routines --triggers --events old_db > old_db.sql mysql -u root -p -e "CREATE DATABASE new_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;" mysql -u root -p new_db < old_db.sql
权限迁移不能靠猜,必须手动同步
导出导入只处理数据库对象,mysql.user 表里的用户权限记录不会自动重映射。如果原库有专用账号(如 'appuser'@'%' ON old_db.*),新库默认无访问权,应用立刻报 Access denied for user。
正确做法是导出对应权限语句:
SELECT CONCAT("GRANT ", privilege, " ON new_db.* TO '", user, "'@'", host, "';")
FROM mysql.db
WHERE db = 'old_db';然后执行生成的 GRANT 语句,并补上 FLUSH PRIVILEGES;。注意:若用户使用了列级权限或动态角色,需额外检查 mysql.columns_priv 和 mysql.role_edges。
应用连接配置和从库同步要一并更新
改名后最容易被忽略的两个点:一是应用代码或配置文件里硬编码的 database=old_db,二是主从架构下从库的 replicate-ignore-db 或 replicate-do-db 规则仍指向旧名,导致同步中断或跳过新库操作。
检查项清单:
- 搜索项目中所有
old_db字符串,包括配置文件、ORM 的database参数、SQL 模板 - 在从库执行
SHOW SLAVE STATUS\G,确认Replicate_Do_DB或过滤规则已更新 - 若使用 GTID,确保
gtid_purged未因 dump 过程意外变动(建议 dump 前执行RESET MASTER仅限测试环境)
真正麻烦的从来不是 rename 本身,而是那些散落在各处、没人记得改的引用点。


















