MySQL 报 "Writing file" 错误(Errcode: 28)怎么办?

MySQL Errcode 28 = No space left on device,磁盘写满。用 perror 解码错误码,df -h/df -i 定位分区与 inode,清理 binlog/慢日志/临时表空间的完整处置流程与 FAQ。

最佳实践
MySQL 报 "Writing file" 错误(Errcode: 28)怎么办?封面

Errcode 28 的含义是 No space left on device——MySQL 所在分区磁盘满了(或 inode 耗尽),写数据/临时文件/日志失败。 可用 perror 28 直接查看任何 MySQL 错误码的文字解释。

perror 28
# 输出:OS error code  28:  No space left on device

第一步:确认是哪个分区满了

df -h                 # 看各分区使用率,重点找 100% 的
df -i                 # 磁盘有空间也可能 inode 耗尽(海量小文件)

MySQL 常写满的位置:数据目录(默认 /var/lib/mysql)、tmpdir(排序/临时表)、binlog 目录、慢查询/错误日志。

第二步:找出空间杀手

du -sh /var/lib/mysql/* | sort -rh | head -20    # 哪个库/表最大
ls -lh /var/lib/mysql/ | grep -E 'binlog|\.log' | head

最常见的四个元凶:

  1. binlog 无限增长:主从或开了 binlog 没设过期——SHOW BINARY LOGS; 看数量,PURGE BINARY LOGS BEFORE '2025-01-01'; 清理,配置文件设 binlog_expire_logs_seconds
  2. 慢查询/general 日志:尤其 general log 忘关,几天能吃几十 G。
  3. 大临时文件tmpdir#sql*.ibd 之类,通常是巨型 ALTER 或排序撑的。
  4. Undo/表空间膨胀:长事务导致 undo 堆积,或 ibdata1 只增不减。

第三步:应急与根治

应急(先让 MySQL 能写):

# 清 binlog 到某个时间点(确认从库已追上!)
PURGE BINARY LOGS TO 'mysql-bin.000123';

# 关闭 general log 并清空
SET GLOBAL general_log='OFF'; TRUNCATE mysql.general_log;

根治:

  • binlog 设过期:my.cnf 里 binlog_expire_logs_seconds = 604800(7 天)。
  • 日志接 logrotate;慢日志单独分区。
  • 大表定期 OPTIMIZE TABLE 或归档历史数据。
  • 给磁盘设监控——下次别再让数据库先发现。

观测云对照

"磁盘满了数据库崩"是运维最不该发生的故障——它 100% 可提前预警。观测云主机监控采集每块磁盘的使用率、inode 使用率,配合监控器设 80%/90% 两级阈值,钉钉/企微提前几天就能收到预警;MySQL 自身的 binlog 增长速率、表空间大小也能通过数据库集成纳入同一仪表盘,空间消耗趋势一目了然。

常见问题(FAQ)

Q:df 显示还有空间,为什么还报 28?
A:两种可能:df -i 看 inode 是否耗尽(小文件太多);或者 MySQL 的 tmpdir 指向了另一个已满的分区(常见于 tmpdir=/tmp 而 /tmp 是小分区)。

Q:磁盘满了连清理命令都执行不了怎么办?
A:先腾出一点空间让系统能工作:truncate -s 0 清空一两个大日志文件(比 rm 安全,不占额外空间),然后再做正式清理。

Q:清完空间后 MySQL 需要重启吗?
A:一般不用。但满盘期间可能有写失败导致的数据不一致,建议对关键表跑 CHECK TABLE,主从环境再校验一次复制状态。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台