
怎么判断 mysqldump 真的成功了?只看文件存在是最大的坑
备份脚本跑完生成了一个 backup_20260302.sql.gz,不代表它能用。磁盘满、连接中断、权限不足时,mysqldump 常常会静默写入空文件或截断文件,但退出码一定是非零——这才是唯一可信的信号。
-
mysqldump执行完立刻检查$?:不是 0 就必须告警,别等解压再发现 - 在 crontab 调用的脚本末尾加一句:
echo $? > /tmp/mysql_backup_exit_code - 别把日志重定向到
/dev/null或丢进nohup.out就算完事,错误输出(stderr)里有关键线索,比如Access denied、MySQL server has gone away、Got errno 28 on write(磁盘满) - 用
grep -i "error\|fail\|warning" /var/log/mysql/backup.log定期扫日志,比人工翻快十倍
gzip -t 和 head -n 20 是最低成本的内容校验组合
退出码为 0 只说明导出过程没崩,不保证 SQL 文件语法正确、结构完整、有真实数据。空 dump、乱码、漏 CREATE DATABASE、没 INSERT INTO 都是线上高频问题。
- 强制校验压缩包完整性:
gzip -t backup_$(date +%Y%m%d).sql.gz &>/dev/null && echo ok || echo broken - 快速确认开头有有效结构:
head -n 50 backup_20260302.sql | grep -q "CREATE TABLE"—— 没这行大概率是空备份或字符集错 - 确认有实际数据块(防截断):
zcat backup_20260302.sql.gz | grep -m 1 "INSERT INTO" | wc -l,结果为 0 就得拦停 - 避免全量导入验证(太重),可用
mysql -u user -p -e "source backup.sql" > /dev/null 2>&1测试语法解析,配合$?判断
监控“时间连续性”比监控“单次成功”更重要
一次失败不可怕,可怕的是失败了三天没人发现。备份中断后第 1 天没人查,第 2 天还照常删旧文件,第 3 天轮转完就只剩一个坏备份——这是生产事故的典型路径。
- 文件名必须带时间戳,如
backup_$(date +\%Y\%m\%d_\%H\%M).sql.gz,方便用find定位最新文件 - 监控脚本定期执行:
find /backup/mysql/ -name "*.sql.gz" -mmin -75 | head -1,超 75 分钟没新文件就触发告警(根据你的调度周期微调) - 保留至少 3 代备份(
backup.0→backup.1→backup.2),防止某次轮转误删全部 - 对比文件大小趋势:
stat -c "%s" backup_$(date -d "yesterday" +\%Y\%m\%d).sql.gz,若比过去 7 天均值低超 30%,可能是库被清空或--databases参数漏写库名
主从延迟大时,备份就是“伪一致”,该跳过就得跳过
如果备份时刻 Seconds_Behind_Master 很高,mysqldump 读到的其实是落后主库几秒甚至几分钟的数据,跨事务导出会丢失一致性。这种备份不能标为“一致备份”,应打标并降级使用。
- 备份前加检查:
mysql -e "SHOW SLAVE STATUS\G" | grep -E "(Seconds_Behind_Master|Slave_IO_Running|Slave_SQL_Running)" - 若
Slave_IO_Running: No或Slave_SQL_Running: No,直接中止备份 - 若
Seconds_Behind_Master > 60,记录日志并设标记字段consistency_flag=0,后续恢复流程需人工确认 - 不要在备份脚本里硬等同步追上——可能等一小时,反而错过窗口;宁可当天跳过,也不做假一致










