mysql动态权限自8.0.16起引入,是运行时注册、全局生效的管理权限,不存于系统表,不可被grant all包含,需显式授予如backup_admin等,且仅作用于.。

确认 MySQL 版本并列出可用动态权限
动态权限仅在 MySQL 8.0+ 生效,低于该版本直接不识别 GRANT CONNECTION_ADMIN 这类语句。先执行:SELECT VERSION();
若返回结果是 7.9.9 或更低,后续所有操作都会报错 ERROR 1064 (42000)。
确认版本达标后,查当前支持的动态权限列表:SELECT privilege, is_dynamic FROM mysql.global_grants;
或更准确地:SELECT * FROM mysql.dynamic_privileges;
注意:mysql.dynamic_privileges 是只读数据字典表,MySQL 8.0.16 起才稳定提供,早期 8.0.x(如 8.0.11)可能为空或缺失。
授予权限时必须指定 ON *.* 且不能省略 host
动态权限只能授予全局级别,语法强制要求 ON *.*,写成 ON testdb.* 或 ON testdb.t1 会直接报错:ERROR 3528 (HY000): Dynamic privileges can only be granted at the global level。
同时,用户主体必须带明确 host,例如:GRANT CONNECTION_ADMIN ON *.* TO 'monitor'@'10.20.30.%';
不能写成 'monitor'@'%' 后再用 FLUSH PRIVILEGES 补救——MySQL 会拒绝解析,提示 ERROR 1410 (42000): You are not allowed to create a user with GRANT(尤其当用户尚不存在时)。
常见疏漏点:
• 用户未提前创建,直接 GRANT ... TO 'newuser'@'%'... 失败
• host 写成 'localhost' 却从远程连接,权限不生效
• 混淆静态权限语法,漏掉 ON *.*
避免用户自赋动态权限的安全漏洞
MySQL 8.0.18 至 8.0.33 存在已知缺陷:只要用户拥有 GRANT OPTION,即使没有 SYSTEM_USER 或 APPLICATION_PASSWORD_ADMIN,也能成功执行:GRANT SYSTEM_USER ON *.* TO CURRENT_USER();
这会导致权限失控,且 SHOW GRANTS 里真会显示该权限已存在。
缓解方式只有两种:
• 不给任何非管理员用户 GRANT OPTION(最稳妥)
• 升级到 MySQL 8.0.34+ 或 8.1.0+,该漏洞已在官方补丁中修复(参考 Bug #112478)
• 临时监控 mysql.global_grants 表变更,例如用触发器或定期巡检脚本
撤销动态权限后 SUPER 不自动恢复
如果你用 REVOKE SUPER ON *.* FROM 'user'@'host'; 剥离旧权限,再赋予若干动态权限(如 SESSION_VARIABLES_ADMIN),要注意:
• SUPER 被撤回后不会“降级保留”子能力,必须显式授予对应动态权限
• SHOW GRANTS 输出里 SUPER 条目消失即生效,无需 FLUSH PRIVILEGES
• 但若用户正在使用 SUPER 执行的操作(如 KILL QUERY),撤销后立即失效,已有连接不受影响,新操作会报 ERROR 1227 (42000): Access denied; you need (at least one of) the SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
真正容易被忽略的是:某些客户端工具(如旧版 MySQL Workbench、Navicat)内部仍尝试用 SUPER 判断权限,即使你已正确配置了 CONNECTION_ADMIN,它们也可能报错或功能异常——此时需升级客户端或切换至命令行验证。











