能跑通的自动备份脚本关键在三处:mysqldump必须加--single-transaction确保innodb一致性快照,crontab需显式指定--defaults-extra-file路径且~/.my.cnf权限为600,脚本必须检查mysqldump退出码并校验gzip文件。

直接上结论:能跑通的自动备份脚本,核心不在“写得多全”,而在「mysqldump参数对不对」「crontab环境能不能读到密码」「退出码有没有被检查」这三处。漏掉任一,备份就可能静默失败。
mysqldump 必须加 --single-transaction 才算安全
不加这个参数,InnoDB 表在备份过程中遇到写入,导出的数据可能跨事务不一致——比如用户表更新了但订单明细没跟上,恢复后数据逻辑就断了。
-
--single-transaction会启动一个一致性快照,全程不锁表,只对 InnoDB 有效 - 如果库混用 MyISAM(比如老系统),得先确认引擎:
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db'; - 务必顺手加上
--routines(导出存储过程)、--triggers(导出触发器)、--events(导出事件),否则这些对象不会进备份文件 - MySQL 5.7.6+ 默认开启 GTID,备份时得显式加
--set-gtid-purged=OFF,否则恢复时报错ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty
crontab 脚本里不能靠 ~/.my.cnf 自动读密码
因为 cron 不加载 shell 的 profile 或 bashrc,~/.my.cnf 默认路径会解析成 cron daemon 的 home(通常是 /root),但如果你把配置放自己用户家目录下,它根本找不到。
- 要么显式指定配置文件路径:
mysqldump --defaults-extra-file=/root/.my.cnf --single-transaction your_db > file.sql - 要么所有命令用绝对路径,并在脚本开头重设 PATH:
export PATH="/usr/bin:/bin:/usr/local/mysql/bin" - 密码绝不能明文写在脚本里;
/root/.my.cnf权限必须是600,内容格式为:[client] user=root password=your_real_password
- 测试方式:用
sudo -u root /bin/bash -c 'mysqldump --defaults-extra-file=/root/.my.cnf -e "SELECT 1"'模拟 cron 环境
备份脚本必须检查 mysqldump 退出码再往下走
常见错误是 mysqldump 因权限/连接/磁盘满失败,却生成了一个空 .sql 文件,后续 gzip 和 find 清理照常执行,你看到日志里“backup success”就信了——其实是个空壳。
- 简单判断:
mysqldump --defaults-extra-file=/root/.my.cnf --single-transaction your_db | gzip > /backup/your_db_$(date +\%Y\%m\%d_\%H\%M).sql.gz if [ $? -ne 0 ]; then logger -t mysql-backup "mysqldump failed at $(date)" exit 1 fi
- 压缩完建议校验:
gzip -t /backup/your_db_*.sql.gz,防止管道中断导致损坏 - 日志别只 echo 到终端,用
logger -t mysql-backup写进系统日志,crontab 默认不保留 stdout/stderr - 备份前加空间检查:
df /backup | awk 'NR==2 {print $5}' | sed 's/%//' | awk '$1 > 90 {exit 1}',超 90% 就跳过并报警
crontab 时间格式和权限最容易写错
写成 2 0 * * * 是每月 2 号 0 点,不是每天 2 点;写成 0 2 * * 1 是每周一 2 点,但如果又写了 0 2 1 * *,那每月 1 号也会触发——cron 是“或”逻辑,不是“且”。
- 每天凌晨 2 点正确写法:
0 2 * * *(分、时、日、月、周) - 编辑 root 级任务必须用:
sudo crontab -e,普通crontab -e编辑的是当前用户,没权限读 MySQL 配置、写/backup - 脚本第一行必须是
#!/bin/bash,且赋予执行权限:chmod +x /backup/mysql_backup.sh - 时间字段里不要同时填“日”和“周”,例如
0 2 1 * 1会导致每月 1 号 + 每周一都执行
真正难的不是写几行脚本,而是让整个链路每一步都可验证:从 mysqldump 是否真拿到了快照,到 cron 是否真用了你给的环境变量,再到压缩文件是否真能 gzip -t 过。任何一环静默失效,你都不会立刻知道。











