仅靠read_only=on无法防止super用户写入,必须同时配置read_only=on和super_read_only=on(顺序不可颠倒)、持久化生效,并回收super及system_variables_admin权限,三者缺一不可。

不能,仅靠 read_only = ON 无法防止具有 SUPER 权限的用户写入。这是 MySQL 的明确设计行为,不是配置错误或版本缺陷。
为什么 read_only = ON 对 root 或 SUPER 用户完全无效
read_only 的作用机制是「权限感知型拦截」:它只检查当前会话用户的权限位,若用户拥有 SUPER(MySQL 8.0.12+ 还包括 SYSTEM_VARIABLES_ADMIN),所有写操作(INSERT、DROP TABLE、CREATE FUNCTION、ANALYZE TABLE 等)都会被放行。
- MySQL 默认给
'root'@'localhost'授予了SUPER和SYSTEM_VARIABLES_ADMIN - 监控脚本、备份工具、高可用组件常用账号也常带
SUPER,它们连上从库后仍可写 -
SHOW VARIABLES LIKE 'read_only'返回ON≠ 实际生效,只是变量值设对了
super_read_only = ON 才是真正兜底的开关
super_read_only 是 MySQL 5.7.20+ 引入的强制锁写机制,启用后:
– 自动把 read_only 设为 ON
– 禁止所有用户(含 SUPER)执行任何写语句
– 连 SET GLOBAL read_only = OFF 都会直接报错 ERROR 1290
- 必须在配置文件
[mysqld]段中,先写read_only = ON,再写super_read_only = ON;顺序颠倒会导致 mysqld 启动失败 - 不能写在
[client]或[mysql]节里——MySQL 会静默忽略 - 值必须是
ON或OFF,不接受1、true、小写on - MySQL 8.0.22+ 可用
SET PERSIST super_read_only = ON,自动写入mysqld-auto.cnf,适合容器环境
即使开了 super_read_only,仍可能被绕过的三个盲点
这个变量本身不是“物理只读”,它的保护边界有明确限制:
-
SQL线程回放 relay log 不受影响——这是复制机制要求,不是漏洞 - 如果从库开启了
log_bin(例如用于级联复制),binlog 写入照常,但主动写表会被拦 -
super_read_only = ON后,只要用户有SYSTEM_VARIABLES_ADMIN权限,仍可执行SET GLOBAL super_read_only = OFF—— 所以这个权限本身也要回收
真正锁死的关键不在参数个数,而在三件事是否同时做对:配置文件顺序正确、super_read_only 持久化启用、高权限账号的 SUPER 和 SYSTEM_VARIABLES_ADMIN 显式回收。漏掉任意一项,root 或监控脚本都可能在你认为“已只读”的时候删掉一张表。











