不能完全防误删,仅能拦截普通用户的dml和ddl操作;super_read_only才真正锁死root等高权限账号,且需先启用read_only再启用super_read_only。

MySQL 从库设为 read_only=ON 是否真能防误删?
不能完全防,但能拦住绝大多数普通用户的 DELETE、UPDATE、INSERT 和 DROP。前提是:用户不是 super 或 SYSTEM_VARIABLES_ADMIN 权限持有者——这类账号可以绕过 read_only 直接写入。
常见错误现象:read_only=ON 设了,但用 root 登录后照样能删表;或者主从切换后从库没自动恢复只读,导致后续写入污染数据。
-
read_only是会话级变量,必须设为全局生效:SET GLOBAL read_only = ON; - 仅靠 SET 命令不持久,MySQL 重启就失效,必须在配置文件中加:
read_only = ON(放在[mysqld]段) - 如果用了 MGR 或 GTID 自动故障转移,要额外确认
super_read_only=ON,否则高权限用户仍可写
为什么 super_read_only 比 read_only 更关键?
read_only 只限制非超级用户,而 super_read_only 连 root 都锁死——只要它开启,连 SET GLOBAL read_only = OFF 都执行失败,除非先关掉 super_read_only。
使用场景:生产从库、备份节点、审计环境,任何你不希望“有人登上去顺手改点啥”的地方。
- 启用顺序有依赖:必须先开
read_only,再开super_read_only,否则后者会拒绝开启 - 关闭时也得反着来:先
SET GLOBAL super_read_only = OFF,再关read_only - MySQL 5.7.20+ 才支持
super_read_only,低版本只能靠权限控制+监控告警补位
哪些操作不受 read_only 限制?容易被忽略的写入点
即使开了 read_only,以下操作仍可能偷偷写盘,导致从库数据漂移:
- 执行
FLUSH LOGS、RESET MASTER(虽然不改业务表,但破坏复制一致性) - 创建或删除临时表:
CREATE TEMPORARY TABLE不受限制 - 修改系统表(如
mysql.user),尤其当账号有UPDATE权限时 - 调用含写逻辑的存储函数(如果函数里有
INSERT且未加READS SQL DATA限定)
所以光靠 read_only 不够,还得配合最小权限原则:从库账号只给 SELECT、REPLICATION CLIENT、PROCESS,砍掉所有 DML/DCL 权限。
验证从库是否真正只读:别只信 SHOW VARIABLES
SHOW VARIABLES LIKE 'read_only' 返回 ON,不代表安全——可能刚被某个运维脚本临时关过又忘了开,也可能权限没卡死。
实操建议用最笨但最稳的方式验证:
- 用实际业务账号登录,执行:
INSERT INTO test_table VALUES (1);—— 应报错ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement - 再用
root账号试:SET GLOBAL read_only = OFF;—— 如果成功,说明super_read_only没开 - 检查当前活跃连接是否有非只读行为:
SELECT * FROM performance_schema.events_statements_summary_by_user LIMIT 5;看有没有UPDATE/DELETE记录
真正麻烦的是那种“半只读”状态:配置写了,但启动时因权限/路径问题没加载,或者被 systemd 启动脚本覆盖。每次变更后,务必进库跑一遍写操作验证。











