SHOW GRANTS FOR 'user'@'host' 是导出用户权限的原生方式,但需配合 mysql.user 表查询补全 CREATE USER 语句,且不可直接 mysqldump mysql.user 表跨版本同步,必须通过逻辑脚本按 host 白名单生成可执行语句。

如何用 SHOW GRANTS 导出用户权限(不带密码)
SHOW GRANTS 是唯一能直接获取用户当前生效权限语句的原生方式,但它默认不输出密码哈希,也不包含 CREATE USER 语句——这意味着只靠它导出的结果无法直接在目标服务器上重建用户。
实操建议:
- 对每个用户执行
SHOW GRANTS FOR 'user'@'host',注意必须显式指定@'host',否则可能命中错误的匹配项(比如'user'@'%'和'user'@'localhost'是两个独立账户) - 若需补全
CREATE USER,得手动查mysql.user表:SELECT User, Host, authentication_string FROM mysql.user WHERE User = 'xxx',但注意:MySQL 8.0+ 的密码字段是authentication_string,5.7 是password,字段名不兼容 - 避免用
SHOW GRANTS FOR CURRENT_USER()—— 它只返回当前会话用户的权限,不是目标用户
为什么不能直接 mysqldump mysql.user 同步权限
直接 dump mysql.user 表看似省事,但实际极危险:表结构、加密方式、插件字段(如 plugin、account_locked)在不同 MySQL 版本间差异极大;8.0 默认用 caching_sha2_password,5.7 是 mysql_native_password,强行导入会导致用户无法登录。
常见错误现象:
- 导入后用户能创建,但连接时报错
Plugin caching_sha2_password could not be loaded -
account_locked=1被同步过去,目标库用户被锁死 - 8.0 的
password_reuse_history等新字段在旧版本表中不存在,导致 INSERT 失败
结论:跨版本迁移时,mysql.user 表不可直传,必须走逻辑层还原。
手写脚本导出权限的最小安全模板(含 host 白名单过滤)
真正可控的方式是用 SQL 查询拼接出可执行的权限语句,并限制只导出可信 host。以下是在源库执行的查询(适配 MySQL 5.7+):
SELECT CONCAT('CREATE USER IF NOT EXISTS \'', User, '\'@\'', Host, '\' IDENTIFIED WITH ', plugin, ' AS \'', authentication_string, '\';') AS create_user
FROM mysql.user
WHERE User != 'root' AND Host IN ('192.168.1.%', 'localhost');
SELECT CONCAT('GRANT ', GROUP_CONCAT(privilege SEPARATOR ', '), ' ON ', db, '.', tbl, ' TO \'', User, '\'@\'', Host, '\';') AS grant_stmt
FROM (
SELECT u.User, u.Host, p.Table_schema AS db, p.Table_name AS tbl,
CASE WHEN p.Column_name IS NULL THEN p.Privilege_type ELSE CONCAT(p.Privilege_type, '((', p.Column_name, '))') END AS privilege
FROM mysql.user u
JOIN mysql.db p ON u.User = p.User AND u.Host = p.Host
WHERE u.User != 'root' AND u.Host IN ('192.168.1.%', 'localhost')
) t
GROUP BY User, Host, db, tbl;
关键点:
- 务必用
IN显式限定Host,防止意外导出'%'或公网 IP -
CREATE USER ... IDENTIFIED WITH ... AS ...是 5.7+ 兼容写法,保留认证插件信息 - 列级权限(如
UPDATE(col1))需单独处理columns_priv表,上面示例未覆盖,需额外查询
导入前必须验证的三件事
权限脚本不是扔进目标库就能跑的“黑盒”,漏掉任一环节都会导致权限异常或服务中断:
- 确认目标 MySQL 版本是否支持源库导出的认证插件:运行
SELECT plugin FROM mysql.user LIMIT 1查看是否已加载对应插件,没加载要先INSTALL PLUGIN - 检查目标库是否存在同名用户且
Host冲突:比如源库有'app'@'192.168.1.%',目标库已有'app'@'%',直接CREATE USER会报错 - 禁止在生产环境直接执行
FLUSH PRIVILEGES—— 新建/修改用户后,MySQL 会自动重载权限;手动执行反而可能干扰内部状态,尤其在主从架构下
最易被忽略的是 host 匹配顺序:MySQL 按 User@Host 字符串长度精确匹配,'user'@'192.168.1.100' 优先于 'user'@'192.168.1.%',而后者又优先于 'user'@'%'。导出脚本里写的 host 必须和应用实际连接时用的一致,否则权限看似生效,实际不生效。


















