mysql 5.7中仅设read_only=on无法阻止root写入,因它是“软只读”,仅限非super用户;真正全局只读必须启用super_read_only=on(需5.7.8+),它自动置read_only=on并禁止所有用户(含root)写操作,且需配置文件持久化或set persist生效。

在 MySQL 5.7 中,仅执行 SET GLOBAL read_only = ON 无法真正阻止 root 或其他 SUPER 用户写入——这是设计行为,不是配置失败。要实现安全的全局只读保护,必须启用 super_read_only,且它依赖 read_only 先开启。
为什么 read_only = ON 后 root 还能写?
MySQL 的 read_only 是“软只读”:它只拦截没有 SUPER 或 SYSTEM_VARIABLES_ADMIN 权限的账号。root 默认带 SUPER,所以 INSERT、DROP TABLE、甚至 CREATE FUNCTION 全部不受限。
- 常见误判:运维用 root 执行了
SET GLOBAL read_only = ON,就认为库已锁死 - 验证方式:用普通账号(如
app_user)连接后执行INSERT INTO t1 VALUES (1),应报错ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement - 检查权限:执行
SELECT CURRENT_USER(), @@session.super_priv,确认当前连接是否拥有SUPER
super_read_only 的启用条件和限制
super_read_only 是 MySQL 5.7.8+ 引入的增强开关,但它不是独立变量——它强制依赖 read_only = ON,且一旦启用,连 SET GLOBAL read_only = OFF 都会直接报错。
- 必须先确保
read_only = ON已生效(否则super_read_only = ON会被拒绝) - 启用命令:
SET GLOBAL super_read_only = ON(在线生效,但重启丢失) - 永久生效:在
my.cnf的[mysqld]段下添加两行:read_only = ON和super_read_only = ON(值只能是ON或OFF,不能写1或true) - 启用后,所有写操作(含
ANALYZE TABLE、OPTIMIZE TABLE)均被禁止,但复制线程(sql_thread)仍可应用 relay log
云数据库或容器环境如何落地?
阿里云 RDS、腾讯云 CDB 等托管服务通常禁用 SET GLOBAL,也不开放 my.cnf 修改权限。你无法直接执行 SET GLOBAL super_read_only = ON。
- 必须通过控制台设置:路径一般是「参数设置」→ 搜索
read_only→ 开启「强制只读」(部分厂商该选项底层即启用super_read_only行为) - Docker 部署时,可在启动容器时挂载自定义
my.cnf,或通过环境变量注入(需基础镜像支持,如mysql:5.7官方镜像支持MYSQL_INITDB_SKIP_TZINFO=1类机制,但read_only必须走配置文件) - 若控制台无对应开关,说明实例不支持运行时只读控制,只能靠网络层(如代理、防火墙)阻断写流量,或提前回收应用账号的写权限
容易被忽略的关键点
read_only 和 super_read_only 都只对新建立的连接生效——已存在的长连接(如应用未重连的连接池)仍按旧状态运行,可能继续写入。
- 检查活跃连接:
SHOW PROCESSLIST,重点关注User和Command列,确认高权限账号是否仍在执行写操作 - 生产切换前,建议滚动重启应用连接池,或临时 kill 掉可疑连接:
KILL [id] - MySQL 5.7.20+ 才支持
super_read_only;低于此版本无法启用,只能靠权限回收 +read_only+ 网络层兜底











