revoke命令必须配合on和from使用,缺一不可;其基本结构为revoke priv_type on db.table from 'user'@'host',权限回收后即时生效,无需flush privileges。

revoke 命令必须配合 on 和 from 使用,缺一不可
MySQL 的 REVOKE 不是独立生效的命令,它必须明确指定「收回哪些权限」「在哪个对象上」「从哪个用户」。漏掉 ON 或 FROM 会直接报语法错误,比如:ERROR 1064 (42000): You have an error in your SQL syntax。
基本结构是:REVOKE priv_type ON db.table FROM 'user'@'host';
-
priv_type可以是SELECT、INSERT、ALL PRIVILEGES等;多个权限用逗号分隔,如SELECT, UPDATE -
ON后的对象范围要和当初GRANT时完全一致:库级写db.*,表级写db.table,全局写*.* -
FROM后的用户必须带引号,且主机部分(如'localhost'或'%')要和创建用户时一致,否则 MySQL 找不到匹配账户
回收 ALL PRIVILEGES 后,USAGE 权限仍保留
执行 REVOKE ALL PRIVILEGES ON *.* FROM 'u1'@'%'; 并不会让该用户彻底“失效”。MySQL 会自动保留一个隐式的 USAGE 权限——它不赋予任何实际操作能力,但允许用户连接服务器(只要密码正确)。这意味着用户还能登录,只是执行任何 DML/DQL 都会报 ERROR 1142 (42000): SELECT command denied 类错误。
若要彻底禁用账号,得额外执行:DROP USER 'u1'@'%'; 或 ALTER USER 'u1'@'%' ACCOUNT LOCK;
回收权限后必须执行 FLUSH PRIVILEGES 吗?
不需要。MySQL 8.0+ 中,REVOKE 是即时生效的,权限变更直接写入系统表(如 mysql.role_edges、mysql.db),服务端内存缓存会自动刷新。只有在极少数手动修改了系统表(比如用 UPDATE mysql.user)之后,才需要 FLUSH PRIVILEGES。
常见误操作:在 REVOKE 后多加一句 FLUSH PRIVILEGES,虽然不报错,但纯属冗余,还可能掩盖权限未生效的真实原因(比如 ON 范围写错了)。
跨库权限回收容易漏掉 db.* 级别授权
用户可能同时拥有多个层级的权限:全局(*.*)、库级(sales.*)、表级(sales.orders)。只对某张表执行 REVOKE SELECT ON sales.orders FROM 'u1'@'%';,不影响其对整个 sales 库的访问能力。
排查方法:SHOW GRANTS FOR 'u1'@'%';,逐条检查输出结果。重点看是否有更宽泛的授权覆盖了你想收回的细粒度权限。
若需彻底清除某用户的库级权限,必须显式回收:REVOKE SELECT, INSERT ON sales.* FROM 'u1'@'%';
权限继承关系是“取并集”,不是“取交集”——哪怕只有一处 GRANT SELECT ON *.* 存在,用户就能查所有表。










