crontab中mysqldump备份失败主因是环境隔离:不读~/.my.cnf、不继承path,且明文密码高危;应使用chmod 600的配置文件+全路径命令+--defaults-extra-file指定,并添加日志重定向、错误退出、压缩校验及按修改时间清理旧备份。

crontab 里 mysqldump 备份失败:常见报错 mysqldump: Got error: 1045: Access denied
根本原因不是密码写错了,而是 crontab 环境下不读取你的 ~/.my.cnf,也不继承 shell 的环境变量(比如 PATH)。直接在 crontab 里写 mysqldump -u root -p123456 ... 属于高危操作——密码会暴露在进程列表里,且大概率失败。
实操建议:
- 用配置文件方式授权:
mysqldump支持读取~/.my.cnf,但必须确保该文件权限是600(chmod 600 ~/.my.cnf),内容形如:
[client] user = backup_user password = your_secure_password
- crontab 中调用时显式指定配置文件:
mysqldump --defaults-extra-file=/home/backup/.my.cnf database_name > /backup/db_$(date +\%F).sql - 绝对路径必须写全:
mysqldump命令本身也得用全路径,比如/usr/bin/mysqldump,否则 cron 可能找不到
备份脚本中如何安全处理日期、压缩与保留策略
单纯生成 SQL 文件很快占满磁盘,且恢复时手动解压麻烦。关键是把「生成 → 压缩 → 清理」串成原子操作,避免中间文件残留或误删。
实操建议:
- 用
date格式化时注意 shell 特殊字符:$(date +\%Y\%m\%d)中的%必须转义,否则 cron 解析失败 - 压缩推荐
gzip而非zip:轻量、MySQL 社区通用,命令直接接管道:mysqldump ... | gzip > /backup/db_$(date +\%Y\%m\%d).sql.gz - 清理旧备份别用
rm -f /backup/*.sql.gz这种粗暴方式;改用find /backup -name "*.sql.gz" -mtime +7 -delete,精准按修改时间删 7 天前的
mysqldump 导出大库卡死或超时:关键参数要加
默认 mysqldump 对大表会一次性加载全量到内存,遇到百 GB 级数据库极易被 OOM kill 或触发 MySQL 的 wait_timeout 断连。
实操建议:
- 强制分块导出:
--single-transaction(InnoDB 必加,保证一致性) +--skip-lock-tables(避免锁表阻塞业务) - 控制内存压力:
--quick(逐行获取,不缓存整结果集) +--max-allowed-packet=256M(适配大字段,需和 MySQL 服务端配置一致) - 若仍失败,拆成单库甚至单表导出,用
mysql -Nse "show databases"动态生成命令,而非硬编码库名
备份脚本执行后没日志,出问题完全无从排查
crontab 默认静默运行,stdout/stderr 全丢弃。等发现备份空了、文件 0 字节、或者某天突然中断,已经晚了。
实操建议:
- 所有 cron 条目末尾加日志重定向:
> /var/log/mysql-backup.log 2>&1 - 在脚本开头加
set -e(出错立即退出)和set -x(打印每条执行命令),方便定位卡在哪一步 - 加简单校验:备份完用
gzip -t检查压缩包完整性,再用wc -l看 SQL 文件是否至少有 10 行(排除空文件)
最常被忽略的是 crontab 的 SHELL 环境和用户权限——同一个脚本,用 sudo crontab -u mysql 和 crontab -e(当前用户)跑,可能一个成功一个连 socket 都连不上。











