必须显式授予system_variables_admin权限且严格匹配'user'@'host',因mysql 8.0中all privileges不包含该动态权限;还需确认变量可动态修改、mysqld-auto.cnf可写且persisted_globals_load=on。

必须显式授予 SYSTEM_VARIABLES_ADMIN 权限,且严格匹配连接时的 'user'@'host',否则 SET PERSIST 会直接报错 ERROR 1227。
为什么 GRANT ALL 不够用
MySQL 8.0 中 ALL PRIVILEGES 是静态权限集合,不包含运行时系统变量管理能力。即使你用 GRANT ALL ON *.* TO 'admin'@'%'; 授了全部常规权限,SET PERSIST 仍会失败——因为该操作需要独立的 SYSTEM_VARIABLES_ADMIN 权限。
- 常见错误现象:
SHOW GRANTS FOR CURRENT_USER;输出里没有SYSTEM_VARIABLES_ADMIN - 验证当前身份:执行
SELECT USER(), CURRENT_USER();,取USER()的结果(即实际登录用的'user'@'host') - 授予权限必须精确到这个组合,比如
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'admin'@'192.168.1.5';,不能只写'admin'@'%'就完事 - 授完无需
FLUSH PRIVILEGES,权限立即生效
SET PERSIST_ONLY 还要额外加一个权限
如果要用 SET PERSIST_ONLY(例如预设 log_bin = OFF 等待重启生效),除了 SYSTEM_VARIABLES_ADMIN,还必须有 PERSIST_RO_VARIABLES_ADMIN。普通 DBA 账号通常没有后者,所以执行时报 ERROR 1227 (42501) 很可能就是缺这个。
GRANT PERSIST_RO_VARIABLES_ADMIN ON *.* TO 'admin'@'192.168.1.5';- 该权限不能被包含在角色中(MySQL 8.0.12+ 才支持角色继承,且需启用
activation_policy) - 生产环境建议按 IP 限定 host,避免用
'%'
权限和变量是否可持久化是两回事
有 SYSTEM_VARIABLES_ADMIN 权限 ≠ 所有变量都能用 SET PERSIST。权限只是“准许你试”,最终能否成功,还得看变量本身是否满足两个硬条件:
-
IS_DYNAMIC = 'YES'(支持动态修改) -
VARIABLE_SCOPE = 'GLOBAL'(作用域为全局) - 查法:
SELECT VARIABLE_NAME, VARIABLE_SCOPE, IS_DYNAMIC FROM performance_schema.variables_info WHERE VARIABLE_NAME = 'max_connections'; - 典型不可持久化变量:
datadir、port、socket、protocol_version——这些即使权限全开也会报ERROR 1238 (HY000): Variable 'xxx' is a read only variable
别忽略权限之外的失败原因
权限给对了,SET PERSIST 还失败?大概率卡在下面三个地方:
-
ERROR 3615 (HY000): Cannot write to mysqld-auto.cnf→ MySQL 数据目录不可写(容器挂载为ro、SELinux 启用、或目录属主不是 MySQL 进程 UID,如容器内常用 uid 999) -
SHOW VARIABLES LIKE 'persisted_globals_load';返回OFF→ MySQL 启动时根本没加载mysqld-auto.cnf,所有持久化都无效 - 改完查
performance_schema.persisted_variables没记录 → 不是权限问题,而是变量本身不支持,或者命令输错了(注意大小写、等号前后空格)
最常被忽略的是:权限必须匹配 USER() 而非 CURRENT_USER(),而 mysqld-auto.cnf 文件格式是 JSON,哪怕多一个逗号,MySQL 启动就会失败——它不报语法错,只静默跳过加载。











