read_only=on对super权限用户无效,需配合最小权限控制才真正生效;super_read_only=on可阻断所有用户写入但5.7.20+才支持,且主从切换后需手动关闭,系统库操作不受二者限制。

设置 read_only=ON 后为什么还能写入?
因为 read_only 对拥有 SUPER 权限的用户无效——这是最常被忽略的前提。运维或 DBA 账号通常带 SUPER,所以即使开了 read_only,用 root 或同权限账号照样能执行 INSERT/UPDATE/DROP。
实操建议:
- 先确认当前用户权限:
SELECT CURRENT_USER(), SUPER_PRIV FROM mysql.user WHERE User=CURRENT_USER(); - 普通应用账号应只授予
SELECT、USAGE等最小权限,避免继承SUPER -
read_only=ON必须配合权限控制才真正生效,单设它不防高权限用户
super_read_only=ON 是不是更保险?
是,但它会强制阻断所有用户的写操作(包括 SUPER 用户),且启动时若配置了 super_read_only=ON,MySQL 会拒绝启动,除非同时显式指定 --skip-grant-tables(不推荐)或先临时关闭它再启动。
实操建议:
- 动态启用:
SET GLOBAL super_read_only = ON;,但需确保当前会话没在事务中,否则报错ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement - 永久生效要写进配置文件:
[mysqld]段下加super_read_only=ON,但上线前必须验证实例能否正常重启 - 注意:5.7.20+ 才支持该变量;5.6 及更早版本只有
read_only,且无对应机制
从库自动切主后 read_only 还生效吗?
不生效。MySQL 主从角色切换(比如 MHA、Orchestrator 自动故障转移)后,原从库变主库,但 read_only 和 super_read_only 不会自动关闭——这会导致新主库“假性只读”,应用写请求全失败。
实操建议:
- 自动化切换工具必须包含 post-failover 步骤:连接新主库并执行
SET GLOBAL read_only = OFF;和SET GLOBAL super_read_only = OFF; - 监控项要覆盖这两个变量值,告警阈值设为“主库上
read_only=ON”或“从库上super_read_only=OFF”,而非只盯复制状态 - 不要依赖
read_only做主从路由判断,应用层或中间件应以SELECT @@read_only+SHOW SLAVE STATUS综合判定角色
为什么 read_only 无法阻止 DROP TABLE mysql.*?
因为 read_only 默认不保护系统库(mysql、information_schema、performance_schema、sys),对这些库的 DDL/DML 仍允许执行——哪怕用户没有 SUPER 权限。
实操建议:
- 如需彻底锁定系统库,必须额外收回对应权限:
REVOKE DROP ON mysql.* FROM 'appuser'@'%'; -
super_read_only=ON也不限制系统库操作,它只限制“非 SUPER 用户”的常规库写入,对系统库无额外防护 - 生产环境应禁止应用账号访问
mysql库,连SELECT都不该开
复杂点在于:两个变量作用域不同、生效时机不同、权限交互逻辑隐蔽,而且故障场景下(比如切主失败、配置未加载)容易误判只读状态是否真实生效。别只改一个参数就以为万事大吉。










