一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何导出MySQL用户及其GRANT授权语句

时间:2026-08-28 09:24:49 编辑:袖梨 来源:一聚教程网

必须用 SHOW GRANTS FOR 'user'@'host' 查权限,因 mysql.user 仅存全局权限字段和账户状态,数据库、表、列级权限分存于 mysql.db、mysql.tables_priv、mysql.columns_priv 等表,手动查易遗漏90%以上授权且字段随版本变化。

必须用 SHOW GRANTS FOR 'user'@'host',不能查 mysql.user 表——后者只存密码和账户状态,不存任何实际权限。

为什么直接 SELECT * FROM mysql.user 会丢权限

MySQL 的权限分层存储:mysql.user 只有全局权限字段(如 Select_priv),而数据库级权限在 mysql.db、表级在 mysql.tables_priv、列级在 mysql.columns_priv,角色权限还要查 mysql.role_edges。手动拼 SQL 极易漏掉 90% 以上真实授权,且字段含义随版本变化(比如 MySQL 5.7 用 Password 字段,8.0 改为 authentication_string)。

如何安全导出单个用户的完整 GRANT 语句

执行前确认你有 SELECT 权限访问系统表,否则 SHOW GRANTS 会报 Access denied

  1. 先查清用户确切的主机名:SELECT User, Host FROM mysql.user WHERE User = 'app_user';
  2. 再执行:SHOW GRANTS FOR 'app_user'@'10.20.%';(注意必须带 @'host',否则报错 ERROR 1141
  3. 导出时加 --skip-column-names 避免首行列名干扰:mysql -u root -p --skip-column-names -e "SHOW GRANTS FOR 'app_user'@'10.20.%'" > app_grants.sql
  4. 输出里若含 USAGE(空权限),建议 grep -v "USAGE" app_grants.sql 过滤掉,避免无效语句

批量导出所有非系统用户的 GRANT 语句

MySQL 不支持 SHOW GRANTS 批量执行,必须逐个生成命令再调用。Linux 下可用以下 shell 脚本:

mysql -Nse "SELECT CONCAT(''', user, ''@'', host, ''') FROM mysql.user WHERE user NOT IN ('mysql.infoschema','mysql.session','mysql.sys','root') AND account_locked = 'N'" | while read u; do echo "SHOW GRANTS FOR $u;"; done | mysql -N | sed 's/$/;/g' > all_grants.sql

关键点:

  1. -N 去掉字段名头,-s 禁用表格格式,确保输出纯文本
  2. 排除内置账号(mysql.*)和锁定账户,防止导出失败或污染脚本
  3. sed 's/$/;/g' 给每条 GRANT 补上分号,方便后续 source 执行
  4. MySQL 8.0+ 若用户有默认角色,SHOW GRANTS 会输出 SET DEFAULT ROLE,必须保留,否则还原后权限链断裂

导入前必须处理的三件事

直接 source all_grants.sql 几乎必然失败:

  1. 用户不存在:GRANT 要求目标用户已存在,需提前执行 CREATE USER 'u'@'h' IDENTIFIED BY 'pwd';(注意主机名严格匹配)
  2. 旧用户残留:若目标库已有同名用户,先 DROP USER IF EXISTS 'u'@'h';REVOKE ALL PRIVILEGES ON *.* FROM 'u'@'h'; 清空再授
  3. 权限不生效:GRANT 后必须显式执行 FLUSH PRIVILEGES;,尤其当用户是通过 INSERT mysql.user 创建的老方式时

最易被忽略的是主机名通配符匹配——'user'@'%''user'@'localhost' 是两个完全独立账号,漏掉任何一个,应用就可能连不上。

热门栏目