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 个月,日志类数据自动过期
