应使用SHOW GRANTS FOR查用户当前生效权限,而非查询mysql.user表;回收高危权限必须用REVOKE并配合FLUSH PRIVILEGES,注意角色继承、连接复用及云平台延迟问题。

怎么查某个用户当前有哪些权限
直接用 SHOW GRANTS FOR 最准,它反映的是当前生效的权限集合,不是查 mysql.user 表里字段拼出来的“可能有”的权限。
常见错误是只查 SELECT host, user, Select_priv, Insert_priv FROM mysql.user,这种查法漏掉数据库级、表级、列级权限,而且字段值为 Y/N 不代表实际生效(比如全局权限被更细粒度的 REVOKE 覆盖后,字段仍可能是 Y)。
-
SHOW GRANTS FOR 'app_user'@'10.20.30.%';—— 查指定用户 -
SHOW GRANTS FOR CURRENT_USER();—— 查当前会话用户(含代理关系) - 没权限查别人?确保你有
SELECT权限在mysql库,或有SELECT+SHOW DATABASES才能执行SHOW GRANTS
回收高危权限必须用 REVOKE,不能只删 mysql.user 表字段
直接 UPDATE mysql.user 表里的 Super_priv 字段为 N 是无效的。MySQL 启动时把权限加载进内存,运行时只认 REVOKE 操作触发的权限变更。
典型高危权限包括:SUPER、SHUTDOWN、FILE、GRANT OPTION、CREATE USER、RELOAD。它们一旦被授予,就可能绕过常规审计和限制。
- 回收全局高危权限:
REVOKE SUPER, SHUTDOWN ON *.* FROM 'dba_backup'@'192.168.1.%'; - 回收数据库级权限:
REVOKE DROP ON `payment_db`.* FROM 'app_user'@'%'; - 回收后必须执行
FLUSH PRIVILEGES;—— 这步不是 always 必需,但安全起见建议加上,尤其跨版本或权限缓存异常时
REVOKE 不能撤销未显式授予的权限
比如用户只有 SELECT 权限,你执行 REVOKE INSERT ON test.* FROM 'u'@'%'; 不报错也不生效 —— MySQL 不认为这是“撤销”,只是忽略。
更麻烦的是:如果用户通过角色获得权限,REVOKE 单独对用户操作不会影响角色继承来的权限。必须先查清来源:
- 查角色分配:
SELECT * FROM mysql.role_edges WHERE TO_HOST = 'u' AND TO_USER = 'u'; - 查角色权限:
SHOW GRANTS FOR 'backup_role'@'%'; - 真正要收权,得
REVOKE角色本身,或从角色里回收对应权限
回收后权限没立刻失效?注意连接复用和缓存
已建立的连接不会实时感知权限变更,新权限/回收只对新建连接生效。但有些客户端(如某些 ORM、连接池)会复用旧连接,导致“明明 revoke 了还能操作”的假象。
- 确认是否生效:新开一个
mysql -u xxx -p连接再试命令 - 强制断开活跃会话:
KILL对应ID(查SHOW PROCESSLIST;),否则旧连接仍可用原权限操作几秒到几分钟 - 某些云厂商(如阿里云 RDS)权限同步有延迟,观察 30 秒后再验证
权限回收不是改完语句就结束的事。最常被跳过的环节是验证——尤其是跨角色、跨连接池、跨代理层的权限穿透,不亲手连一次、不跑一条 INSERT 或 DROP,很难确认真正收干净了。


















