最稳妥的导出方式是用 mysqldump 导出权限表,但需人工清洗密码字段;推荐使用 pt-show-grants 自动生成可执行的 create user 和 grant 语句,并注意目标环境的 sql_mode、密码插件及对象存在性。

如何导出 MySQL 用户权限的完整 SQL 语句
MySQL 本身不提供直接导出用户权限的命令,但可以通过查询 mysql.user、mysql.db、mysql.tables_priv 等系统表,拼出 CREATE USER 和 GRANT 语句。最稳妥的方式是用 mysqldump 配合 --no-data --skip-triggers 导出权限相关表结构和数据:
mysqldump -u root -p --no-data --skip-triggers mysql user db tables_priv columns_priv procs_priv proxies_priv
注意:导出结果中包含 INSERT 语句,不能直接执行恢复——因为密码哈希值(authentication_string 字段)是加密存储的,且不同 MySQL 版本字段名可能不同(如 5.7 用 Password,8.0+ 用 authentication_string)。实际迁移前需人工检查或脚本清洗。
MySQL 8.0+ 中 CREATE USER 和 GRANT 的行为差异
8.0 默认启用 caching_sha2_password 插件,且 GRANT 不再隐式创建用户(必须先 CREATE USER)。常见错误包括:
- 执行
GRANT SELECT ON db.* TO 'u'@'%'报错ERROR 1410 (42000): You have no SUPER privilege and you are not using a secure connection—— 实际是用户不存在,不是权限问题 - 用 5.7 备份的
INSERT INTO mysql.user直接导入 8.0 失败,因缺少plugin字段或account_locked字段缺失 -
SHOW GRANTS FOR 'u'@'%'输出的语句在目标实例执行时报错,可能是目标库缺少对应数据库或表,或角色(ROLE)未提前创建
建议统一用 SHOW CREATE USER 'u'@'%' + SHOW GRANTS FOR 'u'@'%' 组合生成可移植语句,并手动补全 IDENTIFIED WITH caching_sha2_password BY 'xxx'。
用 pt-show-grants 自动化导出权限(Percona Toolkit)
比手写 SQL 更可靠的选择是使用 pt-show-grants(来自 Percona Toolkit),它能智能适配版本差异,输出标准、可执行的 CREATE USER + GRANT 语句:
pt-show-grants --user=root --password=xxx --host=localhost > grants.sql
关键优势:
- 自动跳过匿名用户(
''@'localhost')等危险账户 - 对角色(
ROLE)支持完整,会先输出CREATE ROLE再GRANT - 可加
--revoke参数生成反向REVOKE语句,便于灰度回滚 - 不依赖
mysql.user表结构细节,兼容 5.6–8.0
注意:需确保运行用户有 SELECT 权限访问 mysql 库所有权限表,否则部分权限会漏导。
权限备份后恢复时最容易被忽略的三件事
权限恢复不是简单执行 SQL 就完事。以下三点常被跳过,导致权限“看似恢复成功”但实际不可用:
-
FLUSH PRIVILEGES在大多数情况下不需要——只要用CREATE USER/GRANT执行,权限立即生效;只有直接改mysql表才需要刷新 - 目标 MySQL 实例的
sql_mode若含NO_AUTO_CREATE_USER(5.7 默认关闭,但某些定制包可能开启),会导致GRANT创建用户失败 - 如果源库启用了
validate_password插件,而目标库没启用,恢复时遇到强密码策略报错,需临时关闭:SET GLOBAL validate_password.policy = LOW
真正麻烦的永远不是导出,而是确认每个 GRANT 里的数据库名、表名、列名在目标环境真实存在——缺失的库/表不会报错,只会让权限“静默失效”。










