仅撤销system_variables_admin无法阻止set global,因用户可能仍持有connection_admin、session_variables_admin、super或通过角色继承的权限;必须同步撤销这四类权限、执行flush privileges并验证。

仅撤销 SYSTEM_VARIABLES_ADMIN 权限不能阻止普通用户修改全局参数——MySQL 8.0+ 中存在至少三个独立权限路径可绕过,必须全部清理。
为什么 REVOKE SYSTEM_VARIABLES_ADMIN 后还能执行 SET GLOBAL
这不是权限没生效,而是用户仍持有其他隐含能力的权限:
-
CONNECTION_ADMIN:该权限隐式包含变量修改能力,且优先级高于SYSTEM_VARIABLES_ADMIN撤销结果 -
SESSION_VARIABLES_ADMIN:允许执行SET PERSIST,写入mysqld-auto.cnf,重启后自动加载为全局值,效果等同于SET GLOBAL -
SUPER:虽在 8.0.12+ 被标记为废弃,但依然有效;旧账号若未显式回收,会继续提供绕过能力 - 角色继承:用户可能通过角色(如
mysql.session)间接获得上述任一权限,SHOW GRANTS不显示角色内嵌权限
如何查清用户真实拥有的变量相关权限
别信你“记得”授了什么,MySQL 权限是叠加生效的。必须用系统表交叉验证:
- 查角色授予的权限:
SELECT * FROM information_schema.role_table_grants WHERE grantee = "'user'@'host'" AND privilege_type IN ('SYSTEM_VARIABLES_ADMIN', 'SESSION_VARIABLES_ADMIN', 'CONNECTION_ADMIN'); - 查直接授权:
SHOW GRANTS FOR 'user'@'host';,确认输出里没有上述任一权限 - 查是否属于高危内置角色:
SELECT * FROM mysql.role_edges WHERE TO_HOST = 'host' AND TO_USER = 'user'; - 特别注意:
GRANT ... WITH ADMIN OPTION表示该用户还能把权限再授给他人,必须同步处理
精准回收权限的完整操作清单
按顺序执行,缺一不可:
- 撤销核心权限:
REVOKE SYSTEM_VARIABLES_ADMIN, SESSION_VARIABLES_ADMIN, CONNECTION_ADMIN, PERSIST_RO_VARIABLES_ADMIN ON *.* FROM 'user'@'host'; - 清理遗留
SUPER:REVOKE SUPER ON *.* FROM 'user'@'host';(即使提示 deprecated,也必须执行) - 刷新生效:
FLUSH PRIVILEGES;(动态权限撤销后必须显式刷新) - 验证是否残留:
SELECT @@global.max_connections;应报错Access denied; you need (at least one of) the SYSTEM_VARIABLES_ADMIN privilege(s)
最容易被忽略的是权限匹配的 host + user 组合——如果应用连接用的是 'app_user'@'10.20.30.5',而你只撤销了 'app_user'@'%' 的权限,实际仍能执行。权限控制的是「连接时匹配的凭据」,不是登录后的身份切换。











