mysql还原后权限丢失主因是mysql系统库未导出导入,应显式用mysqldump --skip-lock-tables --routines --triggers --events mysql导出,并确保目标实例已初始化、跨版本需升级而非硬灌,补救时优先用pt-show-grants生成可重放sql并执行flush privileges。

MySQL还原后权限丢失,不是数据没导对,是 mysql 库压根没导——权限信息全存在 mysql.user、mysql.db 这些表里,只 dump 业务库等于把锁匠辞退后还指望门自己开。
mysqldump 默认不导 mysql 库,哪怕加了 --all-databases
很多人以为 mysqldump --all-databases 就万无一失,实际在某些 MySQL 配置(比如启用了 skip-show-database)或旧版本中,它会跳过 mysql 库。更稳的方式是显式指定:
mysqldump -u root -p --skip-lock-tables --routines --triggers --events mysql > mysql_system.sql- 必须加
--skip-lock-tables:否则 dumpmysql库时可能卡死(系统表不能被常规 LOCK) - 必须加
--routines和--triggers:因为存储过程/函数的DEFINER权限也存在mysql.proc等表中 - 必须加
--events:如果用了事件调度器,它的权限也在mysql.event表里
导入 mysql_system.sql 时容易错的三件事
导出对了,导入错一步,权限照样丢。
- 目标实例必须已初始化系统库:执行
ls /var/lib/mysql/mysql/,看到user.ibd或user.frm才说明mysql库存在;空目录但没初始化,直接mysql -u root -p mysql会报 “Unknown database” - 导入命令必须带库名:
mysql -u root -p mysql ,写成 <code>mysql -u root -p 会默认进 <code>test库,所有GRANT语句都执行失败 - 跨大版本(如 5.7 → 8.0)不能硬灌:8.0 的
mysql.user表结构、认证插件(caching_sha2_password)、密码字段长度全变了,强行导入会报错甚至损坏实例;必须走mysql_upgrade或官方升级流程
已经还原完了?用 pt-show-grants 补救最安全
如果旧库还在、新库已上线、又没法回滚,别去手动 INSERT 到 mysql.user——字段漏一个、host 写错、插件名不匹配,都会导致用户无法登录。
- 在旧库上运行:
pt-show-grants --user=root --password=xxx --host=old-host > grants.sql - 该工具生成的是带
CREATE USER和GRANT的完整语句,自动处理DEFINER、IDENTIFIED WITH等细节 - 导入前确认新库已创建对应用户(或让脚本含
CREATE USER),再执行:mysql -u root -p - 导入后务必执行:
FLUSH PRIVILEGES;——这点常被跳过,权限不会自动生效
最麻烦的不是导不出,是导出时没意识到 mysql 是个“活库”:它不只是权限容器,还存着触发器、事件、存储过程的归属关系。少一个 --routines,恢复后函数能调但执行时报错“no such grant”;少一个 --skip-lock-tables,dump 卡住你还以为网络断了。











