备份与磁盘告警必须交叉验证防静默失败:捕获真实退出码(禁用--force、用${pipestatus[0]})、保留stderr、验证sql内容、查挂载点df而非datadir、阈值设85%、告警含主机名/时间/版本/磁盘状态/脱敏错误日志/上次成功时间。

不能只靠 mysqldump 退出码或文件存在就认为备份成功,也不能只看 df -h 就判断磁盘风险——这两类告警必须交叉验证、带上下文、防静默失败。
备份失败告警必须捕获真实退出码,且禁用 --force
mysqldump 返回非 0 码才是唯一可靠依据,但很多脚本因重定向或管道丢失了它:
- 删掉所有
--force参数:它会让 mysqldump 忽略错误继续输出,结果生成空 SQL 却返回0 - 管道压缩时别直接用
$?:mysqldump | gzip > backup.sql.gz的退出码是gzip的,得用${PIPESTATUS[0]}捕获 mysqldump 真实状态 - stderr 别重定向到
/dev/null:至少写入临时文件,失败时附在告警里,例如2> /tmp/backup.err.$$ - 验证文件是否真有内容:
head -c 1 backup.sql | wc -c为0才说明首字节不可读,不是靠ls -l看大小
磁盘空间预警要查挂载点,而非 datadir 路径
MySQL 数据目录可能软链接到其他分区,或使用裸设备,df 才反映真实剩余空间:
- 用
df -P /var/lib/mysql | awk 'NR==2 {print $5}' | sed 's/%//'提取使用率(替换/var/lib/mysql为你实际的挂载点) - 阈值设为
85(即剩余15%),低于这个数 MySQL 写入易卡住;90以上必须立即干预 - 别只查
datadir下的du:它不包含 binlog、slow_log、ibtmp1 等独立大文件,这些得单独ls -lh或find - 监控脚本每
10分钟执行一次,太频繁增加 I/O,太松散可能错过突发写入高峰
告警内容必须含可定位上下文,不能只说“失败”
凌晨三点收到一条“MySQL 备份失败”,等于没告警。运维需要的是立刻能动手的信息:
- 固定包含:
$(hostname)、$(date)、mysqldump --version、df -h /backup - 附最近
5行脱敏 stderr:sed '/-p\|password\|@/d' /tmp/backup.err.$$ | tail -5 - 查上一次成功时间:
ls -t /backup/backup_*.sql.gz | head -1,对比当前时间差 - 邮件或钉钉调用前校验命令是否存在:
which mailx >/dev/null || exit 1,避免 cron 环境下静默失败
物理备份(XtraBackup)要额外检查关键文件和 prepare 状态
逻辑备份靠 SQL 文件验证即可,XtraBackup 失败更隐蔽,必须确认备份产物完整且可恢复:
- 检查备份目录下是否存在
xtrabackup_binlog_info和xtrabackup_checkpoints,缺一不可 - 轻量级验证
--prepare是否能完成:xtrabackup --prepare --target-dir=/backup/latest/ 2>&1 | tail -10,成功末行应为completed OK! - 别依赖
ps aux | grep xtrabackup判断是否运行中——进程可能卡死但未退出,得看日志最后时间戳 - 若用
rsync同步备份到远端,需在同步后加touch /backup/latest/backup.done,监控脚本检查该文件 mtime
最常被忽略的是:备份脚本和磁盘监控脚本各自独立运行,但告警却没做关联。比如备份失败时磁盘刚好 84%,没人意识到这是同一根导火索——建议在告警正文里自动拼接两者的最新结果,让问题暴露得更早、更直白。











