Percona XtraBackup 备份原理说明【转】

本文来自:http://mysql.taobao.org/monthly/2016/03/07/mysql

前言

Percona XtraBackup(简称PXB)是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQL(Oracle)、Percona Server 和 MariaDB,而且所有开源,真可谓是业界良心。咱们 RDS MySQL 的物理备份就是基于这个工具作的。nginx

项目的 blueprint 和 bug 讨论放在 Launchpad,代码以前也放在 Launchpad,如今已经迁移到 Github 啦,项目更新发布很是快,感兴趣的能够关注 :-)git

本文会介绍下备份工具的工做原理,但愿对你们有所帮助。github

工具集

软件包安装完后一共有4个可执行文件,以下:sql

usr ├── bin │ ├── innobackupex │ ├── xbcrypt │ ├── xbstream │ └── xtrabackup 

其中最主要的是 innobackupex 和 xtrabackup,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制。数据库

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

通常状况下,咱们是但愿能备份 MyISAM 表的,虽然咱们可能本身不用 MyISAM 表,可是 mysql 库下的系统表是 MyISAM 的,所以备份基本都经过 innobackupex 命令进行;另一个缘由是咱们可能须要保存位点信息。并发

另外2个工具相对小众些,xbcrypt 是加解密用的;xbstream 相似于tar,是 Percona 本身实现的一种支持并发写的流文件格式。两都在备份和解压时都会用到(若是备份用了加密和并发)。app

本文的介绍的主角是 innobackupex 和 xtrabackup工具

原理

通讯方式

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是同样的,只是实现上的差异。

备份过程

整个备份过程以下图:


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 拷贝线程,而后通知 innobackupexredo 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来启动了。

相关文章
相关标签/搜索