select concat 拼接 grant/revoke 语句可纯 sql 批量生成授权脚本,兼容 mysql 5.6+,需注意用户主机匹配、权限大小写、partial revokes、角色绑定及版本差异。

用 SELECT CONCAT 拼接 GRANT/REVOKE 语句最直接
不用外部工具,纯 SQL 就能批量生成授权和回收脚本,核心是用 SELECT CONCAT 动态构造语句。它不依赖版本,MySQL 5.6 起全支持,适合快速生成一次性脚本。
常见错误现象:手写几十条 GRANT 容易漏引号、错 host、权限拼错;用 mysqldump 导出权限则根本不管用——它跳过 mysql 库或导出无效字段。
-
GRANT和REVOKE都不支持逗号分隔多个用户,必须逐条生成 - 主机名要严格匹配:
'user'@'localhost'和'user'@'127.0.0.1'是两个用户,不能混用 - 权限关键字如
SELECT、INSERT必须大写,否则部分客户端解析失败 - 若目标库启用了
PARTIAL REVOKES(查SELECT @@global.partial_revokes),REVOKE语句需加ON *.*显式指定范围,否则报错ERROR 3790
示例:给所有非系统用户授予 app_db 的只读权限
SELECT CONCAT('GRANT SELECT ON `app_db`.* TO ''', user, '''@''', host, ''';')
FROM mysql.user
WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', '')
AND account_locked = 'N';
回收同理,把 GRANT 换成 REVOKE SELECT ON `app_db`.* FROM 即可。
MySQL 8.0+ 必须处理角色和默认角色
在 8.0+ 环境下,只生成用户级 GRANT 很可能白干——真实权限常通过角色间接授予。不导出角色定义和绑定关系,还原后用户仍无权限。
容易踩的坑:
-
SHOW GRANTS FOR 'u'@'h'默认不展开角色权限,除非加USING role_name -
CREATE ROLE和GRANT ... TO role_name必须先于GRANT role_name TO 'u'@'h'执行,否则报错ERROR 1141 - 用户默认角色存在但未激活(
default_role = ''或为空字符串),SET DEFAULT ROLE语句必须显式导出
实操建议:
先查用户绑定的角色:
SELECT CONCAT('GRANT ', r.role, ' TO ''', u.user, '''@''', u.host, ''';')
FROM mysql.user u
JOIN mysql.role_edges r ON u.user = r.to_user AND u.host = r.to_host
WHERE u.account_locked = 'N';
再单独导出每个角色自身的权限(用 SHOW GRANTS FOR 'role_name'@'%')和 CREATE ROLE 语句。
导入前必须清理目标库的旧权限状态
直接执行生成的 GRANT 脚本大概率失败,不是语法问题,而是目标库已有残留权限或用户冲突。
关键点:
-
CREATE USER IF NOT EXISTS在 MySQL 8.0+ 才支持,5.7 及更早版本会报错,应统一用DROP USER IF EXISTS清场 -
REVOKE ALL PRIVILEGES ON *.* FROM 'u'@'h'不会清除角色绑定,得额外跑REVOKE role_name FROM 'u'@'h' - 密码字段名不同:
password(5.7) vsauthentication_string(8.0+),拼接SET PASSWORD时必须按目标版本选字段 - 账户锁定状态(
account_locked)、密码过期(password_expired)不会被GRANT影响,需单独用ALTER USER设置
推荐清理模板(适配 8.0+):
DROP USER IF EXISTS 'web_user'@'192.168.1.%'; CREATE USER 'web_user'@'192.168.1.%' IDENTIFIED WITH caching_sha2_password BY 'xxx'; GRANT SELECT, INSERT ON `app_db`.* TO 'web_user'@'192.168.1.%'; FLUSH PRIVILEGES;
用 pt-show-grants 处理跨版本兼容性最省心
当你要在 MySQL 5.6、5.7、8.0 混合环境中批量操作,手写 SQL 拼接很快会失控。此时 pt-show-grants 是唯一能稳定覆盖所有边界情况的工具。
它自动处理:
- 认证插件差异(
caching_sha2_password、mysql_native_password) - 动态权限(
BACKUP_ADMIN、CLONE_ADMIN)和 PROXY 权限 - 角色继承链、
WITH ADMIN OPTION、SSL/IDENTIFIED REQUIRE 子句 - 匿名用户(
''@'%')、空用户名、特殊 host(如 IPv6 地址)的引号转义
安装后直接运行:
pt-show-grants --host=localhost --user=root --password=xxx > grants.sql
生成的脚本开头带 FLUSH PRIVILEGES,结尾有注释说明适用版本,可直接 source 执行。注意:它默认跳过内置账户(如 mysql.session),如需包含,加 --all 参数。
真正麻烦的从来不是生成语句,而是搞清权限从哪来、到哪去、中间绕了几层角色、哪些状态没被覆盖。别省那几分钟查 mysql.role_edges 或 SELECT @@global.partial_revokes,漏掉一个,脚本就可能在凌晨三点把你叫醒。











