先执行select @@global.read_only;返回1才真被设为只读,再查@@global.super_read_only(5.7+)和show slave status\g确认主从状态,同时用df -h与lsof +l1排查磁盘满或幽灵文件等伪只读原因。

如何确认 MySQL 当前是只读状态?
直接查变量比猜错误更可靠。应用报 ERROR 1290 或日志里出现 The MySQL server is running with the --read-only option,不代表一定是 read_only=ON,也可能是磁盘满或从库同步卡住导致的“伪只读”。先执行:
-
SELECT @@GLOBAL.read_only;—— 返回1才真被设为只读 -
SELECT @@GLOBAL.super_read_only;—— 如果是 5.7+,这个为1会覆盖read_only,普通用户连SET GLOBAL read_only=0都无效 -
SHOW SLAVE STATUS\G—— 查Slave_IO_Running和Slave_SQL_Running是否都为Yes;若其中一项为No,且Seconds_Behind_Master持续增长,大概率是从库自动启用了只读保护
注意:read_only 变更只对新连接生效,已存在的写失败连接不会自动恢复。
df -h 显示 100% 但 du 总和很小?查幽灵文件
这是最典型的“磁盘满但找不到大文件”场景。MySQL 写不进数据,df -h 显示 /var/lib/mysql 所在分区 100%,但 du -sh /var/lib/mysql 加起来才几十 GB——说明有已被删除、但进程仍在写入的文件占着 inode 空间。
- 立刻运行
lsof +L1,重点关注状态为DEL的大文件(尤其是mysqld进程打开的ib_logfile*、binlog或临时表) - 常见罪魁:未结束的
mysqldump、长时间运行的LOAD DATA INFILE、崩溃后残留的ALTER TABLE临时文件 - 杀掉对应进程(如
kill -9 PID),空间会立即释放;别等它自己退出
别跳过这步——很多团队花 20 分钟调参,其实 30 秒 lsof +L1 | grep mysqld 就能解决。
PURGE BINARY LOGS 前必须核对主从位置
Binlog 是压垮磁盘最频繁的元凶,尤其在批量导入或主从延迟高时。但盲目 PURGE BINARY LOGS 可能直接断主从。
- 先执行
SHOW SLAVE STATUS\G,记下Relay_Master_Log_File和Exec_Master_Log_Pos - 再跑
SHOW BINARY LOGS;,确认你要 PURGE 的最老 binlog 文件名是否 早于Relay_Master_Log_File - 安全命令是:
PURGE BINARY LOGS BEFORE '2026-09-28 00:00:00';(比当前时间早一天),而不是RESET MASTER - 长期解法:确保
my.cnf里有expire_logs_days = 3,并验证生效:SELECT @@expire_logs_days;
忘了核对主从就 PURGE,轻则从库报错 Could not find first log file name in binary log index file,重则数据永久丢失。
tmpdir 指向 /tmp?小心内存盘撑爆
很多配置把 tmpdir 或 innodb_tmpdir 设成 /tmp,而 /tmp 在某些系统上是 tmpfs(内存盘)。一旦排序、JOIN 或 ALTER 操作产生大临时文件,就会瞬间吃光内存并触发 OOM Killer 杀掉 mysqld。
- 查当前设置:
SELECT @@tmpdir, @@innodb_tmpdir; - 检查
/tmp类型:df -T /tmp—— 如果是tmpfs,立刻改配置 - 安全路径应为本地磁盘,比如
/var/tmp/mysql-tmp,并确保mysql用户有读写权限 - 改完重启前,先
mkdir -p /var/tmp/mysql-tmp && chown mysql:mysql /var/tmp/mysql-tmp
这个坑极隐蔽:磁盘明明还有 20GB,df -h 却显示 /tmp 100%,而 MySQL 日志里只报 “Can’t create/write to file”,根本看不出是内存盘的事。











