磁盘报警时应先运行 df -h 和 df -i 判断空间与 inode 是否耗尽,重点检查 /var/lib/mysql、/tmp 和日志路径;再按优先级排查 binlog、general_log、slow_query_log 等日志膨胀问题,并结合 sql 查询大表、碎片及临时文件定位根因。

先看系统层:df -h 和 df -i 必须一起跑
磁盘报警时,别急着进 MySQL,df -h 和 df -i 是第一道判断线。只看 df -h 可能漏掉 inode 耗尽——尤其是 binlog 文件极多(比如每分钟一个 mysql-bin.00xxxx)或临时表爆炸时,df -h 显示还有 5% 空间,df -i 却是 100%,这时删大文件没用,得删小文件。
重点盯这两个路径:
-
/var/lib/mysql(默认datadir,查SHOW VARIABLES LIKE 'datadir';确认) -
/tmp(默认tmpdir,查SELECT @@tmpdir;;很多 CentOS 的/tmp是 tmpfs,大小受限于内存) -
/var/log/mysql或其他自定义日志路径(查SHOW VARIABLES LIKE 'log_error';、slow_query_log_file、general_log_file)
快速定位日志类“空间杀手”
日志是线上磁盘突增最常见原因,且往往无声无息。以下命令按优先级执行:
- 查 binlog 是否失控:
SHOW BINARY LOGS;看文件数量和总大小;再查SHOW VARIABLES LIKE 'expire_logs_days';或binlog_expire_logs_seconds(MySQL 8.0+),值为 0 或过大就危险 - 查 general_log 是否误开:
SHOW VARIABLES LIKE 'general_log%';,如果general_log = ON且日志落在/var/lib/mysql/下,几小时就能撑爆几十 GB - 查 slow_query_log 是否长期未清理:
SHOW VARIABLES LIKE 'slow_query_log%';,配合ls -lh看文件大小 - 查错误日志里有没有
No space left on device、OS error code 28或Can't create/write to file—— 这些是磁盘写入失败的铁证
确认是不是大表或碎片在吃空间
数据文件膨胀通常不会“突然”,但某些场景会加速:比如误执行全量导入、未加条件的 UPDATE、或频繁 DELETE 后没 OPTIMIZE。执行这条 SQL 找出 Top 10 占用表:
SELECT table_schema, table_name,
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size_mb,
ROUND(data_free / 1024 / 1024, 2) AS free_mb
FROM information_schema.tables
ORDER BY size_mb DESC
LIMIT 10;
注意 data_free 字段:若某张大表的 free_mb 高达几百 MB,说明存在严重碎片,不是数据真多,而是空洞多。这时 OPTIMIZE TABLE 才有效,但需锁表;MySQL 5.7+ 可加 ALGORITHM=INPLACE 减少影响。
别只盯着 ibdata1:如果 innodb_file_per_table = ON(推荐),每个表是独立 .ibd 文件,du -sh /var/lib/mysql/*/*.ibd | sort -rh | head -10 更快定位单个大文件。
临时文件和中继日志常被忽略
Copying to tmp table 或 Creating sort index 卡住,大概率是 tmpdir 满了,而不是查询本身慢。检查:
-
SHOW GLOBAL STATUS LIKE 'Created_tmp%';—— 若Created_tmp_disk_tables持续上涨,说明内存不够,临时表被迫落盘 -
SELECT @@tmpdir, @@innodb_tmpdir;—— 如果都指向/tmp,而/tmp是 tmpfs,那实际空间就是内存大小,极易占满 - 从库上查
SHOW SLAVE STATUS\G,看Relay_Log_File和Relay_Master_Log_File,再ls -lh /var/lib/mysql/mysql-relay-bin.*,旧 relay log 若已应用完却没 purge,也会悄悄吃空间
清理临时文件要小心:sudo find /tmp -user mysql -name "#sql*" -mmin +5 -delete 是安全起点;但别直接 rm -f 正被 mysqld 持有句柄的文件,空间不释放,echo '' > file 更稳。
真正棘手的是 binlog 和 general_log 同时失控,或者 tmpdir 和 datadir 共用一个分区——这种配置下,任何一个环节出问题都会互相拖垮。排查时务必把路径、权限、挂载类型(如 tmpfs)、MySQL 进程是否持有句柄这四点串起来看,不能只盯 SQL 层。











