• MySQL备份小计(二)

    背景

    上一节我们讲述了MySQL原生的一些基本备份方式,满足我们日常的小的备份需求。 今天来讲一个比较牛逼的热备份工具,也是全量备份和恢复的利器。

    Percona XtraBackup(简称PXB)是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle)、Percona Server 和 MariaDB,并且全部开源,是日常备份的良器。

    官网文档:https://www.percona.com/doc/percona-xtrabackup/2.4/index.html

    下载地址:https://www.percona.com/downloads/XtraBackup/LATEST/

    github源代码: https://github.com/percona/percona-xtrabackup

    下载安装

    建议用官方文档里的yum安装方式,方便简单:

    1. root权限执行配置persona官方的yum源:

    yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm

    2. 直接安装最新的24版本:

    yum install percona-xtrabackup-24

    卸载: yum remove percona-xtrabackup 即可。

    其他安装方式请参考官网:

    https://www.percona.com/doc/percona-xtrabackup/2.4/installation.html

    Xtrabackup工具集的简单介绍

    安装完毕后会发现其实他就是几个功能比较强大的脚本:

    yy

    innobackupex

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

    但是,在2.2之后,xtrabackup已经支持了MyISAM的表备份,所以innobackupex已经没有存在的必要了,但是为了照顾到大多数人的使用习惯,还是保留了innobackupex,只不过是xtrabackup的软连接。

    这个脚本在之后可能会渐渐的被取消了。

    xtrabackup

    一个由C编译而来的二进制文件,可以整备MySQL database instance with MyISAM, InnoDB, and XtraDB tables。

    xbcrypt

    用来加密或解密备份的数据。

    xbstream

    用来解压或压缩xbstream格式的压缩文件。

    xbcloud

    实现与云端的xbstream的上传下载等交互。


    Xtrabackup备份过程及原理

    一般我们在做热备份之前,可能会存在如下疑虑和担心,只有搞清楚这些以后,才敢进行备份:

    1. 热备份对服务器性能的冲击有多大?
    2. 热备份过程中会对我的库或者表有锁定吗 ? 有的话粒度多大?
    3. 热备份的效率如何,能满足我在非高峰期的备份需求吗 ?
    4. 热备份出来的结果恢复方便吗 ?能否满足我多种的恢复需求?

    我们根据原理来一一检验这些东西(以下的原理部分摘自阿里的数据库内核月报

    此工具在2.2版本之前,主要是由innobackupex Xtrabackup 来配合工作的,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制。

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

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

    或许你会好奇,一个perl脚本和一个C/C++编译的二进制是如何进行交互的,2个工具之间的交互和协调是通过控制文件的创建和删除来实现的,主要文件有:

    • xtrabackup_suspended_1
    • xtrabackup_suspended_2
    • xtrabackup_log_copied

    举个例子,我们来看备份时 xtrabackup_suspended_2 是怎么来协调2个工具进程的:

    1. innobackupex在启动xtrabackup进程后,会一直等xtrabackup备份完 InnoDB 文件,方式就是等待 xtrabackup_suspended_2 这个文件被创建出来;
    2. xtrabackup在备完 InnoDB 数据后,就在指定目录下创建出这个文件,然后等这个文件被 innobackupex删除;
    3. innobackupex检测到文件 xtrabackup_suspended_2 被创建出来后,就继续往下走;
    4. innobackupex在备份完非 InnoDB 表后,删除 xtrabackup_suspended_2 这个文件,这样就通知xtrabackup可以继续了,然后等 xtrabackup_log_copied 被创建;
    5. xtrabackup检测到 xtrabackup_suspended_2 文件删除后,就可以继续往下了。

    是不是感觉有点不可思议,通过文件是否存在来控制进程,这种方式非常的不靠谱,因为非常容易被外部干扰,比如文件被别人误删掉,或者2个正在跑的备份控制文件误放在同一个目录下,就等着备份乱掉吧,但是 Percona 就是这么干的。

    之所以这么搞,估计主要是因为 perl 和 C 二进制2个进程,没有既好用又方便的通信方式,搞个协议啥的太麻烦了。但是官方也觉得这种方式不靠谱,11年就搞了个 blueprint 要用C重写innobackupex终于在2.3 版本实现了,innobackupex功能全部集成到xtrabackup里面,只有一个 binary,另外为了使用上的兼容考虑,innobackupex作为xtrabackup的一个软链。对于二次开发来说,2.3 摆脱了之前2个进程协作的负担,架构上明显要好于之前版本。考虑到 perl + C 这种架构的长期存在,大多数读者朋友也基本用的2.3之前版本,本文的介绍也是基于老的架构(2.2版本),但是原理和2.3是一样的,只是实现上的差别。

    接下来我们先看看备份过程:

    yy

    图片与内容摘自——http://mysql.taobao.org/monthly/2016/03/07/

     

    注:以下原理只针对2.2版本

    1. innobackupex在启动后,会先fork出一个子进程,启动xtrabackup进程,然后就等待xtrabackup备份完ibd文件;
    2. xtrabackup在备份InnoDB相关数据时,也是有2种线程的。1种是redo拷贝线程,负责拷贝redo文件,一种是ibd拷贝线程,负责拷贝ibd文件; redo 拷贝线程只有一个,在 ibd 拷贝线程之前启动,在 ibd 线程结束后结束。xtrabackup进程开始执行后,先启动 redo 拷贝线程,从最新的 checkpoint 点开始顺序拷贝 redo 日志;然后再启动 ibd 数据拷贝线程,在xtrabackup拷贝ibd过程中,innodbbackup一直处于等待状态(等待文件被创建)。
    3. xtrabackup的ibd拷贝线程拷贝完ibd后, 通知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. 最后innobackupexxtrabackup进程各自完成收尾工作,如资源的释放、写备份元数据信息等,innobackupex等待xtrabackup子进程结束后退出。

    注: InnoDB 和非 InnoDB 文件的备份都是通过拷贝文件来做的,但是实现的方式不同,前者是以page为粒度做的(xtrabackup),后者是 cp 或者 tar 命令(innobackup),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 文件拷贝上有不同。

    数据库备份与恢复实践

    备份

    还原

    xtrabackup重要参数

    –defaults-file
    同xtrabackup的–defaults-file参数

    –apply-log
    对xtrabackup的–prepare参数的封装

    –copy-back
    做数据恢复时将备份数据文件拷贝到MySQL服务器的datadir ;

    –remote-host=HOSTNAME
    通过ssh将备份数据存储到进程服务器上;

    –stream=[tar]
    备 份文件输出格式, tar时使用tar4ibd , 该文件可在XtarBackup binary文件中获得.如果备份时有指定–stream=tar, 则tar4ibd文件所处目录一定要在$PATH中(因为使用的是tar4ibd去压缩, 在XtraBackup的binary包中可获得该文件)。
    在 使用参数stream=tar备份的时候,你的xtrabackup_logfile可能会临时放在/tmp目录下,如果你备份的时候并发写入较大的话 xtrabackup_logfile可能会很大(5G+),很可能会撑满你的/tmp目录,可以通过参数–tmpdir指定目录来解决这个问题。

    –tmpdir=DIRECTORY
    当有指定–remote-host or –stream时, 事务日志临时存储的目录, 默认采用MySQL配置文件中所指定的临时目录tmpdir

    –redo-only –apply-log组,
    强制备份日志时只redo ,跳过rollback。这在做增量备份时非常必要。

    –use-memory=#
    该参数在prepare的时候使用,控制prepare时innodb实例使用的内存量

    –throttle=IOS
    同xtrabackup的–throttle参数

    –sleep=是给ibbackup使用的,指定每备份1M数据,过程停止拷贝多少毫秒,也是为了在备份时尽量减小对正常业务的影响,具体可以查看ibbackup的手册 ;

    –compress[=LEVEL]
    对备份数据迚行压缩,仅支持ibbackup,xtrabackup还没有实现;

    –include=REGEXP
    对 xtrabackup参数–tables的封装,也支持ibbackup。备份包含的库表,例如:–include=”test.*”,意思是要备份 test库中所有的表。如果需要全备份,则省略这个参数;如果需要备份test库下的2个表:test1和test2,则写 成:–include=”test.test1|test.test2″。也可以使用通配符,如:–include=”test.test*”。

    –databases=LIST
    列出需要备份的databases,如果没有指定该参数,所有包含MyISAM和InnoDB表的database都会被备份;

    –uncompress
    解压备份的数据文件,支持ibbackup,xtrabackup还没有实现该功能;

    –slave-info
    假设现在有主库A和从库B,目前想再添加一台备库C,并让备库C以主库A为master;因为主库A是生产库,压力一般比较大,所以我们就在备库B上备份一个数据库,然后把这个备份拿到C服务器上 并导入到C库,接下来再在C服务器上执行change master的命令:其中 master_host是A的ip,而master_log_file和master_log_pos就是这个xtrabackup_slave_info里面的值

    –socket=SOCKET
    指定mysql.sock所在位置,以便备份进程登录mysql.

    其实这个工具也支持部分备份,即只备份一部分库或表,但是恢复起来比较麻烦,容易出错,不建议使用。

    远程备份

    在实际的应用场景中,我们可能经常会遇到跑数据库服务的磁盘空间并不是很空闲,所以最好能备份到远程服务器,这里来说一下这种方式:

    远程备份方式1:tar + gzip

    我们可以在数据库服务器上这样实现:

    如上,我的流方式选的是 –stream=tar 的方式。压缩是放在了远端服务器,这样的一个结果集我们可以在远端服务器看到,并且可以直接使用tar命令解压缩然后使用:

    当然,也可以选择备份在远程机器,只打包不压缩:

    远程备份方式2:xbstream方式

    xbstream是工具本身自带的流方式,我们也可以用它来进行远程的备份和压缩:

    如上,备份到远端以后是一个用xbstream流压缩和打包的后缀为.xbstream的文件,这个文件我们可以用如下方式解开:

    当然,你备份的时候也可以选择不压缩:

     

    参考

    http://mysql.taobao.org/monthly/2016/03/07/

    http://www.cnblogs.com/chenpingzhao/p/4905310.html