revoke后权限未失效是因会话权限缓存未刷新,库级权限需use切换数据库才生效,全局权限仅对新连接生效,且撤销必须严格匹配原始grant范围。

REVOKE 后权限没失效,通常不是命令没执行成功
MySQL 的 REVOKE 命令本身是立即写入授权表并触发内部权限重载的,它不依赖 FLUSH PRIVILEGES。如果你发现权限“还在”,大概率是权限生效时机与会话状态不匹配,而不是撤销失败。
库级别权限(db_name.*)需执行 USE 才能感知变更
这是最容易被忽略的点:对 db_name.* 这类库级权限的修改,**不会在当前会话中自动生效**,必须显式切换数据库才能触发权限检查刷新。
- 比如你执行了
REVOKE SELECT ON test.* FROM 'u1'@'%',但当前会话仍处于test库内,SELECT仍可执行 - 退出当前库再
USE test,或新开一个连接,权限限制才会起作用 - 注意:这不是 bug,是 MySQL 官方明确规定的生效逻辑(见 5.7+ 和 8.0 文档)
全局权限(*.*)对已存在连接完全不生效
如果撤销的是 ALL PRIVILEGES ON *.* 或 SUPER、RELOAD 等全局权限,这些变更**只影响新建立的连接**。
- 已登录的会话保留原始权限,直到断开重连
-
FLUSH PRIVILEGES对此无效——它不重置活跃会话的权限缓存 - 验证方式:用同一账号新开一个终端连接,再测试对应操作(如
SHOW DATABASES)
权限粒度不匹配导致 REVOKE 实际未命中
常见错误是撤销时写的范围和当初 GRANT 不一致,MySQL 找不到对应记录,静默跳过。
- 报错
ERROR 1141 (42000): There is no such grant defined for user ...是明确提示;但某些旧版本可能不报错也不生效 - 检查原始授权语句:如果当初是
GRANT SELECT ON `mydb`.`t1` TO 'u1'@'%',就不能用REVOKE SELECT ON mydb.*撤销 - 大小写敏感:
SELECT≠select;反引号包裹的库名(如`my-db`)也必须完全一致
真正麻烦的从来不是“怎么撤”,而是“撤完谁还拿着旧权限在跑”。尤其是 Uproxy、连接池、长连接应用这类场景,会话生命周期远超权限变更时间点,必须主动驱逐或等连接自然重建。











