必须同时设置read_only=on和super_read_only=on(mysql 5.7.8+),并确认二者均为1,才能真正阻断所有用户(含super权限root)写入;仅read_only=on无效,且需配合低权限账号与磁盘空间监控。

从库 read_only 明明是 ON 却还能写入?先查 super_read_only
MySQL 5.7.8+ 的从库只读,read_only = ON 本身就不够用——它只拦普通用户,对拥有 SUPER 权限的账号(比如 root、DBA 账号)完全无效。真正能阻断所有写操作的,是 super_read_only = ON。
必须两个变量同时为 1 才算生效:
-
SELECT @@read_only, @@super_read_only;返回1, 1才安全 - 如果只返回
1, 0,说明super_read_only没开,高权限用户仍可执行INSERT、DROP TABLE、CREATE EVENT等操作 - 动态设置顺序不能错:
SET GLOBAL read_only = ON;必须在前,再执行SET GLOBAL super_read_only = ON;;反过来会报错ERROR 1290
配置文件改了但没生效?确认加载路径和段落位置
写进 /etc/my.cnf 不等于 MySQL 就读到了。启动时它只认一个最终生效的配置文件,顺序由 mysqld --verbose --help | grep "Default options" 输出的第一行决定(常见是 /etc/mysql/my.cnf 优先于 /etc/my.cnf)。
还要注意段落作用域:
-
read_only = ON和super_read_only = ON必须放在[mysqld]段下,写在[client]或[mysql]里完全被忽略 - 二者在配置文件中的顺序也有要求:
super_read_only = ON必须写在read_only = ON后面,否则 MySQL 启动失败 - Docker 场景要特别小心:
--defaults-file参数会跳过默认路径;挂载配置时,确认容器内路径与mysqld实际读取路径一致
写不进去却报 ERROR 1290?别急着关参数,先看磁盘空间
从库突然变只读,不一定是因为你改了配置。当数据目录所在磁盘使用率 ≥ 95%,MySQL 会自动把 read_only 设为 ON 并拒绝一切写入,错误信息也是 ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement。
这不是配置失效,而是保护机制触发:
- 立刻执行
df -h,重点看/var/lib/mysql所在分区 - 临时释放空间可用:
DELETE FROM large_table WHERE ...;或PURGE BINARY LOGS BEFORE '2026-04-01'; -
OPTIMIZE TABLE虽能回收空间,但会锁表,生产环境慎用
应用连的是从库,但写请求没被拦住?检查连接账号权限
即使 read_only 和 super_read_only 都是 ON,如果应用用的是带 SUPER 权限的账号(比如 root),而你又没关 super_read_only,那写请求照样会被拒绝——但更危险的是反过来:账号没 SUPER,但 super_read_only 没开,read_only 就形同虚设。
正确做法是权限与参数双控:
- 从库专用账号应最小化授权:
CREATE USER 'ro_user'@'%' IDENTIFIED BY 'xxx'; GRANT SELECT ON *.* TO 'ro_user'@'%'; - 禁用
SUPER权限:REVOKE SUPER ON *.* FROM 'ro_user'@'%'; - 云 RDS(如阿里云、腾讯云)可能屏蔽
super_read_only参数,即使配置了也无效果,得查控制台文档或联系支持确认是否开放
真正让从库“物理级只读”的,从来不是单个变量,而是 read_only 与 super_read_only 的组合、低权限账号、磁盘水位监控三者缺一不可。最容易被忽略的,是磁盘满导致的自动只读,它不报配置错误,也不留日志痕迹,只默默把所有写请求挡在外面。











