xtrabackup使用详解

原理:

    在InnoDB内部会维护一个redo日志文件,我们也可以叫做事务日志文件。事务日志会存储每一个InnoDB表数据的记录修改。当InnoDB启动时,InnoDB会检查数据文件和事务日志,并执行两个步骤:它应用(前滚)已经提交的事务日志到数据文件,并将修改过但没有提交的数据进行回滚操作。

    Xtrabackup在启动时会记住log sequence number(LSN),并且复制所有的数据文件。复制过程需要一些时间,所以这期间如果数据文件有改动,那么将会使数据库处于一个不同的时间点。这时,xtrabackup会运行一个后台进程,用于监视事务日志,并从事务日志复制最新的修改。Xtrabackup必须持续的做这个操作,是因为事务日志是会轮转重复的写入,并且事务日志可以被重用。所以xtrabackup自启动开始,就不停的将事务日志中每个数据文件的修改都记录下来。上面就是xtrabackup的备份过程。

接下来是准备(prepare)过程。在这个过程中,xtrabackup使用之前复制的事务日志,对各个数据文件执行灾难恢复(就像mysql刚启动时要做的一样)。当这个过程结束后,数据库就可以做恢复还原了。

过程是备份---->准备。就是说:先将文件全部复制过来,再根据事务日志对部分操作进行回滚。

以上的过程在xtrabackup的编译二进制程序中实现。程序innobackupex可以允许我们备份MyISAM表和frm文件从而增加了便捷和功能。

Innobackupex会启动xtrabackup,直到xtrabackup复制数据文件后,然后执行FLUSH TABLES WITH READ LOCK来阻止新的写入进来并把MyISAM表数据刷到硬盘上,之后复制MyISAM数据文件,最后释放锁。

备份MyISAM和InnoDB表最终会处于一致,在准备(prepare)过程结束后,InnoDB表数据已经前滚到整个备份结束的点,而不是回滚到xtrabackup刚开始时的点。这个时间点与执行FLUSH TABLES WITH READ LOCK的时间点相同,所以myisam表数据与InnoDB表数据是同步的。

类似oracle的,InnoDB的prepare过程可以称为recover(恢复),myisam的数据复制过程可以称为restore(还原)。

xtrabackup的安装:

官网下载rpm包或者tar.gz包解压就能用,此外需要通过epel的yum安装依赖包libev

# yum install libev -y

# rpm -ivh percona-xtrabackup-24-2.4.3-1.el6.x86_64.rpm

rpm包释放的可执行文件如下:

/usr/bin/innobackupex    # 封装过的perl脚本

/usr/bin/xbcloud

/usr/bin/xbcloud_osenv

/usr/bin/xbcrypt

/usr/bin/xbstream

/usr/bin/xtrabackup      # 主程序

xtrabackup的使用:

1、完全备份

# innobackupex --user=DBUSER --password=SECRET /path/to/backup/dir/

生成的是一个以当前日期命名的文件夹。

如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

> GRANT PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'bkpuser'@'localhost' IDENTIFIED BY '123456';

> FLUSH PRIVILEGES;

使用innobakupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关文件(.frm)、以及MyISAM、MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存至一个以时间命名的目录中。

在备份的同时,innobackupex还会在备份目录中创建如下文件:

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

每个InnoDB页(通常为16k大小)都会包含一个日志序列号,即LSN。LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的。

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

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

(4)xtrabackup_binary:备份中用到的xtrabackup的可执行文件;

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

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

完全备份\恢复示例:

备份

在node1上执行:

# /etc/init.d/mysqld stop

# innobackupex --user=root --password=xxxx --no-timestamp /backups/

# scp -rp /backups/ root@node2:/tmp

恢复

在node2上执行恢复:

1、node2上停止mysql服务(如果启动的话),并删除mysql的数据目录下所有文件: 

# /etc/init.d/mysqld stop

# rm -fr /data/mysql/*

2、在node2上执行整理操作:

# innobackupex --apply-log /tmp/backups/

3、在node2上执行恢复操作,并修改文件属主属组:

# innobackupex --copy-back /tmp/backups/

# chown -R mysql.mysql /data/mysql/*

4、在node2上启动mariadb服务:

# /etc/init.d/mysqld start

2、增量备份

每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长。这正是InnoDB表可以进行增量备份的基础,即innobackupex通过备份上次完全备份之后发生改变的页面来实现。

要实现第一次增量备份,可以使用下面的命令进行:

# innobackupex --user=root --password=xxxx --incremental /backup --incremental-basedir=BASEDIR

其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据。另外,在执行过增量备份之后再一次进行增量备份时,其--incremental-basedir应该指向上一次的增量备份所在的目录。

注意: 增量备份仅能应用于InnoDB或XtraDB表,对于MyISAM表而言,执行增量备份时其实进行的是完全备份。

“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:

(1)需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”。“重放”之后,所有的备份数据将合并到完全备份上。

(2)基于所有的备份将未提交的事务进行“回滚”。

于是,操作就变成了:

# innobackupex --apply-log --redo-only BASE-DIR

接着执行:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

而后是第二个增量:

# innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上的操作;

增量备份、恢复示例:

1、先做一个完全备份

# innobackupex --user=root /backups/  会在/backups/下生成一个以当前时间命名的文件夹。如下图:

2、对数据表执行些修改等操作

【数据表的修改操作略过】

3、执行增量备份

# innobackupex --incremental /backups/ --incremental-basedir=/backups/2015-11-08_19-24-05

说明:

有时候查看增量备份的文件中的xtrabackup_checkpoints发现其数值没变化,可能是LSN变化太小了。执行大量的数据表修改等操作后,会发现其LSN是会变化的,有时候不变也是正常的。

补充个脚本的方式执行全备份、增量备份:
全备份:
innobackupex --user=root --password=123456 /backups/  
增量备份:
innobackupex --user=root --password=123456 --incremental /backups/  --incremental-basedir=/backups/$(ls -l /backups| awk '{print $NF}'|tail -1)
# 将上面的2个添加到cron计划任务即可,备份的路径是/backups/目录下。

4、合并备份文件

# innobackupex --user=root --password=123456 --apply-log-only --redo-only /backups/2015-11-08_19-57-53/

# innobackupex --user=root --password=123456 --apply-log-only --redo-only /backups/2015-11-08_19-57-53/ --incremental-dir=/backups/2015-11-08_19-59-31/

# cat /backups/2015-11-08_19-57-53/xtrabackup_checkpoints # 检验是否合并成功

5、执行恢复数据到数据库的操作

# innobackupex --user=root --password=123456 --copy-back /backups/2015-11-08_19-57-53/   【注意这里填的应该是basedir的路径】

# ls -lh /data/mysql/   查看文件是否恢复 

# chown -R mysql.mysql /data/mysql/  修改文件权限 

6、启动MySQL查看是否数据已恢复

# /etc/init.d/mysqld start

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杰的记事本

ES6 Promise简单讲解

Promises are a simple concept, and even if you haven’t had a chance to use them,...

9130
来自专栏web秀

10分钟了解JavaScript Async/Await

在过去很长的一段时间里,JavaScript开发人员不得不依赖回调来处理异步代码。如果遇到赋值的逻辑,会发现,特别难处理维护,代码看起来也特别的糟糕。

11440
来自专栏web秀

Vue.js 如何使用 Socket.IO ?

在很多需求业务中,都需要浏览器和服务器实时通信来实现功能,比如:扫码登录(扫码后,手机确认登录,PC网页完成登录并跳转)、订单语言提醒等,这些都是建立在两端实时...

12120
来自专栏前端小课堂

重新理解前端系列 — AMD、CMD

本文主要是针对之前一些熟悉的前端概念,再次回顾的时候,结合自己的开发经验和使用,进行再次理解。经过了开发和线上使用之后,会有更为深刻的印象。对比requirej...

11010
来自专栏web秀

vue面试题 vue-cli相关知识点(一)

1、vue.js:vue-cli工程的核心,主要特点是 双向数据绑定 和 组件系统。 2、vue-router:vue官方推荐使用的路由框架。 3、vuex...

17120
来自专栏web秀

Axios是什么?用在什么场景?如何使用?

Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post请求。说到get、post,大家应该第一时间想到的就是Jquery...

14010
来自专栏web秀

Vue如何创建自定义指令?

什么是vue指令了? Vue自带的指令很多,v-for/v-if/v-else/v-else-if/v-model/v-bind/v-on/v-show/v-...

7220
来自专栏web秀

Node应用的进程管理器: PM2详细介绍

这里的PM2,不是PM2.5,跟空气没有半毛钱的关系。它是NodeJs应用的进程管理器,可以利用它来简化很多Node应用管理的繁琐任务,如性能监控、自动重启、负...

8920
来自专栏女程序员的日常_Lin

package-lock.json和package.json

package-lock.json就是锁定安装时的包的版本号,以保证其他人在npm install时大家的依赖能保持一致。

39540
来自专栏秦子帅

Okhttp3源码解析(3)-Call分析(整体流程)

想起来了吧?无论是get还是post请求 都要生成call对象,在上面我们发现call实例需要一个okHttpClient与request实例 ,我们先点进C...

9710

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励