最轻量可控的mysql自动备份方案是mysqldump+crontab;须用~/.my.cnf存密(权限600),必加--single-transaction、--routines、--triggers、--events,crontab需指定shell和path,备份文件名含时间戳并压缩,配合find清理旧文件。

mysqldump 和 crontab 是 Linux 下实现 MySQL 自动备份最轻量、最可控的组合。不需要额外服务或 GUI 工具,只要 MySQL 本身可运行、mysqldump 命令可用,就能快速落地。
确认 mysqldump 可用且权限正确
mysqldump 必须能连上数据库并导出数据,否则脚本一执行就失败,但错误可能被 crontab 静默吞掉。
先手动运行测试:
mysqldump -u root -p'your_password' --all-databases | head -20
如果报错Access denied或Can't connect to local MySQL server,说明用户权限或 socket 路径不对。-
常见权限问题:
- MySQL 8.0+ 默认禁用密码明文传参,会警告
Using a password on the command line interface can be insecure,虽不影响执行,但建议用~/.my.cnf配置凭据 - 创建
/root/.my.cnf(仅 root 可读):[client] user = root password = YourSecurePass123 host = localhost
- 然后改用无密码参数调用:
mysqldump --all-databases > backup.sql
- MySQL 8.0+ 默认禁用密码明文传参,会警告
注意:如果 MySQL 不在默认 socket 路径(如
/var/lib/mysql/mysql.sock),mysqldump可能连不上。可在.my.cnf中加一行:socket = /path/to/mysql.sock
写一个带容错和日志的备份脚本
纯 dump + gzip 不够健壮。生产环境需要判断成功与否、记录时间、清理旧文件、避免空文件堆积。
-
脚本要点(保存为
/usr/local/bin/mysql-backup.sh):- 开头必须有
#!/bin/bash,且 crontab 执行时不会加载用户环境,所以路径要写全(如/usr/bin/mysqldump) - 用
set -e让任意命令失败即退出,避免后续误操作 - 备份文件名含日期+时间,避免同秒多次触发冲突:
$(date +\%Y\%m\%d_\%H\%M\%S) - dump 后立即检查文件大小:
if [ ! -s "$file" ]; then echo "empty dump"; exit 1; fi - 用
gzip压缩前先确认gzip存在,否则 fallback 到不压缩
- 开头必须有
-
示例片段:
#!/bin/bash set -e BACKUP_DIR="/backup/mysql" DATE=$(date +\%Y\%m\%d_\%H\%M\%S) FILE="$BACKUP_DIR/full_$DATE.sql" LOG="$BACKUP_DIR/backup.log"
echo "[$(date)] START" >> $LOG /usr/bin/mysqldump --all-databases --single-transaction --routines --triggers > "$FILE" if [ ! -s "$FILE" ]; then echo "[$(date)] ERROR: empty dump" >> $LOG rm -f "$FILE" exit 1 fi gzip "$FILE" echo "[$(date)] DONE: $(basename $FILE).gz" >> $LOG
crontab 定时任务必须指定 SHELL 和 PATH
直接 crontab -e 编辑,但很多人忽略两点:
cron 默认
SHELL=/bin/sh,不支持$(date)这类 bash 特性cron 的
PATH极简(通常只有/usr/bin:/bin),mysqldump若装在/usr/local/mysql/bin就找不到-
正确写法(在 crontab 文件顶部添加):
SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 2 * * * /usr/local/bin/mysql-backup.sh
验证 cron 是否生效:
sudo systemctl status crond(CentOS/RHEL)或sudo systemctl status cron(Ubuntu/Debian)
查看日志:sudo tail -f /var/log/cron或journalctl -u cron -n 20切勿把密码写在 crontab 行里 —— 会被
ps aux暴露。务必用.my.cnf或环境变量封装。
清理旧备份不能只靠 mtime,得防空文件和命名混乱
find ... -mtime +7 -delete 看似简单,但实际容易出问题:
-mtime按“24 小时整数倍”计算,不是按日历日。比如今天 15:00 备份,明天 14:59 执行 find,-mtime +0就匹配不到它如果脚本某次失败生成了 0 字节
.sql.gz,-mtime照样保留,占空间还误导人备份文件若被手动改名(如加了
_bak),find -name "*.sql.gz"就漏删-
更稳妥的做法:
- 统一用
date +%Y%m%d命名,再用find ... -name "full_????????.sql.gz" -mtime +7 - 加一层校验:只删那些真正是 gzip 格式的文件:
file "$f" | grep -q "gzip compressed" - 清理逻辑单独写成函数,和备份脚本解耦,也方便手动触发
- 统一用
最关键的是:备份脚本里别写清理逻辑。cron 单独起一条规则跑清理,职责分离,出问题好排查。
时间精度、权限隔离、路径硬编码、空文件残留——这些地方不细抠,自动备份就只是“看起来在跑”,而不是“真能救数据”。











