MySQL磁盘空间不足应先用df -h和du -sh定位是否真满或存在“幽灵文件”,再按风险升序清理日志、临时文件或归档binlog;InnoDB大表删除后需OPTIMIZE TABLE或重建释放空间;预防需配置binlog过期、关闭非必要日志并分离binlog存储。

MySQL 磁盘空间不足的直接判断方法
先确认是不是真的磁盘满,而不是 MySQL 自身表损坏或日志堆积。运行 df -h 查看挂载点使用率,重点盯 /var/lib/mysql 所在分区;再用 du -sh /var/lib/mysql/* | sort -hr | head -10 快速定位最大库或文件。如果 df 显示 100% 但 du 总和远小于此,大概率是已删除但进程仍占用的“幽灵文件”,需查 lsof +L1。
快速释放空间的三类操作(按风险升序)
优先执行低风险动作,避免误删:
- 清空 MySQL 的慢查询日志和通用查询日志(如果启用):
SET GLOBAL slow_query_log = 'OFF'; PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);
注意:PURGE BINARY LOGS不影响主从,但RESET MASTER会彻底清空 binlog 并重置序列,仅限单机调试环境。 - 清理
mysql.ibd外的临时文件:检查/var/lib/mysql下是否有以#sql-或ibtmp1结尾的大文件,后者是 InnoDB 临时表空间,重启 mysqld 可重建(前提是innodb_temp_data_file_path未设为固定大小)。 - 删归档 binlog 前务必确认从库已同步:用
SHOW SLAVE STATUS\G检查Relay_Master_Log_File和Exec_Master_Log_Pos,确保不早于从库正在读取的位置。
大表清理后空间不释放?InnoDB 的坑在这里
InnoDB 表即使 DELETE 掉 90% 数据,.ibd 文件也不会自动缩容——这是设计行为,不是 bug。释放空间只有两种可靠方式:
-
OPTIMIZE TABLE t1;:会重建表并释放碎片,但全程锁表(5.7+ 支持 ALGORITHM=INPLACE 的 DDL,仍需短暂排他锁); -
ALTER TABLE t1 ENGINE=InnoDB;:效果同上,但更明确; - 真正想缩文件,必须用
mysqldump导出 +DROP TABLE+ 重建导入——适合离线维护窗口期。
注意:innodb_file_per_table=ON 是前提,否则所有表共用 ibdata1,删表也不释放空间。
预防性配置必须改的三项
别等爆满才想起调参:
- 限制 binlog 保留时间:
expire_logs_days = 7(MySQL 5.7)或binlog_expire_logs_seconds = 604800(8.0+),写入my.cnf后需重启或SET PERSIST; - 关闭非必要日志:
general_log = OFF、slow_query_log = OFF(开发环境可开,生产慎用); - 监控
information_schema.INNODB_SYS_TABLESPACES中FILE_SIZE和ALLOCATED_SIZE差值,差得大说明碎片严重,该计划OPTIMIZE了。
最常被忽略的是:没有把 log_bin 单独挂到大容量磁盘,导致 binlog 和数据文件挤在同一分区——一出问题就全卡死。










