分享mysql数据库自动备份脚本(本机和docker都可用)
·
利用系统的定时任务周期性执行
备份mysql中的数据
备份策略:
最近30天(每天1份)
最近24小时(每小时1份)
关键点
DB_NAME: 备份的数据库名DB_USER: 数据库账号DB_PASS: 数据库密码
本地部署的mysql
DUMP: 本机mysqldump路径
使用mysqldump备份
$DUMP -u$DB_USER -p$DB_PASS $DB_NAME --default-character-set=utf8 --opt -Q -R ->-skip-lock-tables> $OUT_SQL
docker部署的mysql
DOCKER_CONTAINER: docker容器名
调用docker中的mysqldump备份
docker exec -i "$DOCKER_CONTAINER" mysqldump \ -u"$DB_USER" -p"$DB_PASS" \ --single-transaction \ --skip-lock-tables \ --no-tablespaces \ "$DB_NAME" > "$OUT_SQL"
下面是脚本源码
修改自己的数据库账号密码和备份路径
#!/bin/sh
DUMP=/usr/bin/mysqldump #mysqldump备份程序执行路径(方案A)
DOCKER_CONTAINER="mysql8" # MySQL 容器名称(方案B)
OUT_DIR=/home/developer/mysqlBak #备份文件存放路径
LINUX_USER=root #系统用户名
DB_NAME=user #要备份的数据库名字
DB_USER=mysql #数据库账号
DB_PASS='123456' #数据库密码
DAYS=30 #DAYS=30代表删除30天前的备份,即只保留最近30天的备份
cd $OUT_DIR #进入备份存放目录
DATE=`date +%Y_%m_%d_%H` #获取当前系统时间
OUT_SQL="$DATE.sql" #备份数据库的文件名
TAR_SQL="mysqldata_$DATE.tar.gz" #最终保存的数据库备份文件名
## 方案A: 下面这行是用本机的mysqldump来备份的
#$DUMP -u$DB_USER -p$DB_PASS $DB_NAME --default-character-set=utf8 --opt -Q -R --skip-lock-tables> $OUT_SQL #备份
## 方案B: 下面这行是通过docker exec的方式来备份
# 通过 docker exec 执行 mysqldump(安全方式)
docker exec -i "$DOCKER_CONTAINER" mysqldump \
-u"$DB_USER" -p"$DB_PASS" \
--single-transaction \
--skip-lock-tables \
--no-tablespaces \
"$DB_NAME" > "$OUT_SQL"
# 检查备份是否成功
if [ $? -ne 0 ]; then
echo "MySQL backup failed!"
rm -f "$OUT_SQL"
exit 1
fi
tar -czf $TAR_SQL ./$OUT_SQL #压缩为.tar.gz格式
rm $OUT_SQL #删除.sql格式的备份文件
# chown $LINUX_USER:$LINUX_USER $OUT_DIR/$TAR_SQL #更改备份数据库文件的所有者
# 获取所有备份文件的日期(去重) - 修复正则表达式匹配下划线格式
# 清理策略:保留当天所有备份 + 30天内每日最新备份
TODAY=$(date +%Y%m%d)
echo "开始清理备份,当天日期: $TODAY"
# 获取所有备份文件的日期(去重) - 修复正则表达式匹配下划线格式
dates=$(find "$OUT_DIR" -maxdepth 1 -name "mysqldata_*.tar.gz" -type f | \
sed -n 's/.*mysqldata_\([0-9]\{4\}\)_\([0-9]\{2\}\)_\([0-9]\{2\}\)_.*/\1\2\3/p' | sort -u)
echo "找到的备份日期: $dates"
# 对每个日期处理:非当天的每天只保留最新备份
for date in $dates; do
echo "处理日期: $date"
if [ "$date" = "$TODAY" ]; then
echo " 跳过当天备份: $date"
continue
fi
# 将YYYYMMDD格式转换为YYYY_MM_DD格式进行文件查找
year=$(echo $date | cut -c1-4)
month=$(echo $date | cut -c5-6)
day=$(echo $date | cut -c7-8)
date_pattern="${year}_${month}_${day}"
echo " 查找日期模式 $date_pattern 的所有备份文件..."
files_with_time=$(find "$OUT_DIR" -maxdepth 1 -name "mysqldata_${date_pattern}_*.tar.gz" -type f -printf "%T@ %p\n")
echo " 找到的文件: $files_with_time"
if [ -z "$files_with_time" ]; then
echo " 该日期没有备份文件"
continue
fi
# 统计文件数量
file_count=$(echo "$files_with_time" | wc -l)
echo " 该日期共有 $file_count 个备份文件"
if [ "$file_count" -gt 1 ]; then
echo " 开始删除旧备份,保留最新的..."
echo "$files_with_time" | sort -n | head -n -1 | while read -r timestamp file; do
if [ -n "$file" ]; then
echo " 删除文件: $file"
rm -v "$file"
else
echo " 文件路径为空,跳过"
fi
done
# 显示保留的文件
latest_file=$(echo "$files_with_time" | sort -n | tail -1 | awk '{print $2}')
echo " 保留最新备份: $latest_file"
else
echo " 该日期只有1个备份文件,无需清理"
fi
echo " ----"
done
echo "开始删除30天前的备份..."
old_files=$(find "$OUT_DIR" -name "mysqldata_*" -type f -mtime +$DAYS)
if [ -n "$old_files" ]; then
echo "30天前的备份文件:"
echo "$old_files"
find "$OUT_DIR" -name "mysqldata_*" -type f -mtime +$DAYS -exec rm -v {} \;
else
echo "没有找到30天前的备份文件"
fi
echo "备份清理完成"
更多推荐


所有评论(0)