先查错误日志确认OS error code 28或日志写入失败,再用df -h检查/var/lib/mysql所在分区是否100%满,二者同时成立即可确认磁盘满触发MySQL自动只读。

MySQL报错 ERROR 1621 (HY000): Cannot execute statement in a READ ONLY transaction 怎么确认是磁盘满导致的?
这不是事务只读设置的问题,而是 MySQL 自动进入只读模式的保护机制。先看关键日志:tail -n 50 /var/log/mysql/error.log,如果出现 OS error code 28: No space left on device 或 Could not write to log file,基本可锁定磁盘满。再验证:df -h /var/lib/mysql(或你的数据目录挂载点),Used 列达 100% 或剩余
哪些文件可以安全清理?优先级和风险怎么看?
不是所有大文件都能删,顺序错了可能丢数据或无法启动:
-
binlog文件(如mysql-bin.000123):最安全,但必须用PURGE BINARY LOGS命令删,不能直接rm—— 否则mysql-bin.index不同步,下次启动失败 -
slow_query_log和general_log文件:若已启用且体积大,可临时关闭后清空:SET GLOBAL slow_query_log = OFF;,再rm /var/lib/mysql/slow.log(路径以SHOW VARIABLES LIKE 'slow_query_log_file';为准) -
ibtmp1:InnoDB 临时表空间,MySQL 重启后自动重建,可直接rm /var/lib/mysql/ibtmp1(确保 MySQL 已停止) - 不要碰:
ibdata1、.ibd文件、mysql系统库目录 —— 删了等于删库
如何用 SQL 安全清理 binlog 并防止复发?
执行前确认主从状态(如有从库):SHOW SLAVE STATUS\G,确保 Seconds_Behind_Master = 0 且 IO_Running 和 SQL_Running 都为 Yes。然后按需选择:
- 按时间清理(推荐):
PURGE BINARY LOGS BEFORE '2026-09-20 00:00:00'; - 按文件名清理:
PURGE BINARY LOGS TO 'mysql-bin.000150';(保留该文件及之后的) - 长期防爆:在
my.cnf中加配置项:expire_logs_days = 7(MySQL 8.0+ 改用binlog_expire_logs_seconds = 604800)
注意:PURGE 是原子操作,执行中 MySQL 可正常写入,但期间新建的 binlog 不会被清理。
释放空间后 MySQL 还卡在只读模式怎么办?
磁盘释放后,MySQL 不会自动退出只读状态,必须手动干预:
- 先检查是否真有空间:
df -h确认已释放 ≥2GB - 执行:
SET GLOBAL read_only = OFF;(需要SUPER权限) - 若报错
ERROR 1238 (HY000): Variable 'read_only' is a read only variable,说明实例处于super_read_only = ON状态,得先关它:SET GLOBAL super_read_only = OFF;,再设read_only = OFF - 最后验证:
SELECT @@read_only, @@super_read_only;两个都应返回0
真正容易被忽略的是 super_read_only —— 它比 read_only 优先级更高,且默认在启用了 GTID 或组复制的实例中自动开启,不查就永远切不回来。


















