唯一正确写法是revoke select on database.view_name from 'user'@'host',必须显式指定库名和视图名;模糊写法如database.*或view_name无效,且需前置验证权限存在、用户匹配,撤销后仅新连接生效。

REVOKE SELECT ON database.view_name FROM 'user'@'host' 是唯一正确写法
撤销视图查看权限不能套用数据库或表的模糊写法,必须显式写出「库名.视图名」。MySQL 把视图当作一类特殊对象处理,SELECT 权限需绑定到具体视图上,否则会报错 ERROR 1147 (42000): There is no such grant defined。
常见错误包括:
- 写成
REVOKE SELECT ON database.* FROM 'u'@'h'—— 这只会撤掉该库下所有表的 SELECT,对视图无效 - 写成
REVOKE SELECT ON view_name FROM 'u'@'h'—— 缺少库名,MySQL 找不到该视图对象 - 写成
REVOKE SELECT ON *.* FROM 'u'@'h'—— 全局撤销不覆盖视图级授权,原视图权限依然存在
正确示例:REVOKE SELECT ON finance.salary_view FROM 'reporter'@'192.168.10.%';
先查清权限是否真实存在,再执行 REVOKE
MySQL 的 REVOKE 不校验目标权限是否存在:即使用户根本没被授予过该视图的 SELECT,语句也会返回 Query OK,但实际什么都没发生。
务必前置验证:
- 确认视图存在:
SHOW FULL TABLES IN finance WHERE TABLE_TYPE LIKE 'VIEW'; - 确认用户存在且 host 匹配:
SELECT User, Host FROM mysql.user WHERE User = 'reporter'; - 查当前授权:
SHOW GRANTS FOR 'reporter'@'192.168.10.%';—— 输出中必须明确看到类似GRANT SELECT ON `finance`.`salary_view` TO 'reporter'@'192.168.10.%'才能放心撤
漏掉这步,容易误以为权限已回收,实则毫无效果。
撤销后新连接才生效,旧连接仍可查视图
权限变更对已建立的连接不立即生效。只要连接没断,用户仍能执行 SELECT * FROM finance.salary_view;,哪怕你刚跑完 REVOKE。
关键点:
-
FLUSH PRIVILEGES在 MySQL 8.0+ 中不是必须的(REVOKE 自动刷新),但它无害,加了更稳妥 - 真正起效靠的是「新连接」:应用重连、连接池重建、或用户手动退出重登
- 若需立刻阻断,可配合
KILL对应线程:SELECT ID FROM information_schema.PROCESSLIST WHERE USER = 'reporter';,再KILL [ID];
GRANT OPTION 和 USAGE 权限容易被忽略
视图权限常和 GRANT OPTION 混用——比如用户曾被授过 SELECT ON finance.salary_view WITH GRANT OPTION,那单撤 SELECT 不够,必须额外执行:REVOKE GRANT OPTION ON finance.salary_view FROM 'reporter'@'192.168.10.%';
另外,REVOKE ALL PRIVILEGES 后用户仍保留 USAGE 权限,SHOW GRANTS 会显示 GRANT USAGE ON *.* TO 'reporter'@'192.168.10.%',这是正常现象,不代表权限残留。
如果目标是彻底禁用账号访问能力,不是只撤视图权限,就该走 DROP USER 或 ALTER USER ... ACCOUNT LOCK;,而不是反复折腾 REVOKE。











