mysql 8.0 动态权限是对 super 的拆解而非额外添加,如仅需 set global 应授 system_variables_admin 并撤销 super;动态权限必须直授用户、on .,不可授角色或限定库表,且升级后须显式回收残留 super。

动态权限不是“额外加的权限”,而是对 SUPER 的拆解
MySQL 8.0 把原来一股脑塞给用户的 SUPER 权限,按实际能力切成了十几个独立的动态权限。比如你只想让某个监控账号能执行 SET GLOBAL 修改变量,但不希望它有重启服务、清 binlog 或改复制源的能力——那就只给 SYSTEM_VARIABLES_ADMIN,再把 SUPER 撤掉。这不是锦上添花,是避免权限爆炸的刚需。
常见误判是以为“没授 SUPER 就不能调变量”,其实只要给了对应动态权限(如 SESSION_VARIABLES_ADMIN),SET SESSION sort_buffer_size = 2M 就能成功;而 SET PERSIST_ONLY max_connections = 200 则必须同时有 SYSTEM_VARIABLES_ADMIN 和 PERSIST_RO_VARIABLES_ADMIN。
哪些动态权限最常被误用或漏配?
生产环境踩坑最多的是这几个:
-
REPLICATION_SLAVE_ADMIN:只给它,用户才能执行START REPLICA;但若还涉及BINLOG语句重放(如 mysqlbinlog 输出),还得补上REPLICATION_APPLIER -
AUDIT_ADMIN:启用审计插件后,只有带这个权限的用户才能SET GLOBAL audit_log_policy = 'ALL';否则会报ERROR 1227 (42000): Access denied -
RESOURCE_GROUP_USER:想让应用线程绑定到指定资源组,只给这个就够了;但若要创建/删改资源组,必须用RESOURCE_GROUP_ADMIN -
APPLICATION_PASSWORD_ADMIN:双密码切换(如ALTER USER ... RETAIN CURRENT PASSWORD)必需,否则直接报错ERROR 3022
注意:SYSTEM_USER 是系统账户标识权限,不控制操作能力,仅用于区分内部账户(如 mysql.session),普通业务账号无需也不该授予。
授动态权限时,ON 后面只能写 *.*,不能限定库或表
动态权限作用于服务器全局,语法强制要求:
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'monitor'@'10.20.%';
如果写成 ON mysql.* 或 ON app_db.*,MySQL 会直接报错 ERROR 1064 (42000): You have an error in your SQL syntax。这是硬性限制,不是疏忽。
另外,动态权限不能通过角色间接授予——GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'role_name' 会失败,提示 ERROR 3529 (HY000): Dynamic privileges cannot be granted to roles。必须直授给用户。
回收动态权限容易漏掉“残留的 SUPER”
很多管理员在升级后只新增动态权限,却忘了清理旧的 SUPER。结果就是:用户既有精细权限,又保留了所有老式特权,等于白拆。
安全做法分三步:
- 先查当前有没有
SUPER:SHOW GRANTS FOR 'user'@'host' - 再显式回收:
REVOKE SUPER ON *.* FROM 'user'@'host' - 最后确认:
SHOW GRANTS FOR 'user'@'host'输出里不应再出现SUPER,且警告信息中含Warning: The SUPER privilege is deprecated
特别注意:REVOKE 动态权限时,FROM 后只能是用户名,不能是角色名;动态权限和角色权限是两条平行线,互不交叉。
动态权限本身不记录在 mysql.role_edges 或 mysql.user 表里,而是运行时内存管理。这意味着 mysqld 重启后权限仍在,但如果你用 mysqldump --all-databases 迁移用户,动态权限不会被导出——必须单独用 SHOW GRANTS 重建。这点极易被忽略。











