特性:单库备份、压缩、保留 N 天自动清理过期备份、日志记录、锁文件防止并发、支持发送告警;兼容 MySQL5.7 / 8.0,MariaDB。 依赖:
mysqldump、gzip,建议安装。
1. 脚本 mysql_backup.sh
#!/bin/bash
set -euo pipefail
########################### 配置区,请修改这里 ###########################
# MySQL 连接信息
MYSQL_USER="root"
MYSQL_PASS="你的数据库密码"
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
# 需要备份的数据库名,多个空格分隔:DB1 DB2
DB_NAME="testdb"
# 备份存放目录
BACKUP_DIR="/data/mysql_backup"
# 备份文件保留天数
RETENTION_DAYS=7
# 日志文件
LOG_FILE="/var/log/mysql_backup.log"
# 锁文件,防止脚本重复运行
LOCK_FILE="/tmp/mysql_backup.lock"
###########################################################################
# trap:无论正常退出还是异常退出,都自动删除锁文件
trap 'rm -f ${LOCK_FILE}; echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 脚本退出,清理锁文件" >> ${LOG_FILE}' EXIT
# 判断锁文件是否存在
if [ -f "${LOCK_FILE}" ]; then
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 警告:备份任务正在运行,本次任务退出" >> ${LOG_FILE}
exit 1
fi
touch ${LOCK_FILE}
# 创建备份目录(不存在则新建)
mkdir -p ${BACKUP_DIR}
# 时间戳
TIME_STAMP=$(date +%Y%m%d_%H%M%S)
echo "==================== 开始备份 ${DB_NAME} ====================" >> ${LOG_FILE}
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 开始执行数据库备份" >> ${LOG_FILE}
# 循环备份每个库
for db in ${DB_NAME}; do
BACKUP_FILE="${BACKUP_DIR}/${db}_${TIME_STAMP}.sql.gz"
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 正在备份库:${db},文件:${BACKUP_FILE}" >> ${LOG_FILE}
# mysqldump 备份 + gzip压缩
mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} \
--single-transaction --quick --lock-tables=false ${db} | gzip > ${BACKUP_FILE}
# 判断备份是否成功
if [ $? -eq 0 ]; then
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] ${db} 备份成功" >> ${LOG_FILE}
else
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] ❌ ${db} 备份失败!" >> ${LOG_FILE}
exit 1
fi
done
# 删除超过保留天数的旧备份文件
find ${BACKUP_DIR} -name "*.sql.gz" -type f -mtime +${RETENTION_DAYS} -delete
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] 已清理${RETENTION_DAYS}天前的备份文件" >> ${LOG_FILE}
echo "[$(date +%Y-%m-%d\ %H:%M:%S)] ✅ 全部数据库备份任务完成" >> ${LOG_FILE}
echo "============================================================" >> ${LOG_FILE}
echo "" >> ${LOG_FILE}
exit 0
参数说明
--single-transaction:InnoDB 热备,不锁表(生产 InnoDB 必加)--lock-tables=false:关闭锁表,MyISAM 引擎不适合,MyISAM 建议去掉--single-transaction--quick:大表备份,减少内存占用
⚠️ 安全提示:脚本明文写密码有风险。更安全方案:在
~/.my.cnf写入账号密码,mysqldump 不再带-p参数。 示例 .my.cnf:
[mysqldump]
user=root
password=你的数据库密码
host=127.0.0.1
然后脚本里 mysqldump 去掉 -u -p -h 参数,chmod 600 ~/.my.cnf。
2. 赋予执行权限 & 手动测试
# 赋予执行权限
chmod +x mysql_backup.sh
# 手动运行测试
./mysql_backup.sh
# 调试模式,看每一步执行
bash -x mysql_backup.sh
# 查看日志
tail -f /var/log/mysql_backup.log
3. 配置 cron 定时任务(每天凌晨 2 点自动备份)
# 编辑当前用户定时任务
crontab -e
添加一行:
0 2 * * * /root/mysql_backup.sh >> /dev/null 2>&1
脚本内部已经自带日志输出到
/var/log/mysql_backup.log,所以 cron 这里不再重定向日志。
查看定时任务:
crontab -l
4. 备份恢复测试(重要!备份一定要验证能否恢复)
# 解压备份文件
gzip -d testdb_20260917_020000.sql.gz
# 恢复到数据库
mysql -uroot -p testdb < testdb_20260917_020000.sql
5. 可选增强:失败发送告警(企业微信 / 钉钉机器人)
在备份失败的 else 块内增加 curl 调用,例子(钉钉 webhook):
curl -s "https://oapi.dingtalk.com/robot/send?access_token=xxx" \
-H "Content-Type: application/json" \
-d '{"msgtype":"text","text":{"content":"MySQL数据库备份失败,请尽快检查!"}}'
6. 常见坑
cron 环境 PATH 问题:脚本里
mysqldump写全路径,用which mysqldump获取路径替换磁盘满:可以增加磁盘空间判断,备份前检查磁盘使用率
权限问题:备份目录、日志目录要确保脚本用户有写入权限
MySQL8.0:注意密码认证插件,如果 root 不能用密码登录,需要调整账号认证方式
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问