164 lines
5.9 KiB
Bash
164 lines
5.9 KiB
Bash
#!/bin/bash
|
||
|
||
# ==============================================================================
|
||
# 数据库备份脚本
|
||
# 功能:
|
||
# 1. 备份指定数据库中的多个表。
|
||
# 2. 每天定时运行时,支持滚动备份:
|
||
# - 删除前两天的备份表(后缀 _bak)。
|
||
# - 将前一天的备份表更名为带着 _bak 后缀的表。
|
||
# - 备份今天的表。
|
||
# 3. 表名列表从文件中读取。
|
||
# ==============================================================================
|
||
|
||
# --- 配置区 START ---
|
||
|
||
# 源数据库连接信息 (mysql5.7)
|
||
DUMP_HOST="172.16.20.39"
|
||
DUMP_PORT="23306"
|
||
DUMP_USER="iflyreadonly"
|
||
DUMP_PASSWORD="davwXJk8_m5mWUNg"
|
||
|
||
# 目标数据库连接信息 (mysql8)
|
||
RESTORE_HOST="localhost"
|
||
RESTORE_PORT="3306"
|
||
RESTORE_USER="root"
|
||
RESTORE_PASSWORD="1qaz@WSX"
|
||
|
||
DATABASE="exchange_data_local" # 数据库名称,源和目标数据库相同
|
||
|
||
# 备份的where条件,所有表都使用这个条件
|
||
WHERE_CONDITION="school_id='1010000001000020417'"
|
||
|
||
# !!! 新增配置 !!!
|
||
# 存储表名的文件路径,每行一个表名
|
||
TABLE_LIST_FILE="./table_list.txt"
|
||
|
||
# 日志文件路径
|
||
LOG_FILE=".db_backup_$(date +%Y%m%d).log"
|
||
|
||
# 其他 mysqldump 选项
|
||
MYSQLDUMP_OPTIONS="--single-transaction --set-gtid-purged=OFF --column-statistics=0 --databases ${DATABASE}"
|
||
|
||
# --- 配置区 END ---
|
||
|
||
# 检查表列表文件是否存在
|
||
if [ ! -f "$TABLE_LIST_FILE" ]; then
|
||
echo "错误:表列表文件 '${TABLE_LIST_FILE}' 不存在!"
|
||
echo "请创建该文件并在其中列出要备份的表名,每行一个。"
|
||
exit 1
|
||
fi
|
||
|
||
# 将STDOUT和STDERR重定向到日志文件
|
||
exec > >(tee -a "$LOG_FILE") 2>&1
|
||
|
||
echo "================================================================================="
|
||
echo "数据库备份脚本开始运行于:$(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================================="
|
||
|
||
# 获取当前日期(YYYYMMDD)
|
||
TODAY=$(date +%Y%m%d)
|
||
# 获取昨天日期(YYYYMMDD)
|
||
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
|
||
# 获取前天日期(YYYYMMDD)
|
||
DAY_BEFORE_YESTERDAY=$(date -d "2 days ago" +%Y%m%d)
|
||
|
||
echo "当前日期:${TODAY}"
|
||
echo "昨天日期:${YESTERDAY}"
|
||
echo "前天日期:${DAY_BEFORE_YESTERDAY}"
|
||
|
||
# 从文件中读取表名列表
|
||
# 使用 IFS 和 while read 循环来处理每行,跳过空行和注释行
|
||
echo "正在从文件 '${TABLE_LIST_FILE}' 读取表名..."
|
||
TABLES=()
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
# 移除行首尾空格
|
||
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||
# 跳过空行和以 # 开头的注释行
|
||
if [[ -n "$line" && ! "$line" =~ ^# ]]; then
|
||
TABLES+=("$line")
|
||
fi
|
||
done < "$TABLE_LIST_FILE"
|
||
|
||
if [ ${#TABLES[@]} -eq 0 ]; then
|
||
echo "警告:表列表文件 '${TABLE_LIST_FILE}' 中没有找到有效的表名。"
|
||
echo "请确保文件中有表名,并且每行一个。"
|
||
exit 0 # 没有表可备份,直接退出
|
||
fi
|
||
echo "=====找到了 ${#TABLES[@]} 个表等待备份。====="
|
||
echo "=====开始备份作业====="
|
||
sleep 2
|
||
|
||
# 遍历每个表进行备份
|
||
for TABLE in "${TABLES[@]}"; do
|
||
echo "---------------------------------------------------------------------------------"
|
||
echo "开始处理表:${TABLE}"
|
||
|
||
# 定义目标表名
|
||
TARGET_TABLE="${TABLE}"
|
||
YESTERDAY_BACKUP_TABLE="${TABLE}_bak"
|
||
|
||
# 0. 删除_bak表;
|
||
|
||
echo "删除之前备份的表: ${TABLE}_bak"
|
||
mysql -u${RESTORE_USER} -p${RESTORE_PASSWORD} ${DATABASE} -e "DROP TABLE IF EXISTS \`${TABLE}_bak\`;"
|
||
if [ $? -eq 0 ]; then
|
||
echo "成功删除表:${YESTERDAY_BACKUP_TABLE}"
|
||
else
|
||
echo "删除表失败或表不存在:${YESTERDAY_BACKUP_TABLE}"
|
||
fi
|
||
# 1. 将昨天的备份表重命名为带有 _bak 后缀的表
|
||
echo "尝试将昨天的备份表更名为:${TABLE}_bak"
|
||
|
||
count=$(mysql -u${RESTORE_USER} -p${RESTORE_PASSWORD} ${DATABASE} -sN -e "SELECT count(*) FROM information_schema.TABLES WHERE TABLE_NAME = '${TABLE}';")
|
||
|
||
if [ "$count" -gt 0 ]; then
|
||
mysql -u${RESTORE_USER} -p${RESTORE_PASSWORD} ${DATABASE} -e "RENAME TABLE \`${TABLE}\` TO \`${YESTERDAY_BACKUP_TABLE}\`;"
|
||
if [ $? -eq 0 ]; then
|
||
echo "成功重命名表:${TABLE} 为 ${YESTERDAY_BACKUP_TABLE}"
|
||
else
|
||
echo "重命名表失败或昨天备份表不存在:${TABLE}"
|
||
fi
|
||
else
|
||
echo "Table ${TABLE} does not exist or count is 0."
|
||
fi
|
||
|
||
# 3. 执行 mysqldump 备份今天的表
|
||
echo "尝试备份表:${TABLE} 到 ${TARGET_TABLE}"
|
||
|
||
DUMP_COMMAND="mysqldump -h${DUMP_HOST} -P${DUMP_PORT} -u${DUMP_USER} -p${DUMP_PASSWORD} ${MYSQLDUMP_OPTIONS} --tables ${TABLE} --where=${WHERE_CONDITION}"
|
||
RESTORE_COMMAND="mysql -u${RESTORE_USER} -p${RESTORE_PASSWORD} ${DATABASE}"
|
||
|
||
# 先删除目标表(如果存在),确保清空
|
||
echo "删除旧的今日目标表 (如果存在):${TABLE}"
|
||
mysql -u${RESTORE_USER} -p${RESTORE_PASSWORD} ${DATABASE} -e "DROP TABLE IF EXISTS \`${TABLE}\`;"
|
||
if [ $? -ne 0 ]; then
|
||
echo "警告:删除旧的今日目标表 ${TABLE} 失败!继续备份,但可能存在问题。"
|
||
fi
|
||
|
||
# 执行备份和导入,并捕获错误
|
||
echo "导出到本地文件 ${TABLE}.sql "
|
||
# ${DUMP_COMMAND} | ${RESTORE_COMMAND}
|
||
${DUMP_COMMAND} > ${TABLE}.sql # 先导出到文件
|
||
|
||
sleep 1
|
||
echo "从本地文件 ${TABLE}.sql 导入。"
|
||
${RESTORE_COMMAND} < ${TABLE}.sql # 再把文件导入
|
||
if [ $? -eq 0 ]; then
|
||
echo "成功备份表:${TABLE}"
|
||
else
|
||
echo "备份表失败:${TABLE}"
|
||
echo "请检查错误信息,可能是 mysqldump 或 mysql 命令执行失败。"
|
||
# 可以选择在这里退出脚本,或者继续处理下一个表
|
||
# exit 1
|
||
fi
|
||
|
||
echo "完成处理表:${TABLE}"
|
||
sleep 1
|
||
done
|
||
|
||
echo "================================================================================="
|
||
echo "所有表备份完成于:$(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo "================================================================================="
|
||
|
||
exit 0 |