仅设 read_only=1 不够安全,因为 super 权限用户仍可写入;必须同时启用 read_only 和 super_read_only 才能实现强制只读防护。

为什么只设 read_only=1 不够安全
很多用户以为在从库执行 SET GLOBAL read_only = 1 就能彻底禁止写入,结果发现 root 或有 SUPER 权限的账号仍能照常 INSERT/UPDATE。这是因为 read_only 默认对拥有 SUPER 权限的用户无效——它只是“普通只读”,不是“强制只读”。真正堵住这个口子,必须启用 super_read_only。
如何正确启用双层只读:read_only + super_read_only
两者需同时开启才构成有效防护。顺序和方式很重要:
- 先确保主从复制正常运行(
SHOW SLAVE STATUS\G中Slave_IO_Running和Slave_SQL_Running均为Yes),再设置只读,否则可能中断 SQL 线程 - 执行顺序必须是:
SET GLOBAL read_only = 1→SET GLOBAL super_read_only = 1;反过来会报错(ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement) - 要持久生效,必须在配置文件(如
/etc/my.cnf)中显式写入:[mysqld] read_only = ON super_read_only = ON
仅靠SET GLOBAL设置会在重启后丢失
super_read_only 启用后哪些操作会被拒绝
开启后,任何用户(包括 root)都无法执行写操作,除非临时禁用它。被拦截的典型操作包括:
-
INSERT、UPDATE、DELETE、REPLACE、CREATE TABLE、DROP TABLE -
FLUSH LOGS、RESET MASTER、RESET SLAVE(这些会改变复制状态或日志,属于高危操作) - 但允许
SELECT、SHOW、EXPLAIN、SET(非全局变量)等只读语句 - 注意:
SET GLOBAL修改变量本身也会被拒绝,比如SET GLOBAL read_only = 0—— 必须先关super_read_only才能改其他变量
误操作恢复与常见陷阱
如果因配置错误导致从库卡死或无法修复,最常踩的坑是:
- 没关
super_read_only就直接STOP SLAVE:会失败,报错ERROR 1290;正确做法是先SET GLOBAL super_read_only = 0,再STOP SLAVE - 配置文件里写了
super_read_only = ON,但 MySQL 版本低于 5.7.20 —— 该参数不存在,启动会失败;检查版本用SELECT VERSION() - 主库也误配了
super_read_only = 1:会导致主库完全不可写,业务直接中断;生产环境务必确认只在从库配置 -
read_only和super_read_only都是动态变量,但部分旧版本(如 5.6)不支持super_read_only,必须升级
真正起作用的从来不是单个开关,而是两者的组合策略和落地细节——尤其是配置文件是否写对、版本是否支持、启停顺序是否合规。漏掉任意一环,所谓的“只读”就形同虚设。











