迁移后权限丢失是因为未导出mysql系统库;需显式用mysqldump导出mysql库并加--skip-lock-tables、--routines、--triggers、--events参数,注意5.7与8.0不兼容,须按版本升级流程处理。

迁移后权限全没了,不是数据没导对,是 mysql 系统库根本没导。 默认 mysqldump --databases 只导业务库,mysql.user、mysql.db 这些存权限的表压根不会出现,新实例上只剩 root@localhost 能连,其他用户全 401。
导出 mysql 系统库必须显式指定
不能依赖 --all-databases(它在某些版本或配置下仍可能跳过系统库),最稳的方式是单独 dump mysql 库:
- 加
--skip-lock-tables:避免锁死系统表导致 mysqldump 卡住 - 加
--routines和--triggers:存储过程、函数、触发器的 definer 权限也存在mysql.proc等表里 - 加
--events:如果用了事件调度器,它的权限也得导 - 命令示例:
mysqldump -u root -p --skip-lock-tables --routines --triggers --events mysql > mysql_system.sql
⚠️ 注意:MySQL 5.7 和 8.0 的 mysql 库结构不兼容,跨大版本直接导入会报错甚至损坏实例。8.0 必须用 mysql_upgrade 或官方升级流程,不能硬灌旧版 mysql SQL。
导入前确认目标实例已初始化系统库
刚初始化的 MySQL 实例(比如用 mysqld --initialize 启动过)才有干净的 mysql 系统库。如果目标实例是空目录但没初始化,直接 mysql -u root -p mysql 会失败——因为 <code>mysql 数据库不存在。
- 先检查:
ls /var/lib/mysql/mysql/(路径依安装方式而定),看到user.frm或user.ibd才说明已初始化 - 没初始化?别硬导。要么重新初始化,要么改用
pt-show-grants补救(见下一条) - 导入时用
mysql -u root -p mysql,不是mysql -u root -p(后者默认进test库,权限语句会执行失败)
已经跳过系统库?用 pt-show-grants 生成可重放的 GRANT 语句
如果迁移已完成,旧库还在,别碰 mysql 库文件或直接 INSERT 权限字段——容易漏字段、配错 host、搞混插件。用工具生成标准 SQL 最安全:
- 装 Percona Toolkit:
apt install percona-toolkit(Debian/Ubuntu)或yum install percona-toolkit(RHEL/CentOS) - 从旧库导出:
pt-show-grants --user=root --password=xxx --host=old-host > grants.sql - 该命令默认带
CREATE USER+GRANT,且自动处理host匹配和插件差异(比如 8.0 的caching_sha2_password) - 在新库执行:
mysql -u root -p ,不用手动 <code>FLUSH PRIVILEGES(GRANT语句本身就会刷新)
注意:pt-show-grants 不导角色(Roles),如果用了 MySQL 8.0+ 角色机制,得额外导出 mysql.role_edges 和 mysql.default_roles 表。
MySQL 8.0+ 存储过程调用失败,大概率是 definer 权限断链
迁移后存储过程能查到,但一调就报 ERROR 1449 (HY000): The user specified as a definer ('u'@'h') does not exist,说明 definer 用户在新库不存在,或权限不足。
- 方案一(推荐):迁移时让工具统一改 definer,比如 DRS 或 Data Transmission Service 里勾选“所有 definer 迁移到当前用户”,这样所有存储过程 definer 都变成
'user1'@'%',再给调用者授EXECUTE权即可 - 方案二:保留原 definer,则必须把原用户完整迁过去(包括
mysql.user记录、密码哈希、认证插件),否则即使创建同名用户,definer 校验也会失败 - Java 程序调用还常缺
SELECT ON mysql.proc权限,得单独补:GRANT SELECT ON mysql.proc TO 'app_user'@'%';
真正容易被忽略的是 host 匹配细节:'user'@'localhost' 和 'user'@'%' 是两个完全独立的账号,权限不共享;MySQL 8.0 默认禁用 localhost 的 socket 登录映射,必须显式创建 'user'@'localhost' 才能本地免密连。


















