xtrabackup的备份原理

  • 软件包安装完成之后一共有4个可执行文件,如下:
usr
├── bin
│   ├── innobackupex
│   ├── xbcrypt
│   ├── xbstream
│   └── xtrabackup

其中最主要的是innobackupexxtrabackup,前者是一个perl脚本,后者是C/C++编译的二进制。

  • xtrabackup是用来备份InnoDB表的,不能备份非InnoDB表,和mysqld server没有交互;innobackupex脚本用来备份非InnoDB表,同时会调用xtrabackup命令备份InnoDB表,还会和mysqld server发送命令进行交互,如加读锁(FTWRL),获取位点(SHOW SLAVE STATUS)等。简单来说,innobackupexxtrabackup之上做了一层封装。
  • 一般情况下我们是希望备份MyISAM表的,虽然我们可能自己不用MyISAM表,但是mysql库下面的系统表示MyISAM的,因此备份基本都通过innobackupex命令进行;另外一个原因是我们可能需要保存位点信息。
  • 另外俩个工具比较小众一些,xbcrypt是加解密用的;`xbstream类似于tar,是Percona自己实现的一种支持并发写的流文件格式。俩者都在备份和解压的时候都会用到(如果备份用到了加密和并发)。

原理

通信方式

2个工具之间的交互和协调是通过控制文件的创建和删除来实现的,主要文件有:

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

通过文件是否存在来控制进程这种方式是非常的不靠谱的,因为非常容易被外部干扰,比如文件被其他人误删除掉,活着2个正在跑的备份控制文件误放在同一个目录下面,那么备份很容易乱掉的。

之所以这么做的原因是因为perl和C二进制2个进程,没有既好用又方便的通信方式,弄个协议的话又太麻烦了,所以才会出现这种方式进行通信。

但是官方在2.3版本实现了将innobackupex功能全部集成到了xtrabackup,只有一个binary,另外为了使用上的兼容考虑,innobackupex作为xtrabackup的一个软链。对于二次开发来说,2.3摆脱了之前2个进程协作的负担,架构上明显要好于之前的版本。

2.3之前版本innobackupex备份流程

Xtrabackup备份原理_第1张图片

  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拷贝完成ibd后,通知innobackupex(通过创建文件),同时自己进入等待(redo拷贝线程任然继续拷贝);
  4. innobackupex受到xtrabackup通知后,执行FLUSH TABLES WITH READ LOCK(FTWRL),取得一致性位点,然后开始备份非InnoDB文件(包括frm,MYD,CSV,opt,par等)。拷贝非InnoDB文件过程中,因为数据库属于全局只读状态,如果在业务的主库备份的话,需要特别小心,非InnoDB(主要是MyISAM)比较多的话那么整个只读的时间就会比较长,这个影响需要评估到;
  5. innobackupex拷贝完所有的非InnoDB表文件之后,通知xtrabackup(通过删除文件),同时自己进入等待(等待另一个文件被创建)
  6. xtrabackup收到innobackupex备份完非InnoDB通知后,就停止redo拷贝线程,然后通知innobackupexredo log拷贝完成(通过创建文件);
  7. innobackupex收到redo备份完成通知后,就开始解锁,执行UNLOCK TABLES;
  8. 最后innobackupexxtrabackup进程各自完成收尾工作,如资源的释放,写备份元数据信息等,innobackupexxtrabackup子进程结束后退出。

在上面描述的文件拷贝,都是备份进程直接通过操作系统读取数据文件的,只在执行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来启动了。

转载

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