备份中断大概率因/tmp或备份路径空间/inode不足,需用df -h和df -i分别检查;临时救急用--tmpdir指定大空间目录,长期应脚本开头校验空间并关闭无用日志。

备份脚本执行到一半中断,大概率不是磁盘真满了,而是 mysqldump 在 /tmp 或备份目标路径上撞上了空间或 inode 限制——它不会提前报错,只会在写入失败时静默退出。
确认到底是哪个路径卡住了
别猜,直接查:运行 df -h /tmp 和 df -h /backup(把 /backup 换成你脚本里实际用的路径)。如果两者在同一个挂载点(比如都是 /),那 mysqldump 默认先往 /tmp 写临时文件,再压缩打包,很容易爆掉。再补一句:df -i /tmp,小文件多时 inode 可能先耗尽,df -h 显示还有空间,但实际已无法创建新文件。
临时救急:绕过默认 /tmp 路径
mysqldump 支持 --tmpdir 参数,指定一个空间充裕的目录作为临时缓冲区:
mysqldump --tmpdir=/data/tmp -u root -p mydb > /backup/mydb.sql
- 确保
/data/tmp存在、可写,且 MySQL 进程用户(如mysql)有权限访问 - 该参数只影响
mysqldump自身的临时文件,不影响innodb_tmpdir或sort_buffer_size触发的内部临时表 - 如果用的是
xtrabackup,它不认--tmpdir,得改环境变量:TMPDIR=/data/tmp innobackupex ...
让脚本自己拒绝启动,而不是半截失败
备份失败后清理残留临时文件很麻烦,还可能干扰下一次运行。真正靠谱的做法是:脚本开头就校验空间,不够直接退出,不写任何东西:
#!/bin/bash
BACKUP_DIR="/backup"
THRESHOLD=85
USAGE=$(df "$BACKUP_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
echo "ERROR: $BACKUP_DIR usage ${USAGE}%, aborting backup"
exit 1
fi
# 后续才是 mysqldump 命令
- 这个检查必须包含
/tmp(如果没显式指定--tmpdir)和备份目标路径两个地方 - 别依赖
information_schema.TABLES.DATA_LENGTH估算大小,它比真实.ibd文件小 20%–30%,容易误判 - 脚本里加
set -e,确保任意命令失败立即终止,避免继续往下跑
长期要盯住的三个“隐形吃空间大户”
很多团队只清 binlog,却忽略真正占空间的是这些:
-
general_log和slow_query_log:开启后不轮转,单个日志文件轻松几 GB;关掉立刻释放:SET GLOBAL general_log = 'OFF';,再rm /var/lib/mysql/general.log -
ibtmp1:MySQL 5.7+ 默认启用,升级或重启后可能从 12MB 猛涨到几十 GB,且不会自动收缩;长期方案是在my.cnf加innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:2G - 残留的 binlog 归档:
expire_logs_days = 7在 MySQL 8.0+ 不再实时生效,得看binlog_expire_logs_seconds,或者手动PURGE BINARY LOGS BEFORE '2026-05-25';
最常被忽略的一点:df -h 显示 100%,但 du -sh /var/lib/mysql 总和远小于此?那八成是有“幽灵文件”——文件已被 rm,但 mysqld 进程还在写。用 lsof +L1 找出来,kill 对应进程或重启 MySQL 才能真正释放。











