MySQL备份恢复
MySQL备份恢复
Percona XtraBackup
下载安装
https://www.percona.com/downloads#percona-xtrabackup
全量备份
1
xtrabackup --backup --target-dir=/data/mysql_backup/base -uroot -p'HelloWorld@123' -H localhost -P 3306
增量备份
指定基础目录后进行增量备份,一般为嵌套的模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 准备基础备份(如果未执行过)
xtrabackup --prepare --apply-log-only --target-dir=/data/mysql_backup/base
# 2. 准备第一个增量备份(increment1)
xtrabackup --prepare --apply-log-only \
--target-dir=/data/mysql_backup/base \
--incremental-dir=/data/mysql_backup/increment1
# 3. 创建第二个增量备份(increment2)
xtrabackup --backup \
--target-dir=/data/mysql_backup/increment2 \
--incremental-basedir=/data/mysql_backup/increment1 \
--user=root \
--password-file=/root/mysql_password.txt \
--host=localhost \
--port=3306
增量备份恢复
准备基础备份(仅应用日志)
1
xtrabackup --prepare --apply-log-only --target-dir=/data/mysql_backup/base
合并第一个增量备份(仅应用日志)
1
2
3
xtrabackup --prepare --apply-log-only \
--target-dir=/data/mysql_backup/base \
--incremental-dir=/data/mysql_backup/increment1
合并第二个增量备份(最后一次,完整prepare!)
1
2
3
xtrabackup --prepare \ # 注意:这里没有 --apply-log-only!
--target-dir=/data/mysql_backup/base \
--incremental-dir=/data/mysql_backup/increment2
恢复数据到MySQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 停止MySQL
systemctl stop mysqld
# 清空数据目录(谨慎操作)
mv /var/lib/mysql /var/lib/mysql.bak # 建议先备份原数据
mkdir /var/lib/mysql
# 复制备份文件
xtrabackup --copy-back --target-dir=/data/mysql_backup/base
# 设置权限
chown -R mysql:mysql /var/lib/mysql
# 启动MySQL
systemctl start mysqld
为什么前几次增量恢复使用
--apply-log-only
?目的:仅合并数据,不提交事务
增量备份本身只包含 数据页的变化,而不是完整的事务日志。
--apply-log-only
的作用是:仅应用增量备份的数据变更,但不执行事务提交(避免产生不一致状态)。不执行崩溃恢复(crash recovery),因为后续可能还有更多的增量备份要应用。
差异备份就是基于全量备份和最后一次。
压缩备份需要安装qpress软件,使用–compress参数,准备数据之前使用–decompress参数解压。
mysqldump
基本用法
1
mysqldump -u [用户名] -p[密码] [数据库名] > [输出文件.sql]
常用选项
-u
指定用户名-p
提示输入密码(不要在命令中直接写密码)--databases
备份多个数据库--all-databases
备份所有数据库--no-data
只导出结构,不导出数据--add-drop-table
在每张表前添加 DROP TABLE 语句--skip-lock-tables
不锁定表(适用于大型数据库)
示例
备份单个数据库:
1
mysqldump -u root -p mydatabase > backup.sql
备份多个数据库:
1
mysqldump -u root -p --databases db1 db2 db3 > backup.sql
只备份表结构:
1
mysqldump -u root -p --no-data mydatabase > structure.sql
从备份恢复:
1
mysql -u root -p mydatabase < backup.sql
在binlog中记录了在开始备份后出现的变动:
使用命令将其恢复:
1
mysqlbinlog /var/lib/mysql/binlog.000014 --start-position=158 | mysql -uroot -p'HelloWorld@123'
这样就可以保证数据的一致性。
记录导出
1
mysql -uroot -p'HelloWorld@123' masterke -e 'select * from masterke' --html > 1.txt
数据库备份案例
分解
环境配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CONTAINER_NAME="yudao-mysql"
# 数据库配置
DB_HOST="localhost"
DB_USER=""
DB_PASSWORD=""
DB_NAME=""
# 本地备份文件存储路径
LOCAL_BACKUP_PATH="/app/backup"
# 远程服务器配置
REMOTE_HOST=""
REMOTE_USER="root"
REMOTE_PATH="/app/backup"
备份文件命名
1
2
3
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
BACKUP_FILE_NAME="${DB_NAME}_${TIMESTAMP}.sql"
LOCAL_BACKUP_FILE_PATH="${LOCAL_BACKUP_PATH}/${BACKUP_FILE_NAME}"
创建本地备份目录
1
mkdir -p "${LOCAL_BACKUP_PATH}"
执行备份命令
1
2
DUMP_CMD="mysqldump -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME}"
docker exec "${CONTAINER_NAME}" ${DUMP_CMD} > "${LOCAL_BACKUP_FILE_PATH}"
备份结果检查与远程传输
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if [ $? -eq 0 ]; then
echo "Backup successfully created: ${LOCAL_BACKUP_FILE_PATH}"
scp "${LOCAL_BACKUP_FILE_PATH}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}"
if [ $? -eq 0 ]; then
echo "Backup successfully transferred to ${REMOTE_HOST}:${REMOTE_PATH}"
rm "${LOCAL_BACKUP_FILE_PATH}"
echo "Local backup file deleted: ${LOCAL_BACKUP_FILE_PATH}"
else
echo "Failed to transfer backup to remote server."
fi
else
echo "An error occurred during the backup process."
fi
使用crontab配置定时任务:
1
2
3
4
5
# 编辑crontab配置
crontab -e
# 添加定时任务,例如每天凌晨1点执行
0 1 * * * /path/to/your/script.sh
使用Jenkins配置定时任务:
- 创建新任务:在Jenkins中创建一个新的定时构建任务。
- 配置定时触发:设置任务的触发时间。
- 执行脚本:在构建步骤中添加执行脚本的命令。
源代码
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
#!/bin/bash
CONTAINER_NAME="yudao-mysql"
# 数据库配置
DB_HOST="localhost"
DB_USER=""
DB_PASSWORD=""
DB_NAME=""
# 本地备份文件存储路径
LOCAL_BACKUP_PATH="/app/backup"
# 远程服务器配置
REMOTE_HOST=""
REMOTE_USER="root"
REMOTE_PATH="/app/backup"
# 生成备份文件名
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
BACKUP_FILE_NAME="${DB_NAME}_${TIMESTAMP}.sql"
LOCAL_BACKUP_FILE_PATH="${LOCAL_BACKUP_PATH}/${BACKUP_FILE_NAME}"
# 创建本地备份目录(如果不存在)
mkdir -p "${LOCAL_BACKUP_PATH}"
# 构建mysqldump命令
DUMP_CMD="mysqldump -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME}"
# 在Docker容器中执行mysqldump命令并导出备份文件
docker exec "${CONTAINER_NAME}" ${DUMP_CMD} > "${LOCAL_BACKUP_FILE_PATH}"
# 检查命令执行结果
if [ $? -eq 0 ]; then
echo "Backup successfully created: ${LOCAL_BACKUP_FILE_PATH}"
# 通过SSH将备份文件传输到远程服务器
scp "${LOCAL_BACKUP_FILE_PATH}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}"
if [ $? -eq 0 ]; then
echo "Backup successfully transferred to ${REMOTE_HOST}:${REMOTE_PATH}"
# 可选:删除本地备份文件
rm "${LOCAL_BACKUP_FILE_PATH}"
echo "Local backup file deleted: ${LOCAL_BACKUP_FILE_PATH}"
else
echo "Failed to transfer backup to remote server."
fi
else
echo "An error occurred during the backup process."
fi
还可以一次性备份所有数据库:
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
#!/bin/sh
# 数据库配置
DB_HOST=""
DB_USER=""
DB_PASSWORD=""
# 备份文件存储目录
BACKUP_DIR="/mnt/data/backup/mysql/all_databases/"
mkdir -p $BACKUP_DIR
# 备份文件名
BACKUP_FILE="$BACKUP_DIR/backup_$(date +%Y%m%d%H%M%S).sql"
# 日志文件名
LOG_FILE="$BACKUP_DIR/backup_$(date +%Y%m%d%H%M%S).log"
# 使用mysqldump进行备份,并将日志重定向到日志文件
docker run --rm -v "$BACKUP_DIR":/backup mysql:8.0.41 \
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" --all-databases > "$BACKUP_FILE" 2> "$LOG_FILE"
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "Backup successfully completed: $BACKUP_FILE" >> "$LOG_FILE"
else
echo "Backup failed" >> "$LOG_FILE"
exit 1
fi
# 删除7天前的备份文件
find "$BACKUP_DIR" -type f -name 'backup_*.sql' -mtime +7 -exec rm {} \;
# 删除7天前的日志文件
find "$BACKUP_DIR" -type f -name 'backup_*.log' -mtime +7 -exec rm {} \;
本文由作者按照
CC BY 4.0
进行授权