Skip to content

一、Xtrabackup 介绍

MySQL 冷备、mysqldump、MySQL 热拷贝都无法实现对数据库进行增量备份。在实际生产环境中增量备份是非常实用的,如果数据大于 50G 或 100G,存储空间足够的情况下,可以每天进行完整备份,如果每天产生的数据量较大,需要定制数据备份策略。例如每周使用完整备份,周一到周六使用增量备份。而 Percona-Xtrabackup 就是为了实现增量备份而出现的一款主流备份工具,xtrabackup 有 2 个工具,分别是 xtrabackup、innobackupex。

Percona-xtrabackup 是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQL、Percona server 和 MariaDB,开源免费,是目前较为受欢迎的主流备份工具。xtrabackup 只能备份 InnoDB 和 XtraDB 两种数据引擎的表,而不能备份 MyISAM 数据表。

二、Xtrabackup 优点

  • 备份速度快,物理备份可靠
  • 备份过程不会打断正在执行的事务(无需锁表)
  • 能够基于压缩等功能节约磁盘空间和流量
  • 自动备份校验
  • 还原速度快
  • 可以流传将备份传输到另外一台机器上
  • 在不增加服务器负载的情况备份数据

三、Xtrabackup 备份原理

Xtrabackup 备份流程图:

  • innobackupex 启动后,会先 fork 一个进程,用于启动 xtrabackup,然后等待 xtrabackup 备份 ibd 数据文件;
  • xtrabackup 在备份 InnoDB 数据时,有 2 种线程:redo 拷贝线程和 ibd 数据拷贝线程。xtrabackup 进程开始执行后,会启动一个 redo 拷贝的线程,用于从最新的 checkpoint 点开始顺序拷贝 redo.log;再启动 ibd 数据拷贝线程,进行拷贝 ibd 数据。这里是先启动 redo 拷贝线程的。在此阶段,innobackupex 处于等待状态(等待文件被创建)
  • xtrabackup 拷贝完成 ibd 数据文件后,会通知 innobackupex(通过创建文件),同时 xtrabackup 进入等待状态(redo 线程依旧在拷贝 redo.log)
  • innobackupex 收到 xtrabackup 通知后,执行 FLUSH TABLES WITH READ LOCK(FTWRL),取得一致性位点,然后开始备份非 InnoDB 文件(如 frm、MYD、MYI、CSV、opt、par 等格式的文件),在拷贝非 InnoDB 文件的过程当中,数据库处于全局只读状态。
  • 当 innobackupex 拷贝完所有的非 InnoDB 文件后,会通知 xtrabackup,通知完成后,进入等待状态;
  • xtrabackup 收到 innobackupex 备份完成的通知后,会停止 redo 拷贝线程,然后通知 innobackupex,redo.log 文件拷贝完成;
  • innobackupex 收到 redo.log 备份完成后,就进行解锁操作,执行:UNLOCK TABLES;
  • 最后 innobackupex 和 xtrabackup 进程各自释放资源,写备份元数据信息等,innobackupex 等 xtrabackup 子进程结束后退出。

四、xtrabackup 的安装部署以及备份恢复实现

4.1 xtrabackup 的安装

软件包官网下载:https://www.percona.com/downloads/XtraBackup/LATEST/

可以选择 rpm 包方式安装,也可以下载源码包编译安装,这里直接采用 rpm 包的方式进行安装,安装过程省略。

Xtrabackup 中主要包含两个工具:

  • xtrabackup:用于热备 InnoDB、XtraDB 表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;
  • innobackupex:将 xtrabackup 进行封装的 perl 脚本,提供了备份 MyISAM 表的能力;
bash
常用选项:
   --host     指定主机
   --user     指定用户名
   --password    指定密码
   --port     指定端口
   --databases     指定数据库
   --incremental    创建增量备份
   --incremental-basedir   指定包含完全备份的目录
   --incremental-dir      指定包含增量备份的目录
   --apply-log        对备份进行预处理操作,一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处理不一致状态。"准备"的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。
   --redo-only      不回滚未提交事务
   --copy-back     恢复备份目录

一些常用的其他可选参数:
--lock-wait-query-type   该参数允许用户指定,哪类的SQL语句是需要Flush table with read lock等待的
--lock-wait-threshold    运行超过这个时间的查询才算长查询
--lock-wait-timeout     等待长查询多少时间后再尝试FTWRL,一旦Flush table with read lock被阻塞超过预定时间,则XtraBackup出错返回退出,参数允许用户指定了超过该阈值时间的查询会被Kill,同时也允许用户指定Kill

使用 innobackupex 备份时,其会调用 xtrabackup 备份所有的 InnoDB 表,复制所有关于表结构定义的相关文件(.frm)、以及 MyISAM、MERGE、CSV 和 ARCHIVE 表的相关文件,同时还会备份触发器和数据库配置信息相关的文件,这些文件会被保存到一个以时间命名的目录当中。在备份的同时,innobackupex 还会在备份目录中创建如下文件:

bash
xtrabackup_checkpoints -- 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息

xtrabackup_binlog_info  --  mysql服务器当前正在使用的二进制日志文件及备份这一刻位置二进制日志时间的位置。

xtrabackup_binlog_pos_innodb  --  二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

xtrabackup_binary  --  备份中用到的xtrabackup的可执行文件;

backup-my.cnf    --  备份命令用到的配置选项信息

在使用innobackupex进行备份时,还可以使用--no-timestamp选项来阻止命令自动创建一个以时间命名的目录:如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据。

如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

bash
mysql> CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY '123456';  # 创建用户
mysql> REVOKE ALL PRIVILEGES,GRANT OPTION FROM 'bkpuser';  # 回收此用户所有权限
mysql> GRANT RELOAD,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost';  # 授权刷新、锁定表、用户查看服务器状态
mysql> FLUSH PRIVILEGES;  # 刷新授权表

4.2 xtrabackup 全量备份与恢复

备份:

bash
1、innobackupex --user=DBUSER --password=DBUSERPASS --defaults-file=/etc/my.cnf /path/to/BACKUP-DIR/
2、拷贝数据到远程主机上: scp

恢复:

bash
1、停止数据库
2、删除数据库目录下的数据
3、innobackupex --apply-log /backups/2018-07-30_11-04-55/
4、innobackupex --copy-back --defaults-file=/etc/my.cnf  /backups/2018-07-30_11-04-55/
5、修改 mysql 工作目录所属人、所属组为 mysql
6、启动数据库

实战演示:

bash
(1)全量备份
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1  /backups/
# 在 master 上进行全库备份
# --user=root 指定备份用户
# --password=123456 指定备份用户密码
# --host 指定主机
# /backups 指定备份目录

[root@master backups]# ll
total 0
drwxr-x--- 7 root root 232 Jul 30 11:01 2018-07-30_11-01-37
[root@master backups]# ll 2018-07-30_11-01-37/  # 查看备份数据
total 77856
-rw-r----- 1 root root      418 Jul 30 11:01 backup-my.cnf
-rw-r----- 1 root root 79691776 Jul 30 11:01 ibdata1
drwxr-x--- 2 root root       20 Jul 30 11:01 kim
drwxr-x--- 2 root root     4096 Jul 30 11:01 mysql
drwxr-x--- 2 root root     4096 Jul 30 11:01 performance_schema
drwxr-x--- 2 root root       20 Jul 30 11:01 repppp
drwxr-x--- 2 root root     4096 Jul 30 11:01 wordpress
-rw-r----- 1 root root       21 Jul 30 11:01 xtrabackup_binlog_info
-rw-r----- 1 root root      113 Jul 30 11:01 xtrabackup_checkpoints
-rw-r----- 1 root root      482 Jul 30 11:01 xtrabackup_info
-rw-r----- 1 root root     2560 Jul 30 11:01 xtrabackup_logfile

(2)恢复,停止 slave 上的 mysql
[root@slave ~]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS!

(3)从库也安装上 xtrabackup
[root@slave tools]# yum install -y percona-xtrabackup-24-2.4.9-1.el7.x86_64.rpm

(4)从 master 上拷贝备份
[root@master backups]# scp -r 2018-07-30_11-01-37/ root@192.168.56.12:/backups/

(5)合并数据,使数据文件处于一致性的状态
[root@slave tools]# innobackupex --apply-log /backups/2018-07-30_11-01-37/
180729 23:18:30 completed OK!

(6)在 slave 上删除原有的数据
[root@slave ~]# rm -rf /usr/local/mysql/data/

(7)确保 my.cnf 的数据目录路径,否则会报错,要和 master /etc/my.cnf 配置一致
[root@slave ~]# vim /etc/my.cnf
datadir=/usr/local/mysql/data

(8)在 slave 上数据恢复
[root@slave ~]# innobackupex --copy-back /backups/2018-07-30_11-01-37/
180729 23:32:08 completed OK!

(9)查看 slave 上数据目录
[root@slave ~]# ll /usr/local/mysql/data/
total 188432
-rw-r----- 1 root root 79691776 Jul 29 23:32 ibdata1
...

(10)修改属主属组为 mysql
[root@slave ~]# chown -Rf mysql:mysql /usr/local/mysql/data/

(11)启动 mysql
[root@slave ~]# systemctl start mysqld

(12)查看数据,是否恢复
[root@slave ~]# mysql -uroot -p -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kim                |
| mysql              |
| performance_schema |
| repppp             |
| wordpress          |
+--------------------+

总结全库备份与恢复四步曲:

  • innobackupex 全量备份,并指定备份目录路径,拷贝数据到远程主机;
  • 在恢复前,需要使用 --apply-log 参数先进行合并数据文件,确保数据的一致性要求;
  • 恢复时,直接使用 --copy-back 参数进行恢复,需要注意的是,在 my.cnf 中要指定数据文件目录的路径。
  • 使用 change master to 指定 MASTER_LOG_FILE 和 MASTER_LOG_POS(从 xtrabackup 备份文件的 xtrabackup_info 中获取)
bash
change master to \
master_host="10.114.0.33", \
master_user="repluser", \
master_port=3306, \
MASTER_LOG_FILE='mysql-bin.014266', \
MASTER_LOG_POS=63417078, \
master_password="xxx";

4.3 xtrabackup 增量备份与恢复

使用 innobackupex 进行增量备份,每个 InnoDB 的页面都会包含一个 LSN 信息,每当相关的数据发生改变,相关的页面的 LSN 就会自动增长。这正是 InnoDB 表可以进行增量备份的基础,即 innobackupex 通过备份上次完全备份之后发生改变的页面来实现。在进行增量备份时,首先要进行一次全量备份,第一次增量备份是基于全备的,之后的增量备份都是基于上一次的增量备份的,以此类推。

要实现第一次增量备份,可以使用下面的命令进行:

  • --incremental 创建增量备份
  • --incremental-basedir 指定包含完全备份的目录
  • --incremental-dir 指定包含增量备份的目录
bash
(1)先全量备份
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1 /backups/

[root@master ~]# mysql -uroot -p  # 在 master 上创建 student 库并创建 testtb 表插入若干数据
mysql> create database student;
mysql> use student;
mysql> create table testtb(id int);
mysql> insert into testtb values(1),(10),(99);
mysql> select * from testtb;
+------+
| id   |
+------+
|    1 |
|   10 |
|   99 |
+------+

(2)使用 innobackupex 进行增量备份
[root@master backups]# innobackupex --user=root --password=123456 --host=127.0.0.1 --incremental /backups/ --incremental-basedir=/backups/2018-07-30_11-01-37/
180730 13:51:50 completed OK!

(3)查看备份数据
[root@master backups]# ll
drwxr-x--- 7 root root 232 Jul 30 11:01 2018-07-30_11-01-37  # 全量备份数据目录
drwxr-x--- 8 root root 273 Jul 30 13:51 2018-07-30_13-51-47  # 增量备份数据目录

(4)查看增量备份的 xtrabackup_checkpoints
backup_type = incremental
from_lsn = 3127097
to_lsn = 3158741

(5)模拟 mysql 故障,删除数据目录所有数据
[root@master ~]# /etc/init.d/mysqld stop
[root@master ~]# rm -rf /usr/local/mysql/data/*

(6)合并全备数据目录,确保数据的一致性
[root@master ~]# innobackupex --apply-log --redo-only /backups/2018-07-30_11-01-37/
180730 14:05:29 completed OK!

(7)将增量备份数据合并到全备数据目录当中
[root@master ~]# innobackupex --apply-log --redo-only /backups/2018-07-30_11-01-37/ --incremental-dir=/backups/2018-07-30_13-51-47/
180730 14:06:44 completed OK!

(8)恢复数据
[root@master ~]# innobackupex --copy-back /backups/2018-07-30_11-01-37/
180730 14:08:17 completed OK!
[root@master ~]# chown -R mysql.mysql /usr/local/mysql/data
[root@master ~]# /etc/init.d/mysqld start
[root@master ~]# mysql -uroot -p -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kim                |
| mysql              |
| performance_schema |
| repppp             |
| student            |
| wordpress          |
+--------------------+

总结:

  • 增量备份需要使用参数 --incremental 指定需要备份到哪个目录,使用 --incremental-basedir 指定全备目录;
  • 进行数据备份时,需要使用参数 --apply-log --redo-only 先合并全备数据目录数据,确保全备数据目录数据的一致性;
  • 再将增量备份数据使用参数 --incremental-dir 合并到全备数据当中;
  • 最后通过最后的全备数据进行恢复数据,注意,如果有多个增量备份,需要逐一合并到全备数据当中,再进行恢复。

五、xtrabackup 异机远程流式备份

5.1 xtrabackup 异机远程流式备份脚本

备注:

  • 需要提前在数据库主机上安装好 xtrabackup 备份软件
  • 需要有免密环境(到远程主机上)
  • 采用流备份的方式,短时间内网络流量不会很高,数据库压力也不会太大
  • 删除远程主机上超过 30 天以上的备份文件
bash
[root@master ~]# vim /home/data/backup/xtrbackup_full.sh
#!/bin/bash
#Author        : srebro.cn
####################################################
##
## xtrabackup script
##      backup data at remote host
##      you should config ssh trust
##
## Usage:
##   1.You must check and modify the variable
##     in variable section
##
####################################################

MSNAME=yz
BAKDIR=/home/data/backup/xtrbackup
BAKFILE=$MSNAME-`date +%Y%m%d%H%M`
LOGFILE=$MSNAME-`date +%Y%m%d%H%M`.log
ROOTPWD=r123d$&*#!
REMOTE_HOST=vmuser@10.114.0.15
REMOTE_BAKDIR=/data/xtrbackup
MYCNF=/etc/my.cnf

/usr/bin/innobackupex --defaults-file=$MYCNF --user=root --password=$ROOTPWD --host=127.0.0.1 \
--lock-wait-threshold=40 --lock-wait-query-type=all --lock-wait-timeout=180 --kill-long-queries-timeout=20 --kill-long-query-type=all \
--stream=tar $BAKDIR 2>$BAKDIR/$LOGFILE | ssh $REMOTE_HOST  "cat - > $REMOTE_BAKDIR/$BAKFILE.tar"

# check backup log
CHECKOK=`tail -1 $BAKDIR/$LOGFILE | grep "completed OK\!" | wc -l`
if [ $CHECKOK -ne 1 ]
then
  echo "[ WARNING ] Backup failed!"
  exit
fi

# clean backup piece, delete 30 day before
ssh $REMOTE_HOST "find $REMOTE_BAKDIR/$MSNAME* -mtime +30 -type f -maxdepth 1 | xargs rm -rf {}"

5.2 设置定时任务

bash
[root@master ~]# crontab -e

# xtrabackup 备份,每天夜里凌晨 2 点 02 分
02 02 * * * bash /home/data/backup/xtrbackup_full.sh

5.3 登陆到远程备份主机上查看备份的文件

bash
[root@backup xtrbackup]# ll /data/xtrbackup/
total 11279944
-rw-rw-r--. 1 srebro srebro 1643324416 Aug 19 09:36 yz-202108190935.tar
-rw-rw-r--. 1 srebro srebro 1643275776 Aug 19 09:38 yz-202108190937.tar
-rw-rw-r--. 1 srebro srebro 1643277312 Aug 19 09:39 yz-202108190938.tar
-rw-rw-r--. 1 srebro srebro 1644345856 Aug 20 02:02 yz-202108200202.tar
-rw-rw-r--. 1 srebro srebro 1645821952 Aug 21 02:02 yz-202108210202.tar
-rw-rw-r--. 1 srebro srebro 1665288704 Aug 22 02:02 yz-202108220202.tar
-rw-rw-r--. 1 srebro srebro 1665287680 Aug 23 02:02 yz-202108230202.tar

[root@backup xtrbackup]# du -sh /data/xtrbackup/*
1.6G  /data/xtrbackup/yz-202108190935.tar
1.6G  /data/xtrbackup/yz-202108190937.tar
1.6G  /data/xtrbackup/yz-202108190938.tar
1.6G  /data/xtrbackup/yz-202108200202.tar
1.6G  /data/xtrbackup/yz-202108210202.tar
1.6G  /data/xtrbackup/yz-202108220202.tar
1.6G  /data/xtrbackup/yz-202108230202.tar
最近更新