mysql备份工具之xtrabackup
2010-09-17 13:43:59 阿炯

MySQL数据库的备份,各种工具虽然不少,但一个真正好用易用的却又非常难找。mysqldump做为数据的逻辑备份工具还行,但是无法进行在线热备,而没有物理备份工具,在数据量比较大的时候,恢复的时间也会让人难以接受。InnoDB有一个商业的软件:InnoDB Hotbackup,可以对InnoDB引擎的表实现在线热备。xtraBackup(PXB) 工具是 Percona 公司用 Perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle)、Percona Server 和 MariaDB,并且全部开源,真可谓是业界良心。据说阿里的 RDS MySQL 物理备份就是基于这个工具做的。由于是采取物理拷贝的方式来做的备份,所以速度非常快,它巧妙的利用了mysql 特性做到了在线热备份,不用像以前做物理备份那样必须关闭数据库才行,直接在线就能完成整库或者是部分库的全量备份和增量备份。新版本的xtrabackup改成了cmake安装,和以前有些不一样。其主要功能为:
* 在线(热)备份整个库的InnoDB, XtraDB表
* 在xtrabackup的上一次整库备份基础上做增量备份(仅针对'innodb')
* 以流的形式产生备份,可以直接保存到远程机器上

优点

1)备份速度快,物理备份可靠
2)备份过程不会打断正在执行的事务(无需锁表)
3)能够基于压缩等功能节约磁盘空间和流量
4)自动备份校验与还原速度快
5)可以流传将备份传输到另外一台机器上
6)在不增加服务器负载的情况备份数据
7)物理备份工具,在同级数据量基础上,都要比逻辑备份性能要好的多;在大量数据级别的情况下,物理备份恢复数据上有一定优势。

版本说明:这里以2.4.6为例,而2.3.3之后不备份死锁了,如果数据库是mysql 5.7之后的必须要装2.4.4才可以用,当然会向下兼容的。工具结构如下:
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和XtraDB两种数据表,不能备份非 InnoDB 表(如MyISAM),和 mysqld server 没有交互;
innobackupex 脚本用来备份非 InnoDB 表,同时会调用 xtrabackup 命令来备份 InnoDB 表,还会和 mysqld server 发送命令进行交互,如加读锁(FTWRL)、获取位点(SHOW SLAVE STATUS)等。简单来说,innobackupex 在 xtrabackup 之上做了一层封装,参考了InnoDB Hotbackup的innoback脚本修改而来的perl脚本封装,主要是为了方便同时备份InnoDB和MyISAM引擎的表,但在处理myisam时需要加一个读锁。并且加入了一些使用的选项。如slave-info可以记录备份恢 复后,作为slave需要的一些信息,根据这些信息,可以很方便的利用备份来重做slave。

一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的有系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行;另外一个原因是我们可能需要保存位点信息。另外几个相对小众工具:
xbcrypt 是加解密备份文件用的;
xbstream 类似于tar,是 Percona 自己实现的一种支持并发写的流文件格式,两者在备份和解压时都会用到(如果备份用了加密和并发);
xbcloud 工具的作用是:把全部或部分 xbstream 档案从云上下载或上传到云。

原理

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

备份过程

innobackupex 在启动后,会先 fork 一个进程,启动 xtrabackup进程,然后就等待 xtrabackup 备份完 ibd 数据文件;

xtrabackup 在备份 InnoDB 相关数据时,是有2种线程的,1种是 redo 拷贝线程,负责拷贝 redo 文件,1种是 ibd 拷贝线程,负责拷贝 ibd 文件;redo 拷贝线程只有一个,在 ibd 拷贝线程之前启动,在 ibd 线程结束后结束。xtrabackup 进程开始执行后,先启动 redo 拷贝线程,从最新的 checkpoint 点开始顺序拷贝 redo 日志;然后再启动 ibd 数据拷贝线程,在 xtrabackup 拷贝 ibd 过程中,innobackupex 进程一直处于等待状态(等待文件被创建)。

xtrabackup 拷贝完成idb后,通知 innobackupex(通过创建文件),同时自己进入等待(redo 线程仍然继续拷贝)。

innobackupex 收到 xtrabackup 通知后,执行FLUSH TABLES WITH READ LOCK (FTWRL),取得一致性位点,然后开始备份非 InnoDB 文件(包括 frm、MYD、MYI、CSV、opt、par等)。拷贝非 InnoDB 文件过程中,因为数据库处于全局只读状态,如果在业务的主库备份的话,要特别小心,非 InnoDB 表(主要是MyISAM)比较多的话整库只读时间就会比较长,这个影响一定要考虑到。

当 innobackupex 拷贝完所有非 InnoDB 表文件后,通知 xtrabackup(通过删文件) ,同时自己进入等待(等待另一个文件被创建);

xtrabackup 收到 innobackupex 备份完非 InnoDB 通知后,就停止 redo 拷贝线程,然后通知 innobackupex redo log 拷贝完成(通过创建文件);

innobackupex 收到 redo 备份完成通知后,就开始解锁,执行 UNLOCK TABLES;

最后 innobackupex 和 xtrabackup 进程各自完成收尾工作,如资源的释放、写备份元数据信息等,innobackupex 等待 xtrabackup 子进程结束后退出。

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

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


备份目录下面的各项文件说明

xtrabackup_checkpoints -- 备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)范围信息;每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

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

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

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

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

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


增量备份

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来启动了。

使用innobackupex还原备份,即调用--copy-back参数来还原备份:
$ innobackupex --coyp-back /home/freeoa/2020-02-23_15-55/

会根据my.cnf复制所有备份到datadir下,然后修改还原数据目录的用户属组,完毕后拉起mysql服务。

注:datadir必须是为空的,innobackupex –copy-back不会覆盖已存在的文件,还要注意,还原时需要先关闭服务,如果服务是启动的,那么就不能还原到datadir。


命令行选项

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)阶段,这对于增量备份非常重要


实际应用中一般是直接使用innobackupex方法,它主要有三种操作方式:
innobackup [--sleep=MS] [--compress[=LEVEL]] [--include=REGEXP] [--user=NAME]
[--password=WORD] [--port=PORT] [--socket=SOCKET] [--no-timestamp]
[--ibbackup=IBBACKUP-BINARY] [--slave-info] [--stream=tar]
[--defaults-file=MY.CNF]
[--databases=LIST] [--remote-host=HOSTNAME] BACKUP-ROOT-DIR
innobackup --apply-log [--use-memory=MB] [--uncompress] [--defaults-file=MY.CNF]
[--ibbackup=IBBACKUP-BINARY] BACKUP-DIR
innobackup --copy-back [--defaults-file=MY.CNF] BACKUP-DIR

1)第一个命令行是热备份mysql数据库。
The first command line above makes a hot backup of a MySQL database.By default it creates a backup directory (named by the current date and time) in the given backup root directory. With the --no-timestamp option it does not create a time-stamped backup directory, but it puts the backup in the given directory (which must not exist). This command makes a complete backup of all MyISAM and InnoDB tables and indexes in all databases or in all of the databases specified with the --databases option. The created backup contains .frm, .MRG, .MYD,.MYI., .TRG, .TRN, .opt, and InnoDB data and log files. The my.cnf options file defines the location of the database. This command connects to the MySQL server using mysql client program, and runs ibbackup (InnoDB Hot Backup program) as a child process.

2)带有--apply-log选项的命令是准备在一个备份上启动mysql服务。
The command with --apply-log option prepares a backup for starting a MySQL server on the backup. This command expands InnoDB data files as specified in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/ibbackup_logfile,and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.The BACKUP-DIR should be a path name of a backup directory created by innobackup. This command runs ibbackup as a child process, but it does not connect to the database server.

3)带有--copy-back选项的命令从备份目录拷贝数据、索引、日志到my.cnf文件里规定的初始位置。
The command with --copy-back option copies data, index, and log files from backup directory back to their original locations. The my.cnf options file defines the original location of the database.The BACKUP-DIR is a path name of a backup directory created by innobackup.

xtrabackup不仅包括了Linux平台的二进制版本和源代码版本,还提供Windows平台的安装版本。使用Xtrabackup对MySQL进行热备份是非常简单的,例如我们使用Xtrabackup自带的innobackupex脚本对整个数据库进行热备份,将数据库拷贝到本地的/db_backup目录:
#innobackupex --user=root --password=password --defaults-file=/etc/my.cnf /home/backup

在备份的同时,将备份文件打包:
#innobackupex --user=root --password=password --defaults-file=/etc/my.cnf --stream=tar /home/backup | gzip >  /home/backup/db.tar.gz

将备份文件直接通过网络备份到一台远程服务器:
#innobackupex --user=root --password=password --defaults-file=/etc/my.cnf --stream=tar /home/backup | ssh dbackup@freeoa-host cat > backup.tar

直接通过ssh端口,将数据库热备份到一台远程的服务器上面去,xtrabackup为MySQL带来了企业级的数据备份机制。

注意:从备份后的tar包解包的时候,需要使用-i参数。


一个很简单的过程描述

源服务器:

1、源服务器创建一个备份的目标目录(/freeoadbak),附加读写权限;
2、用mariabackup --backup --target-dir /freeoadbak --user username --password userpassword ,备份的是服务器上所有数据库,当然也可以加参数--databases来指定要备份数据库;

目标服务器:

1、同样建立一个还原的目标目录,例如mkdir /freeoadbak,附加读写权限;
2、把源服务器上备份的数据库文件拷贝到目标服务器/freeoadbak下;
3、先用mariabackup --prepare --target-dir /freeoadbak --user username --password userpassword,将备份文件规范化,这里可以获得备份文件的备份log节点,有助于主从同步使用,假如有主从同步的话;
4、用 mariabackup --copy-back --target-dir /freeoadbak --user username --password userpassword ,来还原数据库;(记住在还原前清掉数据库目录)
5、将数据库文件的权限修正,chown -R mysql:mysql /var/lib/mysql
6、重启mysql服务器。


与mysqldump对比

1、mysqldump可以查看或者编辑十分方便,它也可以灵活性的恢复之前的数据;mysqldump不关心底层的存储引擎,既适用于支持事务的,也适用于不支持事务的表;

2、mysqldump不能作为一个快速备份大量的数据或可伸缩的解决方案。如果数据库过大,即使备份步骤需要的时间不算太久,但有可能恢复数据的速度也会非常慢,因为它涉及的SQL语句插入磁盘I/O,创建索引等等;

3、对于大规模的备份和恢复,更合适的做法是物理备份,复制其原始格式的数据文件,可以快速恢复,这时候就可以用上xtrabackup。mariadb已经集成了该工具,可执行命令叫mariabackup;mariadb10.1以上版本使用的是mariabackup这个备份工具,而不是xtrabackup,mariabackup可能要单独安装的。如果你备份的是10.3的版本数据库,一定要以10.3版本的数据恢复,否则将无法恢复。

4、xtrabackup的缺点是由于是采取复制物理文件的方式备份,需要大量的磁盘空间,用于存放备份;物理备份工具,在同级数据量基础上,都要比逻辑备份性能好的多,特别是在数据量较大的时候,表现的更加明显。


参考来源

mysql和mariadb备份工具xtrabackup和mariabackup

最新版本:2.2
该版本最主要就是实现对 MySQL 5.6 的基本支持,主要包括诸如:GTID、远程/移动式表空间、独立 undo 表空间、5.6 风格的缓冲池 dump 文件等。

最新版本:8.0


项目参考:http://www.percona.com/docs/wiki/percona-xtrabackup:start

该文章最后由 阿炯 于 2021-10-21 17:33:34 更新,目前是第 3 版。