my.cnf中read_only=ON不生效需排查四点:配置文件加载顺序(用mysqld --verbose --help确认)、必须同时启用super_read_only=ON、仅在[mysqld]段设置、用户权限与复制状态协同控制。

my.cnf 中 read_only=ON 不生效?先看配置文件加载顺序
MySQL 启动时只会读取一个最终生效的配置文件,不是所有 my.cnf 都会被加载。常见误区是改了 /etc/my.cnf,但实际用的是 /etc/mysql/my.cnf 或 ~/.my.cnf,导致 read_only 配置压根没进启动参数。
- 用
mysqld --verbose --help | grep "Default options"查看 MySQL 实际搜索路径(顺序即优先级) - 确认你修改的文件在第一行列出的路径中;不在就无效
-
~/.my.cnf优先级高于系统级配置,容易被本地用户覆盖 - 如果用了 Docker,检查是否挂载了错误的配置文件,或
command覆盖了配置项
从库 read_only 被主库 SQL 线程绕过?必须配 super_read_only
read_only=ON 对复制线程(sql_thread)不设防——它仍能写入。这是最常被忽略的设计细节:只开 read_only,从库照样可能被误写(比如人为执行 INSERT 或触发器、事件写入)。
- MySQL 5.7.8+ 必须同时启用
super_read_only=ON,才能阻止包括复制线程在内的所有非 SUPER 用户写操作 - 注意:
super_read_only依赖read_only,后者必须先为 ON,否则前者设不上 - 检查命令:
SELECT @@read_only, @@super_read_only;,两个都得是1 - 动态设置需 SUPER 权限,且重启后失效;务必写入配置文件并重启 mysqld
配置写了但状态仍是 OFF?确认是否在正确作用域设置
read_only 和 super_read_only 是全局变量,不能在 [client] 或 [mysql] 段落下配置,只认 [mysqld] 段落。
- 打开你的配置文件,确认
read_only=ON出现在[mysqld]下,而不是[client]或其他段 - Docker 或 systemd 启动时若用了
--defaults-file,会跳过默认路径,此时必须确保该文件里有正确的段落 - 某些云厂商 RDS 屏蔽了这些参数,即使配置了也会被忽略——查控制台或文档确认是否支持自定义
read_only - 配置后务必重启 mysqld,
SET GLOBAL动态设置在重启后丢失,且部分版本不支持运行时开启super_read_only
为什么 SHOW VARIABLES LIKE 'read_only' 返回 ON,但从库还能写?
返回 ON 只说明变量值设对了,不代表当前连接有权限限制——真正起作用的是会话级权限和变量组合。常见干扰项:
- 用户拥有
SUPER权限:即使super_read_only=ON,SUPER 用户仍可写(这是设计行为,不是 bug) - 应用连接用了 root 或其他高权限账号,应创建专用只读账号:
CREATE USER 'ro_user'@'%' IDENTIFIED BY 'xxx'; GRANT SELECT ON *.* TO 'ro_user'@'%'; - 开启了
log_bin但没关binlog_format=STATEMENT,某些语句(如UUID())在从库执行时可能隐式写临时表,看起来像“突破只读” - 检查是否有未停止的
CHANGE MASTER TO或START SLAVE前残留的写操作(比如 relay log 里已有待执行的 DML)
复杂点在于:只读不是开关,是一组配置 + 权限 + 复制状态的协同结果。漏掉任意一环,都会让“只读”变成幻觉。










