MySQL 数据库备份恢复

任务目标

使用腾讯云自动备份的 .xb 文件,在自建的主机上恢复出数据库。参考文档 https://cloud.tencent.com/document/product/236/33363。

安装 xtrabackup

安装 xtrabackup 和 qpress。其中 qpress 是 xtrabackup 用来压缩和解压的工具。

$ wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
$ sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
$ percona-release enable-only tools release
$ sudo apt install percona-xtrabackup-24
$ sudo apt install qpress

上述脚本先安装 percona 工具,以便修改 ubuntu 的软件源,然后再通过 apt 安装 percona-xtrabackup。需要注意,因为我们用的是 MySQL 5.6 的系统,所以安装 xtrabackup 2.4。如果用的是 MySQL 8.0,则使用配套的 xtrabackup 8.0 版本。

直接从腾讯云上下载安装 qpress 速度会更快。

$ wget -d --user-agent="Mozilla/5.0 (Windows NT x.y; rv:10.0) Gecko/20100101 Firefox/10.0" https://docs-tencentdb-1256569818.cos.ap-guangzhou.myqcloud.com/qpress-11-linux-x64.tar
$ sudo tar -xf qpress-11-linux-x64.tar -C /usr/local/bin

恢复数据

假设下载下来的数据库备份文件为 ~/mysql/weapp.xb,恢复出来的数据文件放在 ~/msyql/data 目录下:

# 修改用户
$ rm -rf ~/mysql/data
$ mkdir -p ~/mysql/data
$ xbstream -x -C ~/mysql/data < ~/mysql/weapp.xb
$ xtrabackup --decompress --remove-original --target-dir=~/mysql/data
$ xtrabackup --prepare --target-dir=~/mysql/data

运行 MySQL Docker 验证

$ sudo docker pull mysql:5.6
$ sudo docker run -p 3306:3306 --name mysql -v ~/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
$ sudo docker container stop mysql
$ sudo docker container start mysql
$ mysql -h 172.17.0.2 -uroot -p123456
mysql> USE information_schema;
mysql> select concat(round(sum(data_length/1024/1024),2),'MB') as data from tables where table_schema='weapp';
+-----------+
| data      |
+-----------+
| 2974.41MB |
+-----------+
1 row in set (0.00 sec)

其中 172.17.0.2 是 MySQL docker 容器的地址,也可以用 127.0.0.1 来替代。

使用 mysql 访问数据库时,可能出现如下错误:

ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1' (using password: YES)

解决方法是,进入 mysql docker image,修改用户权限。

$ sudo docker exec -it mysql /bin/bash
root@6df8e760c575:/# mysql -uroot
mysql> use mysql;
mhsql> select user,host from user where user='root';

+------+----------------+
| user | host           |
+------+----------------+
| root | %              |
| root | 127.0.0.1      |
| root | ::1            |
| root | localhost      |
| root | tencent64.site |
+------+----------------+
5 rows in set (0.00 sec)

修改权限,把 tencent64.site 改为 docker 网关 172.17.0.1。把 ::1 改为小程序后端地址 172.17.0.3

mysql> update user set host='172.17.0.1' where User='root' and host='tencent64.site';
mysql> grant all privileges on *.* to root@'172.17.0.1' identified by '123456' with grant option;
mysql> flush privileges;

mysql> update user set host='172.17.0.3' where User='root' and host='::1';
mysql> grant all privileges on *.* to root@'172.17.0.3' identified by '123456' with grant option;
mysql> flush privileges;

备份数据库

自己使用 docker 运行 mysql 数据库时,就需要考虑灾备。我们可以使用 xtrabackup 来自己进行数据库热备份。

首次备份之前,需要创建链接,把 /var/lib/mysql 链接到真实的 mysql 数据库文件位置。

# 此处假设 mysql 数据库放在 /home/ubuntu/mysql/data 目录下需要创建一个到 /var/lib/mysql 的链接,以便 xtrabackup 备份时访问,否则会报错
$ ln -s /home/ubuntu/mysql/data /var/lib/mysql

把保存备份的主机的登录密钥拷贝到应用主机上。

$ scp -i ~/.ssh/kamidox.qcloud.1.pem sfox.studio.9.aws.pem ubuntu@weapp.kamidox.com:/home/ubuntu/.ssh

然后执行备份,并使用 rsync 把备份文件拷贝到备份主机。

#!/bin/bash
# 调用示例 backup-database-full.sh base
if [ ! $1 ]; then
        BASE=base
else
        BASE=$1
fi

BACKUP_DIR=/home/ubuntu/backup
BASE_DIR=$BACKUP_DIR/$BASE
BASE_XB_FILE=${BASE_DIR}.xb

sudo rm -rf $BACKUP_DIR
mkdir -p $BASE_DIR
sudo xtrabackup --host=172.17.0.2 --user=root --password=123456 --backup --compress --stream=xbstream --target-dir=$BASE_DIR --extra-lsndir=$BASE_DIR > $BASE_XB_FILE
sudo chown -R ubuntu:ubuntu $BASE_XB_FILE
scp -i /home/ubuntu/.ssh/sfox.studio.9.aws.pem $BASE_XB_FILE ubuntu@kamidox.com:/home/ubuntu/backup/

按照当前 6GB 左右的数据库容量,大概在 2m 内可以完成备份。备份出来的文件压缩后在 2.4GB 左右。

备份完成后,我们可以上传到另外一台服务器上,以确保备份文件在物理上,处于不同的区域,提高灾备有效性和安全性。

上传备份时间比较长,且会占用应用服务器的带宽,最好在半夜执行。

还原数据库

当应用服务器的数据损坏或丢失,可以从灾备还原。还原前,需要先把备份数据库拷贝到应用服务器上,然后执行以下脚本来还原。

xtrabackup --decompress --remove-original --target-dir=/home/ubuntu/mysql/backup/
xtrabackup --prepare --target-dir=/home/ubuntu/mysql/backup/
sudo docker container stop mysql
rm -rf /home/ubuntu/mysql/data
mv /home/ubuntu/mysql/backup/ /home/ubuntu/mysql/data
sudo docker container start mysql

此处假设 /home/ubuntu/mysql/data 是 mysql 数据库所在目录。还原后,可以把 /home/ubuntu/mysql/backup/ 删除以便节省空间。

增量备份

增量备份,可以大幅节省空间以及传输的带宽。

#!/bin/bash
# 脚本调用示例 1: backup-database-inc.sh base inc1
# 脚本调用示例 2: backup-database-inc.sh inc1 inc2
if [ ! $1 ]; then
        BASE=base
        INC=inc1
else
        BASE=$1
        INC=$2
fi

BASE_DIR=/home/ubuntu/backup/$BASE
INC_DIR=/home/ubuntu/backup/$INC
INC_XB_FILE=${INC_DIR}.xb

mkdir -p $INC_DIR
sudo xtrabackup --host=172.17.0.2 --user=root --password=123456 --backup --compress --stream=xbstream --incremental-basedir=$BASE_DIR --target-dir=$INC_DIR --extra-lsndir=$INC_DIR > $INC_XB_FILE
sudo chown -R ubuntu:ubuntu $INC_XB_FILE
scp -i /home/ubuntu/.ssh/sfox.studio.9.aws.pem $INC_XB_FILE ubuntu@kamidox.com:/home/ubuntu/backup/

还原增量备份

BASE_DIR=/home/ubuntu/mysql/backup/base
INC_DIR1=/home/ubuntu/mysql/backup/inc1
INC_DIR2=/home/ubuntu/mysql/backup/inc2

xtrabackup --prepare --apply-log-only --target-dir=$BASE_DIR
xtrabackup --prepare --apply-log-only --target-dir=$BASE_DIR --incremental-dir=$INC_DIR1
xtrabackup --prepare --target-dir=$BASE_DIR --incremental-dir=$INC_DIR2

除了最后一个增量备份外,其他的备份都需要带 --apply-log-only 参数。

准备好了之后,就可以用 rsync, cp, mv 等命令来直接恢复数据库。

自动增量备份

自动从 /home/ubuntu/backup 目录查找已经备份的文件,并在最新的增量备份基础上,再进行增量备份。

#!/bin/bash
# hint: 必须使用 bash,否则 crontab 会默认使用 /bin/sh,导致无法识别 ${BASE:3} 表达式
# hint: 在 BACKUP_DIR 目录下查找最新的增量备份,在这个基础上再次进行增量备份,如 inc1 -> inc2; inc324 -> inc325;
BACKUP_DIR=/home/ubuntu/backup
BASE=$(ls -lt $BACKUP_DIR | grep '^d' | grep inc | head -n 1 | awk '{print $9}')
if [ ! $BASE ]; then
        BASE=base
        INC=inc1
else
        NUM=${BASE:3}
        NUM=$((NUM+1))
        INC=${BASE:0:3}${NUM}
fi

echo "backup database incremental, BASE=$BASE INC=$INC"
/home/ubuntu/bin/backup-database-inc.sh $BASE $INC

(完)


Post by Joey Huang under web on 2023-07-29(Saturday) 23:52. Tags: mysql,


Powered by Pelican and Zurb Foundation. Theme by Kenton Hamaluik.