MySQL突然只读需先查read_only和super_read_only状态,任一为ON即确认全局只读;磁盘满≥95%也会自动触发只读,须用df -h验证并手动SET GLOBAL关闭。

MySQL突然只读,先确认是不是 read_only 或 super_read_only 被打开了
线上写操作全报错 ERROR 1290 (HY000): The MySQL server is running with the read-only option...,第一反应不是改权限,而是查状态。因为只读模式可能被人为开启、磁盘满自动触发、或主从切换后残留配置。
执行这两条命令快速验证:
SHOW VARIABLES LIKE 'read_only';<br>SHOW VARIABLES LIKE 'super_read_only';
如果任一返回 ON,就坐实了是全局只读开关生效。注意:super_read_only = ON 时,连 root 都不能写——这不是权限问题,是实例级锁死。
-
read_only = ON:普通用户禁止写,但拥有SUPER权限的用户仍可写 -
super_read_only = ON:所有用户(含SUPER)均不可写,且该变量依赖read_only,必须先开read_only才能启用它 - 这两个变量只对新连接生效;已存在的连接仍保留旧权限,所以改完要让应用重连或重启连接池
临时关闭只读模式,用 SET GLOBAL 而不是改配置文件
故障期间不能等重启,必须秒级恢复写能力。直接 SQL 命令最有效:
SET GLOBAL read_only = OFF;<br>SET GLOBAL super_read_only = OFF;
这两句必须都执行(如果 super_read_only 是 ON),顺序无所谓,但缺一不可。执行后立即对新连接生效。
- 不需要
FLUSH PRIVILEGES—— 这是权限表刷新命令,和read_only无关 - 如果提示
Access denied,说明当前用户没SUPER权限,换有该权限的账号(如root)再试 - 改完立刻用
SHOW PROCESSLIST看是否有长事务卡住,避免刚放开就撞上锁等待
排查完别忘了关回去,但别用 GRANT/REVOKE 恢复“只读用户”
很多人误以为“只读”是靠给用户删权限实现的,结果故障排查时又手动 GRANT INSERT,完事再 REVOKE——这极不安全。
真正适合临时排查的只读控制,是角色(ROLE)机制:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 提前建好专用角色:
CREATE ROLE 'troubleshoot_role'; - 只授最小必要权限:
GRANT SELECT, SHOW DATABASES, PROCESS, REPLICATION CLIENT ON *.* TO 'troubleshoot_role'; - 赋予目标用户:
GRANT 'troubleshoot_role' TO 'dba_user'@'%'; - 排查时激活:
SET ROLE 'troubleshoot_role';(仅当前会话生效) - 退出或执行
SET ROLE NONE;即刻失效,不残留、不审计难、不影响连接池
用 GRANT/REVOKE 动用户权限,最大的坑是:REVOKE 不会清理已建立连接的权限缓存,旧连接还能继续写;而角色是会话级的,干净利落。
磁盘空间不足也会自动触发只读,别漏查 df -h
MySQL 5.7+ 在数据目录所在分区使用率 ≥ 95% 时,会自动设 read_only = ON 防止写崩溃。这种“被动只读”不会出现在 my.cnf 里,也查不到人工操作记录。
所以看到 read_only = ON 但没人动过,立刻跑:
df -h /var/lib/mysql
如果已满,清日志或扩盘后,read_only 不会自动关,必须手动 SET GLOBAL read_only = OFF。
顺手检查慢查询日志、错误日志是否占满:ls -lh /var/log/mysqld*,大日志文件直接 mv 归档 + kill -USR1 `cat /var/run/mysqld/mysqld.pid` 触发日志轮转。










