首页 > C/C++, 数据库 > mysql数据热备份工具xtrabackup使用介绍

mysql数据热备份工具xtrabackup使用介绍

2013年8月10日 发表评论 阅读评论 7695次阅读    

最近需要用XtraBackup进行mysql数据备份,Gaojie同学推荐的工具,效果还不错,推荐。

详细的介绍请移步上面的链接去官网查看,官网介绍的很清楚了,这里只是就一些容易总结和容易犯的错误等。如果确定数据库的表全部是myisam的表,那就可以简单用“mysql数据热备份脚本-MYISAM表”里的方法做文件备份了,简单的东西总是"更简单可依赖"。

XtraBackup包含2个主要的部分:C程序xtrabackup, perl包装代码innobackupex  , 实际上后者调用了前者,提供一些包装的功能。因为xtrabackup只支持Innodb表,所以innobackupex  额外提供备份myisam表的能力。下面会说一下其原理

XtraBackup的优点有如下:

  1. 热备,不需要停机。对于innodb表,支持完全热备,甚至不需要锁表。对于非日志系的表,如MYISAM表,需要在备份表文件的时候加读锁
    • 对于Innodb表,其备份原理是这样的:基于数据库的LSN,也就是上次修改的序列号,一个64位的整数,每次对数据库修改有一个自增的LSN的。XtraBackup会创建一个后台线程,每秒监控LSN的变化,只要变化了就将变化的步部分拷贝出来,mysql在拷贝ibdata1数据文件的时候,如果在拷贝期间发生了写入操作,那都能够通过后台进程进行监控,从而等到回复的时候将其写入到数据文件即可。
    • 对于MYISAM表,其备份需要通过innobackupex  脚本里面的函数 mysql_lockall锁表:FLUSH TABLES WITH READ LOCK 锁表,然后innobackupex  会通过backup_files将MYISAM表拷贝到备份目录。然后用“UNLOCK TABLES” 解锁。注意这里不能用简单的shell语句操作,因为mysql 的锁机制是一个连接会话退出后,锁会自动解掉,所以备份文件期间必须保证不断开连接。具体见上一篇文章:mysql数据热备份脚本-MYISAM表.
  2. 开源,但也有收费版本,具体区别在这里。基于innodb
  3. 支持全量备份和增量备份,这就满足了数据库很大,但是写入相对少的时候。这时全量备份不断速度很慢,而且也会容易影响线上服务,因此增量备份时很重要的。其增量备份支持基于全量备份做的增量备份。其实原理还是LSN。

一、如何做全量备份

将chenzhenianqing数据库,以及其从库等信息都备份到/home/mysqlbak/base目录下面。命令:

innobackupex --defaults-file=/etc/mysql/my.cnf --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng --slave-info --safe-slave-backup --no-timestamp /home/mysqlbak/base

下面简单介绍下参数:

  1. --slave-info --safe-slave-backup 用来备份slave信息的,比如master的地址,POS位置等。这样就会生成/home/mysqlbak/base/xtrabackup_slave_info  文件,其里面内容如下:

CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000154', MASTER_LOG_POS=73044692

也就是记录了master的log 文件名,以及已经读取的位置,等下次恢复后,可以用这条命令设置slave信息,然后slave start就行了。

  1. --no-timestamp 是让innobackupex 别自动生成一个时间戳的目录名/home/mysqlbak/2013***,而是存放在/home/mysqlbak/base

二、全量备份的恢复

如果数据出问题了,需要恢复的话,可以用上面备份出来的文件恢复数据库。命令为:

#将备份的过程中产生的写入语句,日志合并到ibdata1数据文件中
innobackupex --defaults-file=/etc/mysql/my.cnf --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng  --apply-log --use-memory=4G /home/mysqlbak/base
/etc/init.d/mysql stop

#将数据文件等拷贝到mysql的data目录,然后启动mysql即可。
innobackupex --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng --database="${db}" --copy-back /home/mysqlbak/base
chown -R mysql:mysql ${mysqldatadir}

如果备份的数据库是从库,那么恢复之后,需要将/home/mysqlbak/base/xtrabackup_slave_info 里面的语句运行一下,重新设置一下主库的log日志文件名和路径。因为上次备份以来,同步的位置肯定有变化。我们需要从上次备份的点开始重新同步数据。

/home/mysqlbak/base/xtrabackup_binlog_info 这个文件记录了当前的binlog_info, 如果需要做一个从库的话,这个会游泳的。具体可以参考这里:“How to setup a slave for replication in 6 simple steps with Xtrabackup” 。

 --apply-log 这个参数是关键,告诉innobackupex将log文件的数据合并到ibdata1里面去。
--use-memory=4G 设置最大内存使用大小,可以加快速度。

三、增量备份

增量备份时基于上一次全量备份做的,可以看看这个文件:/home/mysqlbak/base/xtrabackup_checkpoints

backup_type = full-backuped
from_lsn = 0
to_lsn = 1595695
last_lsn = 1595695
compact = 0

backup_type 表示全量备份;
from_lsn 是指这个全量备份时从LSN=0也就是第一条数据开始拷贝的;
last_lsn 拷贝的最后一条改动,增量备份的时候,需要制定全量备份的目录,这样可以找到xtrabackup_checkpoints这个文件然后找到last_lsn,于是增量备份就只备份改动时间大于这个LSN也就是在这个之后改动的数据。这样就不需要拷贝全部数据了。

增量备份的命令为:

innobackupex --defaults-file=/etc/mysql/my.cnf --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng --slave-info --safe-slave-backup --no-timestamp <strong>--incremental --incremental-basedir=/home/mysqlbak/base</strong>  /home/mysqlbak//partial_${time}

上面注明了,--incremental-basedir=/home/mysqlbak/base参数是重点,告诉innobackupex我要从这个全量备份的地方开始做增量备份。
值得一提的是可以基于上一个增量备份再做增量备份。因为它是根据last_lsn的,所以原理上是一样的。

我用多次迭代的增量备份测试过,在小数据库上没有问题,但对大的数据库比如100G的数据库,在恢复的时候会出现提示ibdata1损坏的情况,具体原因没有找到。后来就退而求其次,每天凌晨做一次全量备份,然后每隔一个小时基于这个全量备份做增量备份,这样是没有问题的。知道什么原因的同学麻烦告诉我一下原因,多谢了!

四、增量备份恢复

增量备份恢复跟全量备份差不多,不同的是对于备份文件的操作需要将增量备份的数据合并到全量备份里面,然后覆盖mysql-data的数据。

#处理一下全量备份的数据,将其日志文件重做等,这是需要用redo-only
innobackupex innobackupex --defaults-file=/etc/mysql/my.cnf --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng -redo-only --apply-log --use-memory=4G /home/mysqlbak/base

#指定增量备份目录,将其数据合并到全量备份里面,这个时候千万别用redo-only
innobackupex --defaults-file=/etc/mysql/my.cnf --host=127.0.0.1  -port=3306 --user=root --password=helloworld --database=chenzhenianqng  --slave-info --safe-slave-backup --apply-log --use-memory=4G /home/mysqlbak/base --incremental-dir=/home/mysqlbak/partial_$time

上面的几个参数得说明一下,以免继续碰坑:

-redo-only 这个参数在全量备份恢复的时候是不需要的。在增量备份里面,除了最后一个增量备份aply-log的时候,是需要的,原因是mysql的redo日志,虽然在全量备份的时候备份了,但是恢复的时候很可能在增量备份的时候,数据已经存在于增量备份里面了。也就是说,后面的增量备份里面是有数据的,所以前面不需要做这个改动了。

比较微妙,我被坑过。这里再次引用一下官方文档里“Incremental Backups with innobackupex”的话,千万注意别搞错了,否则数据恢复不好不说,还不一致了。以后自己也得注意,没事在地铁上多看看文档,别坑了自己就睁眼瞎了:

Note
--redo-only should be used when merging all incrementals except the last one. That’s why the previous line doesn’t contain the --redo-only option. Even if the --redo-only was used on the last step, backup would still be consistent but in that case server would perform the rollback phase.

五、需要注意的地方

  1. 如果放到生产环境中定时备份的时候,请务必做好错误判断,比如备份是否成功,失败了做报警;磁盘空间不够了发短信报警等。我是这么做的:将每条命令的任何输出都重定向到一个文件中,命令执行完后,resstr=`tail -1 $outfile | grep "completed OK"`得到是否成功的标志,然后if [ "$resstr" != "" ];then 就成功。否则报警。
  2. 备份完成后定期去看看文件是否能够正常恢复数据,所谓灾难预演,这个很重要的。别到时候傻眼的:数据备份了,down机的时候却发现恢复不了了·····人死了,钱没花完一个道理。
  3. 至于异地备份什么的,得看具体需求了,数据量大的话异地备份很难做的,网络传输太大,并且本身传输也不安全。
  4. 数据操作有风险,任何操作之前请提前备份数据,一个回车敲下去可能就干掉用户对你的全部期待和信任了。
  5. 最后最重要的是:没事在地铁上多看看文档^.^。

写错了的地方麻烦提醒一下,被坑了也麻烦告诉我一下······

Share
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。