必须同时启用super_read_only=on并配最小权限账号才能真正防止误写,因为read_only=on仅拦截无super或system_variables_admin权限的普通用户,而root等高权限账号仍可执行insert、drop table、analyze table甚至set global,导致主从数据静默不一致。

只开 read_only = ON 不足以防止误写,必须同时启用 super_read_only = ON 并配最小权限账号。
为什么从库设了 read_only 还能被写入
因为 read_only = ON 仅拦截普通用户(无 SUPER 或 SYSTEM_VARIABLES_ADMIN 权限)的写操作。拥有高权限的账号(如 root@localhost、监控脚本用的通配符账号 'admin'@'%')仍可执行 INSERT、DROP TABLE、ANALYZE TABLE,甚至 SET GLOBAL——这些都会导致主从数据静默不一致。
常见误写场景包括:
- 运维连错从库,用
root执行FLUSH STATUS或清临时表 - BI 工具连接时使用了带
REPLICATION CLIENT+SUPER的账号 - 云 RDS 控制台显示“只读实例”,但底层未开放
super_read_only参数,配置无效
如何正确启用双只读参数(read_only 和 super_read_only)
二者有强依赖关系,顺序和持久化方式错一个就失效:
- 动态设置时,必须先执行
SET GLOBAL read_only = ON,再执行SET GLOBAL super_read_only = ON;反过来会直接报ERROR 1290 - 配置文件中,
super_read_only = ON必须写在read_only = ON之后,否则 MySQL 启动失败 - 必须写入
/etc/my.cnf的[mysqld]段并重启服务;仅SET GLOBAL在重启后丢失 -
super_read_only = ON会自动把read_only设为ON,但read_only = OFF会强制把super_read_only设为OFF
只读不是靠参数兜底,而是账号 + 参数 + 磁盘三重校验
即使两个参数都开了,仍可能“看起来只读、实际可写”:
- 检查当前连接账号:
SELECT CURRENT_USER(), USER();+SHOW GRANTS FOR CURRENT_USER();,确认应用没用root或'%'@'%'这类通配账号 - 云环境(如阿里云 RDS)可能屏蔽
super_read_only,需查控制台文档或联系支持确认是否开放 - 磁盘满到 ≥95% 时,MySQL 会自动静默把
read_only设为ON,错误提示一模一样,但你查配置文件什么都没改——df -h查/var/lib/mysql所在分区才是第一排查项 - 权限表不复制:主库上
CREATE USER不会同步到从库,只读实例必须单独创建账号并GRANT SELECT,否则连接直接失败
ALTER DATABASE ... READ ONLY 适用场景有限
MySQL 8.0.22+ 新增的数据库级只读功能(如 ALTER SCHEMA lfq READ ONLY = 1)不阻止对其他数据库的写入,也不影响系统库、临时表或日志表;它只适用于极少数需要隔离单库读写的灰度场景,不能替代实例级只读。
真正防住误写的关键点往往藏在权限回收和磁盘状态里,而不是参数开关是否“打上”。SHOW GRANTS 查一遍,df -h 看一眼,比反复 SET GLOBAL 更管用。











