必须同时撤销SYSTEM_VARIABLES_ADMIN、SESSION_VARIABLES_ADMIN、CONNECTION_ADMIN、PERSIST_RO_VARIABLES_ADMIN及SUPER权限,并执行FLUSH PRIVILEGES;否则SET GLOBAL或SET PERSIST仍可执行,因权限叠加、角色继承或高危权限残留导致绕过。

SET GLOBAL 和 SET PERSIST 是普通用户绕过权限限制修改全局配置的两个主要入口,仅靠回收 SUPER 权限在 MySQL 8.0+ 中已完全失效。必须同时清理三类动态权限,并验证是否残留角色继承。
为什么 REVOKE SYSTEM_VARIABLES_ADMIN 后还能改变量?
常见现象是执行了 REVOKE SYSTEM_VARIABLES_ADMIN ON *.* FROM 'user'@'host';,但用户仍能成功运行 SET GLOBAL wait_timeout = 600 或 SET PERSIST sort_buffer_size = 2097152。这不是权限没生效,而是以下任一情况在起作用:
-
CONNECTION_ADMIN权限隐式包含变量修改能力,且优先级高于SYSTEM_VARIABLES_ADMIN撤销结果 - 用户仍持有
SUPER权限(尤其旧账号未显式回收),该权限在 8.0.12+ 虽已废弃但依然有效 -
SESSION_VARIABLES_ADMIN允许执行SET PERSIST,而该语句会持久化写入mysqld-auto.cnf,重启后自动加载为全局值 - 用户通过角色(如
mysql.session)间接继承了上述任一权限,SHOW GRANTS不显示角色内嵌权限
如何查清用户真实拥有的变量相关权限?
别信你“记得”授了什么,MySQL 权限是叠加生效的。必须用系统表交叉验证:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 查角色授予的权限:
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'; - 再执行:
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) for this operation
容易被忽略的细节
权限生效依赖于「连接时匹配的 host + user」组合,而不是登录后切换用户。如果应用用 'app_user'@'10.20.30.5' 连接,但你授的是 'app_user'@'%',权限不匹配,依然拒绝。另外,SET PERSIST 修改的变量会写入 mysqld-auto.cnf,若磁盘满或该文件不可写,即使有权限也会失败,错误日志中会出现 Failed to write to mysqld-auto.cnf 类提示。

















