mysql和mariadb备份工具xtrabackup

时间:2022-08-31 17:12:40

简介
 

    xtraBackup(PXB) 工具是 Percona 公司用 perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle)、Percona Server 和 MariaDB,并且全部开源,真可谓是业界良心。阿里的 RDS MySQL 物理备份就是基于这个工具做的。由于是采取物理拷贝的方式来做的备份,所以速度非常快,几十G数据几分钟就搞定了,而它巧妙的利用了mysql 特性做到了在线热备份,不用像以前做物理备份那样必须关闭数据库才行,直接在线就能完成整库或者是部分库的全量备份和增量备份。新版本的xtrabackup改成了cmake安装,和以前有点不一样。

版本说明:这里安装的版本是2.4.6,而2.3.3之后不备份死锁了,如果数据库是mysql 5.7之后的必须要装2.4.4才可以用,当然了, 会向下兼容的。

1
2
3
4
5
6
7
bin/
├── innobackupex -> xtrabackup
├── xbcloud
├── xbcloud_osenv
├── xbcrypt
├── xbstream
└── xtrabackup 

  其中最主要的是 innobackupex 和 xtrabackup,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制。Percona 在2.3 版本用C重写了 innobackupex ,innobackupex 功能全部集成到 xtrabackup 里面,只有一个 binary,另外为了使用上的兼容考虑,innobackupex 作为 xtrabackup 的一个软链接。对于二次开发来说,2.3 摆脱了之前2个进程协作的负担,架构上明显要好于之前版本。(Percona XtraBackup 2.3 发布之后,推荐的备份方法是使用 xtrabackup 脚本。 )

xtrabackup 是用来备份 InnoDB 表的,不能备份非 InnoDB 表,和 mysqld server 没有交互;innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。简单来说,innobackupex 在 xtrabackup 之上做了一层封装。

一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行;另外一个原因是我们可能需要保存位点信息。

另外几个工具相对小众些,xbcrypt 是加解密备份文件用的;xbstream 类似于tar,是 Percona 自己实现的一种支持并发写的流文件格式;两者在备份和解压时都会用到(如果备份用了加密和并发)。xbcloud 工具的作用是:把全部或部分 xbstream 档案从云上下载或上传到云。

XtraBackup原理

  2.3版本之前 innobackupex 和 xtrabackup 这2个工具之间的交互和协调是通过控制文件的创建和删除来实现的,2.3版本将 innobackupex 功能全部集成到 xtrabackup 里面,也就不需要他们之间的通信。这里介绍基于老的架构(2.2版本),但是原理和2.3是一样的,只是实现上的差别。

PXB 备份过程

  1. innobackupex 在启动后,会先 fork 一个进程,启动 xtrabackup进程,然后就等待 xtrabackup 备份完 ibd 数据文件;
  2. xtrabackup 在备份 InnoDB 相关数据时,是有2种线程的,1种是 redo 拷贝线程,负责拷贝 redo 文件,1种是 ibd 拷贝线程,负责拷贝 ibd 文件;redo 拷贝线程只有一个,在 ibd 拷贝线程之前启动,在 ibd 线程结束后结束。xtrabackup 进程开始执行后,先启动 redo 拷贝线程,从最新的 checkpoint 点开始顺序拷贝 redo 日志;然后再启动 ibd 数据拷贝线程,在 xtrabackup 拷贝 ibd 过程中,innobackupex 进程一直处于等待状态(等待文件被创建)。
  3. xtrabackup 拷贝完成idb后,通知 innobackupex(通过创建文件),同时自己进入等待(redo 线程仍然继续拷贝);
  4. innobackupex 收到 xtrabackup 通知后,执行FLUSH TABLES WITH READ LOCK (FTWRL),取得一致性位点,然后开始备份非 InnoDB 文件(包括 frm、MYD、MYI、CSV、opt、par等)。拷贝非 InnoDB 文件过程中,因为数据库处于全局只读状态,如果在业务的主库备份的话,要特别小心,非 InnoDB 表(主要是MyISAM)比较多的话整库只读时间就会比较长,这个影响一定要评估到。
  5. 当 innobackupex 拷贝完所有非 InnoDB 表文件后,通知 xtrabackup(通过删文件) ,同时自己进入等待(等待另一个文件被创建);
  6. xtrabackup 收到 innobackupex 备份完非 InnoDB 通知后,就停止 redo 拷贝线程,然后通知 innobackupex redo log 拷贝完成(通过创建文件);
  7. innobackupex 收到 redo 备份完成通知后,就开始解锁,执行 UNLOCK TABLES;
  8. 最后 innobackupex 和 xtrabackup 进程各自完成收尾工作,如资源的释放、写备份元数据信息等,innobackupex 等待 xtrabackup 子进程结束后退出。

在上面描述的文件拷贝,都是备份进程直接通过操作系统读取数据文件的,只在执行 SQL 命令时和数据库有交互,基本不影响数据库的运行,在备份非 InnoDB 时会有一段时间只读(如果没有MyISAM表的话,只读时间在几秒左右),在备份 InnoDB 数据文件时,对数据库完全没有影响,是真正的热备。

InnoDB 和非 InnoDB 文件的备份都是通过拷贝文件来做的,但是实现的方式不同,前者是以page为粒度做的(xtrabackup),后者是 cp 或者 tar 命令(innobackupex),xtrabackup 在读取每个page时会校验 checksum 值,保证数据块是一致的,而 innobackupex 在 cp MyISAM 文件时已经做了flush(FTWRL),磁盘上的文件也是完整的,所以最终备份集里的数据文件都是写入完整的。

增量备份

PXB 是支持增量备份的,但是只能对 InnoDB 做增量,InnoDB 每个 page 有个 LSN 号,LSN 是全局递增的,page 被更改时会记录当前的 LSN 号,page中的 LSN 越大,说明当前page越新(最近被更新)。每次备份会记录当前备份到的LSN(xtrabackup_checkpoints 文件中),增量备份就是只拷贝LSN大于上次备份的page,比上次备份小的跳过,每个ibd文件最终备份出来的是增量 delta 文件。

MyISAM 是没有增量的机制的,每次增量备份都是全部拷贝的。

增量备份过程和全量备份一样,只是在 ibd 文件拷贝上有不同。

恢复过程

如果看恢复备份集的日志,会发现和 mysqld 启动时非常相似,其实备份集的恢复就是类似 mysqld crash后,做一次 crash recover。

恢复的目的是把备份集中的数据恢复到一个一致性位点,所谓一致就是指原数据库某一时间点各引擎数据的状态,比如 MyISAM 中的数据对应的是 15:00 时间点的,InnoDB 中的数据对应的是 15:20 的,这种状态的数据就是不一致的。PXB 备份集对应的一致点,就是备份时FTWRL的时间点,恢复出来的数据,就对应原数据库FTWRL时的状态。

因为备份时 FTWRL 后,数据库是处于只读的,非 InnoDB 数据是在持有全局读锁情况下拷贝的,所以非 InnoDB 数据本身就对应 FTWRL 时间点;InnoDB 的 ibd 文件拷贝是在 FTWRL 前做的,拷贝出来的不同 ibd 文件最后更新时间点是不一样的,这种状态的 ibd 文件是不能直接用的,但是 redo log 是从备份开始一直持续拷贝的,最后的 redo 日志点是在持有 FTWRL 后取得的,所以最终通过 redo 应用后的 ibd 数据时间点也是和 FTWRL 一致的。

所以恢复过程只涉及 InnoDB 文件的恢复,非 InnoDB 数据是不动的。备份恢复完成后,就可以把数据文件拷贝到对应的目录,然后通过mysqld来启动了。

查看数据库支持引擎(mysql和mariadb默认是Innodb引擎):

1
show engines;

mysql和mariadb备份工具xtrabackup

查看数据库表支持的引擎

1
show create table table_name; 

安装

1、下载地址

  你可以根据自己的需求选择不同的操作系统和版本(我这里是用最新的版本)

1
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.11/binary/tarball/percona-xtrabackup-2.4.11-Linux-x86_64.libgcrypt145.tar.gz

2、加压缩后,mv更改目录名为xtrabackup,然后加入环境变量方便使用。

1
2
export PATH=$PATH:/root/xtrabackup/bin/
source /etc/profile

完整备份

   xtrabackup选项

  xtrabackup 工具有许多参数,具体可去官网查询(xtrabackup 参数选项 | innobackupex 参数选项),这里简单介绍 innobackupex 一些常用的参数。

  1) innobackupex 参数选项

  --defaults-file=[MY.CNF]    //指定配置文件:只能从给定的文件中读取默认选项。 且必须作为命令行上的第一个选项;必须是一个真实的文件,它不能是一个符号链接。

  --databases=#    //指定备份的数据库和表,格式为:--database="db1[.tb1] db2[.tb2]" 多个库之间以空格隔开,如果此选项不被指定,将会备份所有的数据库。

  --include=REGEXP    //用正则表达式的方式指定要备份的数据库和表,格式为 --include=‘^mydb[.]mytb’ ,对每个库中的每个表逐一匹配,因此会创建所有的库,不过是空的目录。--include 传递给 xtrabackup --tables。

  --tables-file=FILE    //此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称,格式为databasename.tablename。该选项传递给 xtrabackup --tables-file,与--tables选项不同,只有要备份的表的库才会被创建。

  注意:部分备份(--include、--tables-file、--database)需要开启 innodb_file_per_table 。

  --compact    //创建紧凑型备份,忽略所有辅助索引页,只备份data page;通过--apply-log中重建索引--rebuild-indexs。

  --compress    //此选项指示xtrabackup压缩备份的InnoDB数据文件,会生成 *.qp 文件。

  --decompress    //解压缩qp文件,为了解压缩,必须安装 qpress 工具。 Percona XtraBackup不会自动删除压缩文件,为了清理备份目录,用户应手动删除 * .qp文件:find /data/backup -name "*.qp" | xargs rm。

  --no-timestamp    //指定了这个选项备份将会直接存储在 BACKUP-DIR 目录,不再创建时间戳文件夹。

  --apply-log    //应用 BACKUP-DIR 中的 xtrabackup_logfile 事务日志文件。一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处于不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件使得数据文件处于一致性状态。

  --use-memory=#    //此选项接受一个字符参数(1M/1MB,1G/1GB,默认100M),仅与--apply-log一起使用,该选项指定prepare时用于崩溃恢复(crash-recovery)的内存。

  --copy-back    //拷贝先前备份所有文件到它们的原始路径。但原路径下不能有任何文件或目录,除非指定 --force-non-empty-directories 选项。

  --force-non-empty-directories    //恢复时指定此选项,可使 --copy-back 和 --move-back 复制文件到非空目录,即原data目录下可以有其他文件,但是不能有与恢复文件中同名的文件,否则恢复失败。

  --rsync    //此选项可优化本地文件(非InnoDB)的传输。rsync工具一次性拷贝所有非InnoDB文件,而不是为每个文件单独创建cp,在备份恢复很多数据库和表时非常高效。此选项不能和 --stream 一起使用。

  --incremental    //这个选项告诉 xtrabackup 创建一个增量备份,而不是完全备份。它传递到 xtrabackup 子进程。当指定这个选项,可以设置 --incremental-lsn 或 --incremental-basedir。如果这2个选项都没有被指定,--incremental-basedir 传递给 xtrabackup 默认值,默认值为:基础备份目录的第一个时间戳备份目录。

  --incremental-basedir=DIRECTORY    //该选项接受一个字符串参数,该参数指定作为增量备份的基本数据集的完整备份目录。它与 --incremental 一起使用。

  --incremental-dir=DIRECTORY    //该选项接受一个字符串参数,该参数指定了增量备份将与完整备份相结合的目录,以便进行新的完整备份。它与 --incremental 选项一起使用。

  --redo-only    //在“准备基本完整备份” 和 “合并所有的增量备份(除了最后一个增备)”时使用此选项。它直接传递给xtrabackup的 xtrabackup --apply-log-only 选项,使xtrabackup跳过"undo"阶段,只做"redo"操作。如果后面还有增量备份应用到这个全备,这是必要的。有关详细信息,请参阅xtrabackup文档。

  --parallel=NUMBER-OF-THREADS    //此选项接受一个整数参数,指定xtrabackup子进程应用于同时备份文件的线程数。请注意,此选项仅适用于文件级别,也就是说,如果您有多个.ibd文件,则它们将被并行复制; 如果您的表一起存储在一个表空间文件中,它将不起作用。

  2) xtrabackup 参数选项

  --apply-log-only    //这个选项使在准备备份(prepare)时,只执行重做(redo)阶段,这对于增量备份非常重要

 

  这里这用的是centos7.4.x和5.5.56-MariaDB MariaDB Server,这里以zabbix数据库备份为背景。

3、创建备份的目录

1
mkdir -p /data/mysql

4、进行完整备份

1
innobackupex --defaults-file=/etc/my.cnf --user=root  --password=123456 --socket=/var/lib/mysql/mysql.sock  /data/root

mysql和mariadb备份工具xtrabackup

5、查看备份目录(连接数据库,开始拷贝redo log,拷贝innodb表文件,锁表、拷贝非innodb表文件,停止拷贝redo log,解锁。)

  其中zabbix和test、mysql、performance_schema都是已经备份的数据库,backup-my.cnf是备份的my.cnf配置文件。

mysql和mariadb备份工具xtrabackup

mysql和mariadb备份工具xtrabackup

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

 xtrabackup_info:记录备份的基本信息,uuid、备份命令、备份时间、binlog、LSN、以及其他加密压缩等信息。

xtrabackup_logfile:备份的重做日志文件。

 6、全盘恢复

   6.1首先停止数据库服务,并准备好数据的恢复目录(为了不覆盖原有的数据,建议重新找个位置存放数据库文件,我这里是默认的/var/lib/mysql/),

1
systemctl stop mariadb

  6.2准备(prepare)一个完全备份: --apply-log ( /data/root/2018-05-09_01-28-45/ 为备份目录,执行之后 xtrabackup_checkpoints 文件中的 backup_type = full-prepared )

1
[root@bogon root]# innobackupex --apply-log /data/root/2018-05-09_01-28-45/

mysql和mariadb备份工具xtrabackup

  6.3执行恢复操作:

1
innobackupex  --defaults-file=/etc/my.cnf --copy-back --rsync /data/root/2018-05-09_01-28-45/

  提示我们这个说原来数据库存放目录是不是空的(它其实说不让我们在原来的数据库目录恢复,要不你换地方,要不你删除原来所有的数据库文件,我这里为了防止意外,就换个地方)

  mysql和mariadb备份工具xtrabackup

  首先,我们得修改my.cnf配置文件中数据库存放位置的路径,更改后的目录是我们刚才新建的目录。

  mysql和mariadb备份工具xtrabackup

  再此执行恢复操作,提示OK。

  mysql和mariadb备份工具xtrabackup

  6.4、刚才我们停止了mariadb服务,现在我们除了要开启数据库服务外,还得给新的mysql目录所有文件mysql用的属主和属组的权限。

1
2
[root@bogon root]# chown -R mysql.mysql /data/mysql
[root@bogon root]# systemctl start mariadb

  测试,我们最开始备份了所有所有数据库(备份完成后,我删除了zabbix配置里面的几个监控项,当恢复完成后原来的监控项都已经恢复)

增量备份、恢复

   注意、只有InnoDB引擎支持增量备份,MyISAM只支持完整备份。

  1、首先我们要对数据库进行一个全备。

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock --no-timestamp /data/backup/all_backup

  2、然后我们修改数据库操作,再进行第一次增量备份。注意,--incremental-basedir=指的是对谁进行增量备份,这里我们是第一次增量备份,所以这里指的应该是全备。

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock  --no-timestamp --incremental /data/backup/incremental-dir-1 --incremental-basedir=/data/backup/all_backup/

  3、然后我们再对数据库进行修改,再进行第二次增量备份。这里我们增量的部分是相对第一次增量备份到第二次增量备份的差异部分,所以这里--incremental-basedir=应该是指的第一次增量备份incremental-dir-1

1
innobackupex -uroot -p123456 --no-timestamp --socket=/var/lib/mysql/mysql.sock  --incremental /data/backup/incremental-dir-2/  --incremental-basedir=/data/backup/incremental-dir-1/

  4、上面我们对数据库进行了两次不同的修改,也做了两次增量,下面我们来看增量备份的恢复方法(为了试验效果明显,我这里删除了两次增量备份增加的部分)。首先我们要准备一个完整备份(全备)

1
innobackupex --apply-log --redo-only /data/backup/all_backup/

  5、然后恢复第一次增量备份恢复,注意:只要不是最后一次增量备份的恢复,都需要加上--redo-only参数。

1
innobackupex --apply-log --redo-only /data/backup/all_backup/  --incremental-dir=/data/backup/incremental-dir-1

  6、第二次增量备份的恢复,这里是最后一次增量备份的恢复,所以不用加--redo-only参数。

1
innobackupex --apply-log /data/backup/all_backup/  --incremental-dir=/data/backup/incremental-dir-2

  7、将两次增量备份,合并到完整备份中(合并完成后,跟完整备份的恢复方法一样)

1
innobackupex --apply-log /data/backup/all_backup/

  8、为了数据一致性,先停止mariadb数据库服务。这里我们的数据库文件目录是/var/lib/mysql下,我给他换个位置到/data/mysql(你也可以直接mv  /var/lib/mysql  var/lib/mysql.bak,然后再新建一个mysql目录),记得要修改/etc/my.cnf文件中datadir=路径。

1
mkdir -p /data/mysql

  9、恢复的目录有了,我们下面开始恢复,想到与被上面合成到一起的增量备份文件copy到/data/mysql/这个目录下。

1
innobackupex --copy-back /data/backup/all_backup/

  10、只恢复文件还不行,这会儿/data/mysql/下的文件(包含一级目录都是属主和属组都是root,,我们需要给mysql权限)

1
chown mysql:mysql -R /data/mysql/

  11、启动数据库服务,增量备份的备份和恢复完整。

1
systemctl restart  mariadb

差异备份、恢复(建议使用)

   增量备份的优缺点:

  1、上面我们说了xtrabackup的增量备份和恢复,增量备份有它的好处,就是每次进行相对上次备份有不同的地方进行备份,但是中间如果哪个备份挂了(丢失了),那就没法恢复了,而且增量备份一般都是每间隔几个小时备份一次(最次也得每天进行一次增量备份)。恢复起来其实是很麻烦的,可能需要你恢复的时候,增量备份已经好几百个了,除非你写脚本,否则个人感觉很麻烦的。

  2、我们知道增量备份的时候有个参数--incremental-dir=,它的意思是根据之前的哪次备份进行差异性备份,以前增量情况是首先一个全备,第一次增量的做法是根据全备进行备份,第二次增量备份的做法是根据第一次增量备份进行备份,依次类推。很麻烦。

  3、既然可以指定根据哪次做增量备份,我们就直接每次根据完整备份进行增量备份----差异备份。这样做的好处是恢复时候只需要恢复最后一次增量备份就行,缺点是我们每次都是根据完整备份进行备份,长时间下去会占用空间很大。

备份:

1、首先进行一次完整备份

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock --no-timestamp /data/backup/all_backup

2、第一次次增量备份

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock  --no-timestamp --incremental /data/backup/incremental-dir-1 --incremental-basedir=/data/backup/all_backup/

3、第二次增量备份

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock  --no-timestamp --incremental /data/backup/incremental-dir-2 --incremental-basedir=/data/backup/all_backup/

4、第三次增量备份

1
innobackupex -uroot -p123456 --socket=/var/lib/mysql/mysql.sock  --no-timestamp --incremental /data/backup/incremental-dir-3 --incremental-basedir=/data/backup/all_backup/

注意,上面我们每次备份都是根据完整备份进行增量备份的。

恢复:

1、首先准备一个全备

1
innobackupex --apply-log --redo-only /data/backup/all_backup/

2、恢复最后一次备份,这里恢复是肯定最后一次恢复,所以不用加--redo-only参数

1
innobackupex --apply-log /data/backup/all_backup/  --incremental-dir=/data/backup/incremental-dir-3

3、将增量备份合并到完整备份中。

1
innobackupex --apply-log /data/backup/all_backup/

4、为了数据一致性,先停止mariadb数据库服务。这里我们的数据库文件目录是/var/lib/mysql下,我给他换个位置到/data/mysql(你也可以直接mv  /var/lib/mysql  var/lib/mysql.bak,然后再新建一个mysql目录),记得要修改/etc/my.cnf文件中datadir=路径。

1
mkdir -p /data/mysql

5、恢复的目录有了,我们下面开始恢复,想到与被上面合成到一起的增量备份文件copy到/data/mysql/这个目录下。

1
innobackupex --copy-back /data/backup/all_backup/

6、只恢复文件还不行,这会儿/data/mysql/下的文件(包含一级目录都是属主和属组都是root,,我们需要给mysql权限)

1
chown mysql:mysql -R /data/mysql/

7、启动数据库服务,增量备份的备份和恢复完整。

1
systemctl restart  mariadb

注意:

  1、完整备份需要备份到另外一个位置,如果你恢复失败的,你的完整备份里面的参数也会跟着改变了,这个时候需要再恢复就困难了。相反我只需要把完整备份的备份cp到完整备份的目录里面就OK了,可以接着折腾了。

  2、如果你不备份你的完整备份,一旦恢复失败,想要重新恢复,那你就等着哭吧。

转载于:https://www.cnblogs.com/lei0213/p/9012272.html