原标题:MySQL 数据库自动备份失败排查教程 源于DNF_私服数据库自动备份失败排查记录

一、适用场景

适用于 Linux 服务器上出现以下情况:

手动执行数据库备份正常,但定时自动备份没有生成文件。

常见于 MySQL/MariaDB + Shell 脚本 + cron/crond 的备份方案。


二、排查思路

不要直接修改数据库配置,应按照备份链路逐层排查:

定时服务
→ 定时任务
→ 备份脚本
→ 数据库备份
→ 压缩/打包
→ 最终备份文件

只要确定哪一层失败,就可以缩小问题范围。


三、检查定时服务

首先确认 crond 是否正常:

systemctl status crond
systemctl is-active crond

正常应显示:

Active: active (running)

如果系统使用 cron,则执行:

systemctl status cron

如果定时服务没有运行,先启动并设置开机自启:

systemctl start crond
systemctl enable crond

四、检查定时任务是否存在

查看当前用户:

crontab -l

查看 root:

sudo crontab -l

查看系统级任务:

cat /etc/crontab
ls -la /etc/cron.d/

同时可以搜索备份相关任务:

grep -RniE "backup|mysqldump|mysql|sql" /etc/cron* /var/spool/cron 2>/dev/null

如果完全找不到备份任务,说明问题可能出在面板没有正确创建定时任务,而不是数据库本身。


五、确认定时任务是否实际执行

查看 crond 日志:

journalctl -u crond --since "1 hour ago" --no-pager

部分系统也可以查看:

tail -100 /var/log/cron

实时观察:

journalctl -u crond -f

到了任务设定时间后,如果出现:

(root) CMD (...)

说明 crond 已经触发任务。

如果 crond 正常运行,但到了执行时间完全没有对应的 CMD,应继续检查 cron 配置、文件权限及任务格式。


六、找到实际执行的备份脚本

例如 cron 中存在:

1 * * * * root run-parts /etc/cron.hourly

则需要继续检查:

ls -la /etc/cron.hourly/

找到对应脚本后查看:

cat /etc/cron.hourly/备份脚本

继续追踪它实际调用的程序,例如:

/etc/cron.hourly/backup
        ↓
/root/backup/sql
        ↓
mysqldump

不要只检查 cron 配置,要一直追踪到真正执行数据库备份的 Shell 脚本。


七、直接手动执行备份脚本

找到实际脚本后,直接执行:

cd /脚本所在目录 && ./backup.sh

或者:

bash /脚本路径

观察完整输出。

如果手动执行也失败,问题就在脚本、数据库连接、权限或依赖程序。

如果手动执行成功,而自动执行失败,则重点检查 cron 与 SSH 手动执行环境的差异。


八、检查数据库备份

确认 mysql 和 mysqldump 是否存在:

which mysql
which mysqldump

测试数据库连接:

mysql --defaults-extra-file=/etc/my.cnf -h127.0.0.1 -e "show databases"

单独测试备份:

mysqldump --defaults-extra-file=/etc/my.cnf -h127.0.0.1 --all-databases > /tmp/test.sql

如果数据库备份成功,说明问题已经不在 MySQL,而应该继续检查后面的压缩、上传或文件保存阶段。


九、检查备份文件和压缩过程

很多备份脚本并不是直接生成最终文件,而是:

MySQL
→ dnf.sql
→ tar.gz
→ 删除 dnf.sql

因此需要分别检查每个阶段。

例如:

ls -lh /root/mysqlbak/

如果发现 .sql 已生成,但 .tar.gz 没有生成,说明数据库备份成功,问题发生在压缩阶段。

单独测试:

tar -czf /tmp/test.tar.gz /备份文件.sql

同时检查 tar:

which tar
tar --version

十、重点检查 cron 环境差异

cron 执行脚本时的环境通常比 SSH 手动执行更加简单。

重点检查:

1. PATH

cron 可能只有:

PATH=/sbin:/bin:/usr/sbin:/usr/bin

而手动 SSH 环境拥有更多 PATH。

因此脚本最好使用绝对路径:

/usr/bin/mysql
/usr/bin/mysqldump
/usr/bin/wget
/bin/tar

可以使用以下命令确认实际路径:

which mysql mysqldump wget tar

2. 当前目录

不要依赖:

./backup.sh

或:

backup/file.sql

最好使用绝对路径:

cd /root/backup
/bin/bash /root/backup/backup.sh

3. 权限

确认执行用户:

ls -l /备份脚本
ls -ld /备份目录

并确认该用户具有:

  • 执行脚本权限
  • 读取数据库配置权限
  • 写入备份目录权限

十一、检查服务器环境变化

如果备份方案在旧服务器正常,迁移到新服务器后失败,应重点对比两台服务器的环境。

常见差异包括:

操作系统版本
MySQL/MariaDB版本
mysql/mysqldump路径
Shell环境
PATH
权限
IPv4/IPv6
防火墙
DNS
外网访问
/etc/my.cnf
依赖程序

特别注意脚本中是否存在:

wget
curl
tar
gzip
mysqldump

等外部依赖。


十二、特别检查 IPv4 / IPv6

如果备份脚本会获取公网 IP,并将 IP 写入文件名,例如:

IP=$(wget -qO - ifconfig.co)
tar -czf sql_${IP}_${time}.tar.gz dnf.sql

需要特别检查:

wget -qO - ifconfig.co

返回的是 IPv4 还是 IPv6。

如果返回:

2402:xxxx:xxxx:xxxx:xxxx

而脚本没有考虑 IPv6,可能因为 IPv6 中的 : 导致文件名或命令参数被错误解析。

可以强制获取 IPv4:

IP=$(wget -4 -qO - ifconfig.co)

更稳妥的是不要让公网 IP 成为备份流程的必要依赖。


十三、给自动备份增加日志

如果自动任务失败但没有任何提示,最有效的方法是将输出写入日志:

cd /root/backup && /bin/bash /root/backup/backup.sh >> /root/backup/backup.log 2>&1

之后查看:

cat /root/backup/backup.log

或者:

tail -100 /root/backup/backup.log

这样可以直接看到 cron 执行脚本时产生的错误。


十四、快速判断故障位置

情况 1:crond 没运行

crond
×

处理定时服务。

情况 2:crond 正常,但没有备份任务

crond ✓
cron任务 ×

检查面板是否正确创建定时任务。

情况 3:cron 有执行记录,但脚本失败

crond ✓
cron任务 ✓
脚本 ×

检查脚本、PATH、权限和依赖。

情况 4:数据库 .sql 能生成,但压缩包没有

数据库备份 ✓
tar/gzip ×

检查 tar、文件名、路径和压缩命令。

情况 5:手动成功,cron失败

手动执行 ✓
cron执行 ×

重点检查:

PATH
运行用户
当前目录
环境变量
绝对路径
权限
外部网络访问
IPv4/IPv6

十五、推荐的最短排查流程

遇到“SQL 自动备份失败”,实际可以先执行下面这组检查:

systemctl is-active crond
crontab -l
sudo crontab -l
ls -la /etc/cron.d/
grep -RniE "backup|mysqldump|mysql|sql" /etc/cron* /var/spool/cron 2>/dev/null
journalctl -u crond --since "1 hour ago" --no-pager

找到备份脚本后:

cd /脚本目录 && ./备份脚本
ls -lh /备份目录

如果手动执行成功,再检查:

which mysql mysqldump wget tar
cat /etc/my.cnf
ls -ld /备份目录

最后重点检查脚本中是否存在公网 IP 获取、IPv6、相对路径、PATH 和权限等环境依赖。

核心原则只有一个:

沿着“定时任务 → 脚本 → 数据库 → 压缩 → 文件”的实际执行链逐层验证,不要看到最终没有备份文件就直接判断是 MySQL 出问题。