revoke grant option必须显式声明,仅执行revoke all privileges不会收回转授权能力;mysql将grant option视为独立权限,撤销须严格匹配原始授权的作用域(库、表、host)、版本语法(8.0+用for,5.7直接写),且不级联回收已传播权限。

REVOKE GRANT OPTION必须显式声明
只写 REVOKE ALL PRIVILEGES ON db.* FROM 'u1'@'%' 不会收回 GRANT OPTION,它只是权限集合,不包含转授权能力。MySQL 把 GRANT OPTION 当作独立权限处理,哪怕当初是跟 SELECT, INSERT 一起授予的,撤销时也得单独点名。
正确写法必须带 GRANT OPTION FOR:
REVOKE GRANT OPTION ON db1.* FROM 'u1'@'%';
注意:FOR 是 MySQL 8.0+ 的语法;5.7 及更早版本用 WITH GRANT OPTION 作后缀(但仅用于 GRANT),REVOKE 时不加任何修饰词——直接写 REVOKE GRANT OPTION ON ... 即可生效。
撤销 GRANT OPTION 后,已传播的权限是否失效?
取决于 MySQL 版本和当初授权方式:
- MySQL 5.7:不级联回收。即使 u1 已把
SELECT权限转授给 u2,撤掉 u1 的GRANT OPTION后,u2 的SELECT仍有效 - MySQL 8.0+:默认不级联;但若当初用
CASCADE(如REVOKE SELECT ON db.t FROM u1 CASCADE;)才触发级联回收——不过这个语法目前仅对角色(ROLE)支持,对普通用户无效 - 真正能级联切断传播链的,只有
DROP USER u1(连带删掉其所有转授权记录),但这属于账号删除,不是权限回收
常见报错:ERROR 1141 和范围不匹配
执行 REVOKE GRANT OPTION ON *.* FROM 'u1'@'%' 报错 ERROR 1141 (42000): There is no such grant defined...,说明当初不是在 *.* 层级授的权。
必须严格匹配原始 GRANT 的作用域:
- 原始是
GRANT SELECT ON app_db.users TO 'u1'@'%' WITH GRANT OPTION→ 撤销必须写REVOKE GRANT OPTION ON app_db.users FROM 'u1'@'%' - 原始是
GRANT INSERT, UPDATE ON sales.* TO 'u1'@'10.%'→ 撤销GRANT OPTION时 host 必须也是'10.%',不能简写为'%' - 列级权限(如
GRANT UPDATE(col_a) ON t1 TO u1)也要精确到列,REVOKE GRANT OPTION ON t1(col_a)才合法
MySQL 5.7 与 8.0+ 在 GRANT OPTION 处理上的关键差异
MySQL 8.0 引入了角色(ROLE)和动态权限模型,导致 GRANT OPTION 行为更严格:
- 5.7 中,
GRANT OPTION可以跨层级“继承”:在*.*授予后,自动适用于所有库表;8.0 要求显式逐层授予,否则REVOKE无法定位目标 - 8.0+ 的
SHOW GRANTS FOR 'u1'@'%'会明确列出GRANT OPTION所属的作用域,而 5.7 可能只显示GRANT ... WITH GRANT OPTION,不标范围 - 8.0+ 支持
REVOKE GRANT OPTION ON PROCEDURE p1 FROM u1这类对象级细粒度操作;5.7 不支持对存储过程/函数单独撤销GRANT OPTION
最易被忽略的一点:撤销 GRANT OPTION 后,用户仍保有原权限本身(比如 SELECT),只是不能再转授——这点常被误认为“权限全没了”。











