mysqldump安全导出压缩需禁用明文密码(用~/.my.cnf配置文件)、加--single-transaction、绝对路径调用命令、重定向stderr日志、定时任务显式声明path、上传oss前校验、按实际时间清理旧备份并确保系统时钟同步。

mysqldump 是核心工具,但光靠它导出 SQL 文件远远不够——没压缩会吃光磁盘,没清理会堆积失效备份,没日志根本不知道哪次失败了。直接写个“能跑就行”的脚本,在生产环境撑不过三天。
如何用 mysqldump 安全导出并压缩数据库
明文密码写在命令行里(如 mysqldump -u root -p123456 db_name)会被 ps 看到,也留在 shell 历史中,非常危险。必须改用配置文件方式:
- 创建
~/.my.cnf,权限设为600:[client] user = backup_user password = your_secure_password host = localhost
- 导出时省略用户名密码,只写:
mysqldump --databases db1 db2 | gzip > /backup/db_$(date +%Y%m%d_%H%M%S).sql.gz - 加
--single-transaction(InnoDB 表)或--lock-tables=false(避免锁库阻塞业务) - 不推荐用
-p后紧跟密码;也不要用环境变量传密码,mysqldump不读取MYSQL_PWD(已弃用且不安全)
crontab 定时执行的几个硬坑
crontab -e 编辑的脚本默认没有用户环境变量(比如 PATH),mysqldump 找不到、gzip 报 command not found 是最常见报错。
- 在 crontab 条目开头显式声明 PATH:
PATH=/usr/local/bin:/usr/bin:/bin - 所有命令写绝对路径:用
/usr/bin/mysqldump而不是mysqldump - 重定向 stderr 到日志,否则失败无声:
2>> /var/log/mysql-backup.log - 示例条目(每天凌晨 2:15 执行):
15 2 * * * PATH=/usr/local/bin:/usr/bin:/bin /backup/backup.sh >> /var/log/mysql-backup.log 2>&1
上传到阿里云 OSS 的最小可行方案
不用 Python SDK 或复杂封装,ossutil64 命令行工具足够轻量稳定。
- 先安装:
curl https://gosspublic.alicdn.com/ossutil/install.sh | sudo bash - 配置凭据:
ossutil64 config -e oss-cn-hangzhou.aliyuncs.com -i your_access_key_id -k your_access_key_secret - 上传前确保本地备份文件存在,用
test -f "$file"判断,避免空文件上传 - 上传命令加
--update参数可跳过已存在且大小时间一致的文件,减少重复流量 - 上传后校验:
ossutil64 head oss://your-bucket/$filename | grep "Content-Length",确认非零
自动清理旧备份的关键逻辑
find /backup -name "*.sql.gz" -mtime +7 -delete 看似简洁,但 -mtime +7 指“修改时间超过 7×24 小时”,不是“7 天前的文件”——如果某次备份卡在 23:59,第二天 00:01 才完成,它可能被提前删掉。
- 更稳妥的做法是按文件名日期解析:
find /backup -name "db_????????_*.sql.gz" | while read f; do basename "$f" | grep -q "$(date -d '7 days ago' +%Y%m%d)" || rm "$f"; done - 或者用
stat -c '%y %n' /backup/*.sql.gz | sort | head -n -7 | cut -d' ' -f6- | xargs -r rm(按实际修改时间倒序取前 N 个保留) - 删除前务必
echo出要删的文件列表,调试阶段注释掉rm,确认无误再放开
真正容易被忽略的是时间同步和时区。服务器若未启用 ntpd 或 chronyd,date 命令生成的时间戳会漂移,导致 crontab 时间不准、备份文件名错乱、find -mtime 判定失准。2026 年多数发行版默认启用 chronyd,但老系统或容器环境仍需手动检查:timedatectl status 中的 “System clock synchronized: yes” 必须为 true。











