MySQL磁盘空间不足时表现为写入失败、无法建表、主从中断或崩溃;应先用df -h和du定位大文件,再安全清理(如PURGE BINARY LOGS、TRUNCATE TABLE)、优化存储(innodb_file_per_table、字段类型)并建立监控预警机制。

MySQL磁盘空间不足时,最直接的表现是写入失败、无法创建表、主从同步中断或服务崩溃。关键不是等报错才处理,而是快速定位大文件、释放无效数据、优化存储结构,并建立长期监控机制。
查清空间被谁占用了
先确认是哪个分区满了(常用 df -h),再聚焦 MySQL 数据目录(datadir,可通过 SHOW VARIABLES LIKE 'datadir'; 查看)。进入该目录后:
- 用
du -sh * | sort -hr | head -20快速列出最大的库/文件 - 对单个数据库,进对应子目录执行
du -sh *.ibd | sort -hr找出最大的表 - 检查是否有残留的临时文件(如
ibtmp1过大、未清理的.err或慢日志) - 注意:
information_schema.TABLES只反映 InnoDB 表估算大小,实际物理占用以.ibd文件为准
安全清理可释放的空间
不建议直接删文件,应通过 SQL 或规范操作释放:
- 删除无用历史数据:用
DELETE FROM table WHERE ...+OPTIMIZE TABLE(注意锁表,生产环境慎用) - 清空整张表:用
TRUNCATE TABLE比DELETE更快且立即释放空间(但不可回滚) - 归档冷数据:把旧数据导出后
DROP表,或用ALTER TABLE ... REMOVE PARTITIONING(若已分区) - 清理二进制日志:
PURGE BINARY LOGS BEFORE '2024-01-01';或设置expire_logs_days = 7 - 关闭不必要的日志:如禁用通用查询日志(
general_log=OFF)、限制慢日志大小
优化存储避免反复踩坑
释放只是治标,需从配置和设计上减少空间浪费:
- 调整
innodb_file_per_table=ON(默认开启),确保每张表独立.ibd,便于单独回收空间 - 避免
TEXT/BLOB存大量冗余内容,考虑外存或压缩存储 - 合理设置字段类型:用
TINYINT代替INT,用VARCHAR(50)代替VARCHAR(255) - 定期分析表碎片:
SELECT table_name, data_free FROM information_schema.tables WHERE data_free > 1024*1024*100;(>100MB 碎片) - 对频繁更新的大表,考虑使用
ROW_FORMAT=COMPRESSED(需启用innodb_file_format=Barracuda)
加监控防再次告急
靠人工巡检容易滞后,应主动预警:
- 用
zabbix/prometheus + mysqld_exporter监控mysql_global_status_innodb_data_pending_fsyncs和磁盘使用率 - 写脚本每天检查
datadir使用率,超 85% 自动发邮件/钉钉告警 - 记录大表增长趋势:每月跑一次
SELECT table_schema, table_name, round((data_length+index_length)/1024/1024,2) size_mb FROM information_schema.tables ORDER BY size_mb DESC LIMIT 10; - 对业务方明确数据保留策略,比如订单只保留 18 个月,日志类数据自动过期










