MySQL 8.0 中撤销角色必须显式指定角色名和用户全称(含 host),语法为 REVOKE 'role_name' FROM 'user'@'host';需先查 mysql.role_edges 确认绑定关系,撤销后用户仍保留 USAGE 权限,彻底锁死需额外执行 REVOKE USAGE ON .。

不能用 REVOKE ALL FROM,必须明确指定角色名和用户
REVOKE 'role_name' FROM 'user'@'host' 是唯一合法语法
MySQL 8.0 不支持 REVOKE ALL FROM 'app_reader' 或类似模糊写法。报错 ERROR 1064 (42000) 是必然结果。撤销动作永远作用于“用户与角色之间的绑定关系”,不是清空角色本身。
正确做法是显式写出角色名和目标用户全称(含 host):
REVOKE 'app_reader' FROM 'alice'@'localhost';REVOKE 'dev_role' FROM 'bob'@'%';
注意:角色名和用户名一样,必须带单引号;主机名不匹配会导致语句执行成功但实际无效果(比如角色是 'app_reader'@'localhost',而你对 'alice'@'%' 执行 REVOKE,不会报错,但也不起作用)。
先查清楚用户绑了哪些角色,再逐个撤销
盲目执行 REVOKE 容易漏掉或错撤。真实运维中第一步永远是摸底:
- 查用户绑定的角色:
SELECT FROM_USER FROM mysql.role_edges WHERE TO_USER = 'alice' AND TO_HOST = 'localhost'; - 结果返回的每一行
FROM_USER字段值,就是你要在REVOKE里填的角色名 - 如果没查到记录,说明该用户根本没被授过任何角色,
REVOKE没必要执行
别跳过这步——系统表 mysql.role_edges 是唯一权威来源,SHOW GRANTS FOR 'alice'@'localhost' 只显示授予语句,不反映当前是否生效(比如角色已被 DROP 但绑定记录残留,SHOW GRANTS 还会显示它)。
撤销后用户只剩 USAGE 权限,但 USAGE 不会自动消失
执行完所有 REVOKE 'role_name' FROM ... 后,用户仍能连上数据库,只是无法执行任何 DML/DQL 操作。这是因为 MySQL 默认保留 USAGE ON *.* 权限(仅允许连接)。
- 如果你要彻底“锁死”该用户,需额外执行:
REVOKE USAGE ON *.* FROM 'alice'@'localhost'; - 这条语句不能省略
ON *.*,否则语法错误 - 撤销
USAGE后,用户将无法登录,除非重新GRANT其他权限
很多人以为撤销角色就等于“归零”,其实只是回到 USAGE 状态——这个细节常被忽略,导致误判权限是否真正回收。
DROP ROLE 和 REVOKE 角色是两件事,别混用
REVOKE 'role_name' FROM 'user'@'host' 只解除绑定,不影响角色定义;DROP ROLE 'role_name' 是删掉角色本身。两者目的完全不同:
- 想让某个用户暂时/永久失去权限 → 用
REVOKE解绑 - 想让某个角色彻底失效(且确认没人还在用)→ 先对所有用户
REVOKE,再DROP ROLE - 如果跳过
REVOKE直接DROP ROLE,会报ERROR 3530 (HY000)
最危险的操作是手动 DELETE FROM mysql.role_edges ——MySQL 8.0 的权限缓存机制会不同步,导致用户权限状态异常,甚至服务拒绝响应。


















