目录

[TOC]

数据备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/bin/bash

# 数据库信息【根据需要修改】
DB_USER="root"
DB_PASS="root"
# 替换成 mysql-master节点IP【必须修改】
DB_IP="127.0.0.1"
DB_PORT="3306"

# 备份文件路径【根据需要修改】
BAK_PATH="/mysql_bak/bak/"

# 运行的MySQL容器名称【根据需要修改】
CONTAINER_NAME="k8s_mysql"

# 远程备份相关信息【根据需要修改】
REMOTE_BACKUP_ENABLED=false # 设置为 true 启用远程备份
REMOTE_USER="root"
REMOTE_IP="远程服务器ip" # 替换为实际的远程服务器 IP 地址
REMOTE_PATH="远程备份路径" # 远程备份文件存放路径

# 备份的文件及文件存放文件夹的名称【根据需要修改】
BACKUP_FILE_NAME="mysql-$(date +"%Y%m%d")"

# 不需要备份的数据库【根据需要修改】
IGNORE_DATABASES=("Database" "mysql" "performance_schema" "information_schema" "sys")

# 不需要备份的表【根据需要修改】
IGNORE_TABLES=("IGNORE_TABLES1" "IGNORE_TABLES2")

# 备份文件完整路径【不修改】
BACKUP_FOLDER="${BAK_PATH}${BACKUP_FILE_NAME}"
# 备份文件完整名称【不修改】
BACKUP_FILE="${BACKUP_FILE_NAME}.tar.gz"

# 文件保存几天
SAVE_DAYS=7

# 记录备份开始时间的时间戳
START_TIME=$(date +"%s")

# 创建文件夹函数
create_folder() {
local folder=$1
if [ ! -d "$folder" ]; then
mkdir -p "$folder"
echo -e "\n$folder 文件夹已创建"
else
echo -e "\n$folder 文件夹已存在"
fi
}

# 备份数据库函数
backup_database() {
local database=$1
local ignore_tables_str=""

for table in "${IGNORE_TABLES[@]}"; do
ignore_tables_str+=" --ignore-table=${database}.${table}"
done

docker exec -i $(docker ps | grep $CONTAINER_NAME | awk 'NR==1 {print $1}') mysqldump -h $DB_IP -P $DB_PORT -u $DB_USER -p$DB_PASS --single-transaction --quick --databases $database $ignore_tables_str $database > "${BACKUP_FOLDER}/${database}.sql"
echo -e "\n备份 $database 数据库完成"
}

# 远程备份函数
remote_backup() {
# 判断是否启用远程备份
if [ "$REMOTE_BACKUP_ENABLED" = true ]; then
echo -e "\n开始远程备份中......"

# 执行远程备份
if scp "$BACKUP_FILE" "${REMOTE_USER}@${REMOTE_IP}:${REMOTE_PATH}"; then
# 远程备份成功,删除本地备份文件
rm -f "$BACKUP_FILE"
echo -e "远程备份完毕!"
else
# 远程备份失败,输出错误信息
echo -e "远程备份失败!"
fi
else
echo -e "\n远程备份未启用。"
fi
}

# 清理本地备份文件函数
clean_local_backup() {
echo -e "\n开始清理${SAVE_DAYS}天以外的备份文件......"

# 获取文件夹下的文件数量
file_count=$(find "$BAK_PATH" -maxdepth 1 -type f | wc -l)

if [ "$file_count" -ge "${SAVE_DAYS}" ]; then
# 文件数量足够,进行删除操作
find "$BAK_PATH" -type f -mtime +${SAVE_DAYS} -exec rm {} \;
echo -e "\n备份文件清理完成"
else
echo -e "\n文件数量不足 ${SAVE_DAYS} 个 / 没有${SAVE_DAYS}天以外的文件,不进行删除"
fi
}


# 创建文件夹(递归创建)
create_folder "$BAK_PATH"
create_folder "$BACKUP_FOLDER"

echo -e "\n开始备份数据库......\n"

for database in $(docker exec -i $(docker ps | grep $CONTAINER_NAME | awk 'NR==1 {print $1}') mysql -h $DB_IP -P $DB_PORT -u $DB_USER -p$DB_PASS -e "SHOW DATABASES;" | grep -Ev "($(IFS=\|; echo "${IGNORE_DATABASES[*]}"))"); do
backup_database "$database"
done

echo -e "\n数据库备份完成."

# 记录mysqldump时间
MYSQLDUMP_TIME=$(date +"%s")
MYSQLDUMP_DIFF=$((MYSQLDUMP_TIME - START_TIME))
echo -e "\nmysqldump备份耗时: $((MYSQLDUMP_DIFF / 3600)) 小时 $(((MYSQLDUMP_DIFF % 3600) / 60)) 分钟 $((MYSQLDUMP_DIFF % 60)) 秒"

# 压缩备份文件夹
echo -e "\n开始压缩备份文件夹......"
cd "$BAK_PATH"
tar -zcvf "$BACKUP_FILE" "$BACKUP_FILE_NAME"
echo -e "\n备份文件夹压缩完成."

# 远程备份
remote_backup

# 删除临时备份文件夹
echo -e "\n删除临时备份文件夹......"
rm -rf "$BACKUP_FOLDER"
echo -e "\n临时备份文件夹删除完成."

# 清理本地备份文件
clean_local_backup

# 记录备份结束时间的时间戳
END_TIME=$(date +"%s")

# 计算时间差值
TIME_DIFF=$((END_TIME - START_TIME))
echo -e "\n总备份耗时: $((TIME_DIFF / 3600)) 小时 $(((TIME_DIFF % 3600) / 60)) 分钟 $((TIME_DIFF % 60)) 秒\n"

数据恢复

1
vi recover.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash

# 数据库信息
DB_USER="root"
DB_PASS="root"
DB_IP="127.0.0.1"
DB_PORT="3306"
BACKUP_FILE_NAME="mysql-$(date +"%Y%m%d")"

# 运行的MySQL容器名称【根据需要修改】
CONTAINER_NAME="mysql"

# 记录恢复开始时间的时间戳
START_TIME=$(date +"%s")

# 解压备份文件夹
echo -e "\n开始解压备份文件夹......"
tar -zxvf $BACKUP_FILE_NAME.tar.gz
echo -e "\n备份文件夹解压完成."

# 执行SQL命令
echo -e "\n开始执行SQL文件......"
for sql_file in $BACKUP_FILE_NAME/*.sql; do
if [ -f "$sql_file" ]; then
database=$(basename "$sql_file" .sql)
echo -e "\n执行 $database 数据库的SQL文件......"
docker exec -i $(docker ps | grep $CONTAINER_NAME | awk 'NR==1 {print $1}') mysql -h $DB_IP -P $DB_PORT -u $DB_USER -p$DB_PASS < "$sql_file"
fi
done
echo "SQL文件执行完成."

echo -e "\n脚本执行完成."

# 记录恢复结束时间的时间戳
END_TIME=$(date +"%s")

# 计算时间差值
TIME_DIFF=$((END_TIME - START_TIME))
echo -e "\n恢复耗时: $((TIME_DIFF / 3600)) 小时 $(((TIME_DIFF % 3600) / 60)) 分钟 $((TIME_DIFF % 60)) 秒"
1
chmod +x recover.sh&&sh recover.sh

设置定时任务

1
2
3
4
crontab -e

0 21 * * * sh /mysql/mysql_bak.sh >> /mysql/mysql_bak.log 2>&1 &

‍‍

清理七天以外的文件

如果文件备份到远程服务器上,需要将该脚本放到远程服务器上,用于定时清理数据

1
2
3
4
5
6
#!/bin/bash
BAK_PATH="/mysql/bak/"
# 清理七天以外的备份文件
echo -e "\n开始清理七天以外的备份文件......"
find $BAK_PATH -type f -mtime +7 -exec rm {} \;
echo -e "备份文件清理完成\n"

设置ssh免登录

1
2
3
4
5
# 查看公钥信息【数据库所在服务器】
cat ~/.ssh/id_rsa.pub

# 将查看的信息存入远程免登录认证文件中
echo "上面看到的信息" >> ~/.ssh/authorized_keys