mysql 8.0动态权限必须直授用户、on *.*,不可通过角色继承或限定库表;生效需重连,super未撤销会覆盖细粒度控制;system_user禁授,应聚焦application_password_admin等真实业务权限。

MySQL 8.0 的动态权限不能“顺手加上”,必须直授用户、限定 ON *.*、且不能通过角色间接继承——否则直接报错或权限不生效。
GRANT SYSTEM_VARIABLES_ADMIN ON *.* 是唯一合法写法
动态权限作用范围是整个 MySQL 实例,语法强制要求全局层级。任何尝试限定库表的操作都会失败:
-
GRANT SYSTEM_VARIABLES_ADMIN ON mysql.* TO 'user'@'%'→ 报错ERROR 1064 (42000) -
GRANT SYSTEM_VARIABLES_ADMIN ON app_db.* TO 'user'@'%'→ 同样语法错误 - 正确写法只有:
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'user'@'%'
这不是疏忽,是硬性限制。MySQL 解析器在语法层就拒绝非 *.* 的 ON 子句。
哪些操作真需要动态权限?别乱授
常见误判是把“能建表”“能查数据”和动态权限混为一谈。实际场景中,真正触发动态权限检查的操作极少,且都有明确对应关系:
-
SET GLOBAL sort_buffer_size = 4M→ 必须SYSTEM_VARIABLES_ADMIN -
SET SESSION wait_timeout = 600→ 只需SESSION_VARIABLES_ADMIN(不是SYSTEM_) -
START REPLICA→ 必须REPLICATION_SLAVE_ADMIN,光有SUPER已不够(8.0.16+) -
KILL 12345→ 需CONNECTION_ADMIN,旧版靠SUPER实现的这部分能力已被剥离 -
FLUSH BINARY LOGS→ 必须BINLOG_ADMIN
如果你只是想让开发创建临时库,CREATE DATABASE 要的是静态 CREATE 权限,跟动态权限完全无关。
授完不重连,权限等于没给
动态权限生效不走缓存刷新机制,FLUSH PRIVILEGES 对它无效。用户必须断开当前连接、重新登录才能拿到新权限:
- 已存在的连接执行
SHOW GRANTS仍显示旧结果 - 即使 DBA 在另一终端执行了
GRANT ... ON *.*,老连接调用SET GLOBAL仍报ERROR 1227 (42000): Access denied - 应用若用连接池(如 HikariCP),需配置
connection-init-sql=SET ROLE 'xxx'或重启池子
更隐蔽的坑是:如果用户之前被授予过 SUPER,升级到 8.0 后必须显式 REVOKE SUPER ON *.* FROM 'user'@'%',否则动态权限的细粒度控制形同虚设——SUPER 会覆盖所有动态权限检查。
SYSTEM_USER 这种权限千万别碰
SYSTEM_USER 不是操作权限,而是系统账户标识符。它用于标记内部账户(如 mysql.session、mysql.infoschema),普通业务账号既不需要、也不该被授予:
- 授予后不会增强任何操作能力
- 反而可能干扰审计日志或监控系统的账户分类逻辑
- MySQL 官方文档明确建议:仅由服务器内部使用,不应出现在人工 GRANT 语句中
真正该盯住的是 APPLICATION_PASSWORD_ADMIN(双密码切换)、PERSIST_RO_VARIABLES_ADMIN(配合 SET PERSIST_ONLY 使用)这类有明确业务诉求的权限,而不是看到带 _ADMIN 就全授。











