MySQL不支持RENAME DATABASE语句,5.7报权限错误实为语法拒绝,8.0彻底移除;安全做法唯有mysqldump导出+CREATE DATABASE+导入,确保逻辑层重建、可审计、可重试。

MySQL 没有 RENAME DATABASE 语句(5.7 及以前会报错,8.0 直接移除)
直接执行 RENAME DATABASE old_db TO new_db 在绝大多数 MySQL 版本里都会失败,不是权限问题,是语法本身被禁用或废弃。官方这么做的原因是:重命名数据库涉及底层文件系统操作(如 .frm、.ibd 文件移动),容易因中断、权限、事务不一致导致库损坏。
- MySQL 5.7 执行该语句会返回错误:
ERROR 1044 (42000): Access denied for user ... to database 'old_db'(实际是伪错误,本质是命令被拒绝) - MySQL 8.0+ 彻底移除了该语法,报错:
ERROR 1064 (42000): You have an error in your SQL syntax - 别信网上“加
FLUSH TABLES再 rename”的旧方案——那是 MySQL 5.1 时代的临时 hack,现在不可靠且不安全
安全做法只有两个步骤:导出 + 创建 + 导入
这是唯一被 MySQL 官方文档认可、跨版本稳定、可审计、可中断重试的路径。核心是绕过文件系统层,走逻辑层重建。
- 用
mysqldump导出原库:mysqldump -u root -p --single-transaction --routines --triggers old_db > old_db.sql
(--single-transaction保证一致性,--routines和--triggers确保存储过程和触发器不丢) - 创建新库:
CREATE DATABASE new_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;(字符集务必和原库一致,查原库用SHOW CREATE DATABASE old_db;) - 导入到新库:
mysql -u root -p new_db - 验证后,再删旧库:
DROP DATABASE old_db;(这步不能省,也不能提前做)
大库(>1GB)要注意锁与超时
导出和导入过程本身不锁表(--single-transaction 依赖 InnoDB),但导入时如果含大量写操作(比如 INSERT 多、有外键约束、索引多),会显著拖慢速度,并可能触发 wait_timeout 或 max_allowed_packet 报错。
- 导入前在客户端加参数:
mysql -u root -p --max-allowed-packet=512M new_db - 导入时跳过外键检查提速:
SET FOREIGN_KEY_CHECKS=0;放在.sql文件开头(mysqldump默认已加) - 如果业务不能停写,导出后需比对
SHOW MASTER STATUS的 binlog 位点,用mysqlbinlog补增量(否则中间写入会丢失) - 别用 phpMyAdmin 或 Navicat 点击式导入大文件——它们常因内存/超时失败,坚持用命令行
权限与用户映射容易被忽略
库名变了,但 mysql.user 表里基于数据库名的权限(如 'user'@'host' ON `old_db`.*)不会自动迁移。不处理会导致应用连上新库却没权限。
- 查旧库权限:
SELECT User,Host,Db FROM mysql.db WHERE Db='old_db'; - 复制权限到新库:
INSERT INTO mysql.db SELECT User,Host,'new_db',Select_priv,Insert_priv,... FROM mysql.db WHERE Db='old_db';(字段要对齐) - 刷新权限:
FLUSH PRIVILEGES; - 更稳妥的做法是:导出权限单独用
mysqldump -u root -p --no-data --no-create-info --skip-triggers mysql db > db_privs.sql,然后手动替换库名再导入


















