reload权限只能全局回收且必须用on *.*,不可作用于库或表;批量回收需逐用户执行并过滤root;已存在连接仍保留旧权限,新连接才生效;生产环境操作前须确认grant option权限、用户真实性及角色继承问题。

RELOAD权限只能在全局范围回收,必须用 ON *.*
RELOAD 是 MySQL 的管理类权限,属于全局权限(Global Privilege),不能作用于某个库或某张表。试图写 REVOKE RELOAD ON mydb.* FROM 'u1'@'%' 会直接报错 ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES。它只存在于 mysql.user 表中,对应字段是 Reload_priv,回收时必须显式指定 ON *.*。
常见错误写法包括:
-
REVOKE RELOAD FROM 'u1'@'%'—— 缺少ON *.*,语法不合法 -
REVOKE RELOAD ON test.* FROM 'u1'@'%'—— 范围非法,MySQL 拒绝执行
批量回收所有用户RELOAD权限的可行方案
MySQL 不支持 REVOKE ... FROM ALL USERS 这类通配语法,必须逐个用户执行。但可通过查询 mysql.user 表生成批量语句:
SELECT CONCAT('REVOKE RELOAD ON *.* FROM ''', User, '''@''', Host, ''';')
FROM mysql.user
WHERE Reload_priv = 'Y' AND User != 'root';
把结果复制执行即可。注意过滤掉 root 或其他运维账号,避免误操作。
更稳妥的做法是先导出当前拥有该权限的用户清单:
SELECT User, Host, Reload_priv FROM mysql.user WHERE Reload_priv = 'Y';
再人工核对,确认无关键账号后,再生成并执行 REVOKE 语句。
执行后权限是否立即生效?别信“Query OK”
REVOKE 命令本身会触发权限缓存更新,但实际生效依赖连接状态:
- 已存在的客户端连接仍持有旧权限,
RELOAD(如FLUSH LOGS)仍可执行,直到连接断开或超时 - 新连接才会按最新权限校验
- 若需强制所有连接立即失效,得配合
KILL对应线程,或重启服务(不推荐)
验证是否真正回收成功,不能只看命令返回 Query OK,而要用:
SHOW GRANTS FOR 'u1'@'%';
输出里不应再出现 RELOAD;同时查 mysql.user 表:
SELECT User, Host, Reload_priv FROM mysql.user WHERE User = 'u1';
确认 Reload_priv 字段值为 N。
生产环境批量回收前必须做的三件事
高危权限批量操作极易引发故障,以下检查缺一不可:
- 确认当前登录账户有
GRANT OPTION权限,否则REVOKE会报Access denied - 检查目标用户是否真实存在且未被误匹配:主机名含通配符(如
%、192.168.%)可能命中多个记录,REVOKE只处理明确匹配的一条 - 禁止在业务高峰执行
FLUSH PRIVILEGES—— 虽然REVOKE自动刷新,但若你额外补了一条FLUSH PRIVILEGES,它会锁住mysql系统库短暂时间,影响其他权限变更
最易被忽略的是:MySQL 8.0+ 默认启用角色机制,如果用户通过角色继承了 RELOAD,仅对用户执行 REVOKE 无效,必须查 role_edges 和对应角色的权限。











