#!/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