如何进行MySQL中的xtrabackup备份恢复

64次阅读
没有评论

共计 8044 个字符,预计需要花费 21 分钟才能阅读完成。

这篇文章给大家介绍如何进行 MySQL 中的 xtrabackup 备份恢复,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

  XtraBackup 是 Percona 推出的一款备份工具,算是对于 mysqldump 的一个补充。对于大批量数据的导入使用 mysqldump 会出现一定的瓶颈,这一点做过一些数据迁移项目的同学可能感同身受。

  数据迁移中的数据量,小有小的好,大有大的招,见招拆招,找到适合的场景是最佳的。

  如果现在去 Percona 官网下载,就会发现最新的版本已经是 2.4.6 了。下载可以选择一个完整的打包,或者逐个的 rpm 根据需求来安装也可以。完整的工具大概在 60M 左右。

  而目前的 MySQL 版本大多都在 5.5,5.6, 对于 5.7 相对来说要新一些。中间会有一些时间的过渡,在多年前,可能相对来说用 2.0 版本一下的还比较多。

  XtraBackup 其实包含两个工具,一个是 xtrabackup,另外一个是 innobackupex。我们暂且以一个较早的版本作为演示,然后使用新版本来对比下。

# xtrabackup –version
xtrabackup version 1.6.5 for Percona Server 5.1.59

innobackupex –version
InnoDB Backup Utility v1.5.1-xtrabackup; Copyright 2003, 2009 Innobase Oy
and Percona Inc 2009-2012.  All Rights Reserved.

  可以看到这两个工具的版本还有一些差别,

xtrabackup 主要是用于热备份 innodb, 或者是 xtradb 表中数据的工具,不能备份其他类型的表,也不能备份数据表结构;

innobackupex 是将 xtrabackup 进行封装的 perl 脚本,可以备份和恢复 MyISAM 表以及数据表结构。

  所以总体来看 InnoDB 的使用场景虽然最为普遍,但是还得考虑到 MyISAM, 两者总体来说,使用 innobackex 的场景会多一些。

备份浅析

  使用 innobackupex 备份,命令选项还不少,可以使用 innobackupex –help 来查看明细的参数使用。

比如我需要做一个全备。可以采用如下类似的方式,在备份命令中加几个辅助选项,备份使用 socket 连接,备份目录在 /home/databak/full/20170322 下。

innobackupex –socket=/home/mysql/mysql.sock  /home/databak/full/20170322  –no-timestamp –no-lock –throttle=100 备份后查看对应的目录,备份的数据情况如下,其中红色的几个文件是备份中额外生成的。整体看来和源库的目录结构一样。

# du -sh ./*
2.6G  ./backend
4.0K  ./backup-my.cnf
646M  ./gm
1.0G  ./ibdata1
99M  ./mobile_activity
5.0G  ./mobile_billing
1.1M  ./mysql
2.0G  ./oem_mon
212K  ./performance_schema
112K  ./test
4.0K  ./xtrabackup_binary
4.0K  ./xtrabackup_checkpoints
4.0K  ./xtrabackup_logfile 对于上面生成的文件,我们简单看一下。

binary 结尾的文件是备份中用到的可执行文件,这个可以对应几个版本,比如 xtrabackup_51,xtrabackup_55 等

# more xtrabackup_binary
xtrabackup_55logfile 结尾的文件的内容无法直接查看,但是可以用 strings 来看。通过 strings 解析可以看到对应的二进制日志,当然事务的 Xid 也有的。

# strings xtrabackup_logfile
xtrabkup 170322 16:33:40
{  {
  {
MySQLXid
./mysql-bin.000009
  393102654
08360000000039DB 下面的这个文件就更特别了,这个是作为数据的备份恢复的关键,里面有着备份恢复所有的检查点 LSN, 从下面的数据来看,这是一个全备,因为 from_lsn=0.

# cat xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 30754980731
last_lsn = 30754980731

而在源库的目录结构下,我们稍作过滤,也会得到一个几乎和这个工具备份出来一样的目录结构来。 

# du -sh ./*|grep -v mysql-bin|grep -v innodb|grep -v log
2.6G  ./backend
646M  ./gm
1.0G  ./ibdata1
4.5M  ./ib_lru_dump
99M  ./mobile_activity
5.0G  ./mobile_billing
1.1M  ./mysql
4.0K  ./mysql.pid
0  ./mysql.sock
2.0G  ./oem_mon
212K  ./performance_schema
112K  ./test 所以 xtrabackup 这样一个工具就是一个热备工具,有点类似有文件级别的拷贝,但是不止于此,我们往下看。 

全库恢复模拟

  数据恢复是 DBA 最重要的工作之一,多年之前,这个“之一“的字眼还要去掉。数据无法恢复,则备份无意义。

  数据的恢复还是使用 innobackupex 这个工具,这是参数有些差别。

 
这里的数据恢复分为两个步骤,prepare 和还原恢复,prepare 的意义就在于,如果我们备份数据的时候,存在未提交的事务,但是数据却存在于备份中,这样就是一个数据不一致的状态,在启动数据库的时候需要走一个前滚,然后是一个回滚的操作。这个体现主要就在于 logfile 和 ibdata。是使用 apply-log 这个选项实现的。

  我们使用如下的方式来做。

innobackupex –defaults-file=/home/databak/full/20170322/backup-my.cnf –user=root –apply-log /home/databak/full/20170322 这个过程其实就会隐式调用 xtrabackup_55 这个可执行文件,调用的命令类似于:

xtrabackup_55  –defaults-file= /home/databak/full/20170322/backup-my.cnf 默认会使用 100M 的内存,也可以使用选项 –use-memory 来调整,整个过程会重构 redo 日志文件和 ibdata.

  这个步骤完成之后就是最关键的地方了,还原恢复。这个过程是使用 copy-back 的选项实现的。

innobackupex –defaults-file=/home/databak/full/20170322/backup-my.cnf –user=root –copy-back /home/databak/full/20170322 整个过程就是大量的拷贝工作。

完成之后需要修改一下文件的属主,默认是 root, 然后启动即可。

增量备份恢复

  我们接下来看看增量备份和恢复,先来创建一些数据。我们在数据库 test 下创建一个表 test2.

create table test2 (id int);
Query OK, 0 rows affected (0.01 sec)
insert into test2 values(1),(2);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

因为刚刚已经做了全备,我们继续做一个增备。

使用的命令如下:

 innobackupex –defaults-file=/etc/my.cnf –user=root –incremental-basedir=/home/databak/incre/20170322 –incremental
/home/databak/incre/20170322 但是很不幸,执行失败了。这个错误带有典型的意义。

170322 18:05:34  innobackupex: Starting ibbackup with command: xtrabackup_55  –defaults-file= /etc/my.cnf –backup –suspend-at-end –target-dir=/home/databak/incre/20170322/2017-03-22_18-05-32 –incremental-basedir= /home/databak/incre/20170322
innobackupex: Waiting for ibbackup (pid=4079) to suspend
innobackupex: Suspend file /home/databak/incre/20170322/2017-03-22_18-05-32/xtrabackup_suspended

xtrabackup: Error: cannot open /home/databak/incre/20170322/xtrabackup_checkpoints
xtrabackup: error: failed to read metadata from /home/databak/incre/20170322/xtrabackup_checkpoints
innobackupex: Error: ibbackup child process has died at /usr/bin/innobackupex line 349. 原因就在于里面的一个关键文件 _checkpoints

使用增备得有一个参考点,从哪里开始,即从哪个 LSN 开始,这个 LSN 在指定的参数 –incremental-basedir=/home/databak/incre/20170322 下不存在,因为这个是一个新目录,所以需要指向全库备份的目录。

  然后修复后备份就没问题了,英为有了这个参考点 LSN,所以需要要说明的是这个备份其实有累计增量和差异增量了。

  这个怎么理解呢,比如周日做一个全备,周一做一个增备,周二做一个周日全备到周二的一个增备,这就是一个累计增量备份,而周三的时候做一个周二至周三数据变化的备份,就是一个差异增量备份。

  下面的是一个累计增量备份。因为基准是上次的一个全备,备份后会自动生成一个目录,比如 2017-03-22_18-07-38

  innobackupex –defaults-file=/etc/my.cnf –user=root –incremental-basedir=/home/databak/full/20170322 –incremental
/home/databak/incre/20170322  为了区别两次增量,我继续插入两行数据。

insert into test2 values (3),(4);
Query OK, 2 rows affected (0.00 sec)  这样表 test2 就有 4 条数据了,每次插入 2 条。

  下面的是一个差异增量备份。基于上一次的增备。

 innobackupex –defaults-file=/etc/my.cnf –user=root –incremental-basedir=/home/databak/incre/20170322/2017-03-22_18-07-38 –incremental /home/databak/incre/20170322  整个恢复的过程是下面的形式,还是一个 prepare 的过程,首先是全备:

innobackupex –defaults-file=/etc/my.cnf –user=root –apply-log –redo-only /home/databak/full/20170322 然后是增备,注意这里标红的参数。

innobackupex –defaults-file=/etc/my.cnf –user=root –apply-log –redo-only /home/databak/full/20170322 –incremental-dir=/home/databak/incre/20170322/2017-03-22_18-07-38 这样做其实是一个 merge 的过程,对于增备来说,会生成如下的几个文件,都是.delta, .meta 之类的文件。

[test]# ll
total 132
-rw-r–r– 1 mysql mysql  61 Mar 22 17:58 db.opt
-rw-rw—- 1 mysql mysql  8556 Mar 22 18:03 test2.frm
-rw-r–r– 1 root  root  81920 Mar 22 18:08 test2.ibd.delta
-rw-r–r– 1 root  root  18 Mar 22 18:08 test2.ibd.meta

增备目录下的 checkpoint 文件就有意思了。有一个很清晰的 LSN 的增量描述。

[2017-03-22_18-07-38]# cat *checkpoints
backup_type = incremental
from_lsn = 30754980731
to_lsn = 30754984465
last_lsn = 30754984465 而 prepare 之后的全备里面的 checkpoint 文件其实已经发生了变化

# cat *checkpoints
backup_type = full-prepared
from_lsn = 0
to_lsn = 30754984465
last_lsn = 30754984465 这个时候我们使用如下的方式来还原恢复。

#innobackupex –defaults-file=/etc/my.cnf –user=root –copy-back /home/databak/incre/20170322/2017-03-22_18-07-38 这个时候表 test2 里面的数据是几条?是 2 条。

  这个过程我们相当于完成了一个全备 + 一个增备的数据恢复过程。

  而我们在一个增备之后又插入了一些数据,这个怎么继续恢复呢,还是 prepare 的过程。这个路径需要注意,还是 merge 到全备中。

innobackupex –defaults-file=/etc/my.cnf –user=root –apply-log –redo-only /home/databak/full/20170322 
–incremental-dir=/home/databak/incre/20170322/2017-03-22_18-11-26 继续还原恢复。

innobackupex –defaults-file=/etc/my.cnf –user=root –copy-back /home/databak/full/20170322 再次查看数据, 我们要恢复的 4 条数据都恢复回来了。

select *from test2;
+——+
| id  |
+——+
|  1 |
|  2 |
|  3 |
|  4 |
+——+
4 rows in set (0.06 sec)

备份中的选项补充

innobackupex 中的选项很多,有几个还是比较有特色的,比如 stream 选项,–slave-info 选项能够方便搭建从库,生成偏移量的信息,比如并行 –parallel 等,还可以根据 LSN 来备份,选项是 –incremental-lsn

对于 stream 选项,默认是打包,可以结合管道来实现压缩,比如:innobackupex –defaults-file=/etc/my.cnf –user=root –stream=tar 
/home/databak/full/20170322_2 | gzip
/home/databak/full/20170322_2/20170322_2.tar.gz 

备份中的常用场景

  很多时候其实我不想备份整个库,我只想备份一个表,那么这个操作如何来实现呢。

innobackupex –defaults-file=/etc/my.cnf –user=root –include= test.test2   /home/databak/full/20170322_2 这里有几点需要注意,工具还是会逐个去扫描,只是那些不符合的会被忽略掉,也就意味着备份出来的情况和全备的目录结构是一样的,但是指定的表会备份出 ibd,frm 文件。

[test]# ll
total 1036
-rw-r–r– 1 mysql mysql  8556 Mar 22 18:34 test2.frm
-rw-r–r– 1 root  root  1048576 Mar 22 19:26 test2.ibd
[test]# cd ../mysql
[mysql]# ll
total 0 而且有一点值得吐槽一下的是,ibdata 也会完整备份出来,如果这个文件很大,那就相当不给力了。

不过也别对这种备份失去信心,有一个场景还是很实用的。那就是迁移表。

迁移表

  还是刚刚的这个场景,如果表 test2 需要拷贝到另外一套环境中,我们可以使用 Innobackupex 来做物理备份,然后还原导入,达到迁移的目的。

下面的命令会声明指定目录下的备份需要导出对象。 innobackupex –apply-log –export /home/databak/full/20170322_2/2017-03-22_19-26-46 这个过程的直接产物就是生成了一个.exp 文件,在 MySQL 原生版本中是.cfg 文件

[test]# ll
total 1052
-rw-r–r– 1 root  root  16384 Mar 22 19:29 test2.exp
-rw-r–r– 1 mysql mysql  8556 Mar 22 18:34 test2.frm
-rw-r–r– 1 root  root  1048576 Mar 22 19:26 test2.ibd 对表 test2 做数据信息截断。

alter table test2 discard tablespace;
Query OK, 0 rows affected (0.07 sec) 然后就是物理拷贝,复制.exp 文件和.ibd 文件到指定目录下,修改属主权限。

然后使用 import 的方式即可完成导入。

alter table test2 import tablespace;
Query OK, 0 rows affected (0.00 sec) 有另外一点值得说的是,这个.exp 文件是不是必须的,其实也不是。

我们只拷贝.ibd 文件也照样可以。可能在新版本中会有一些警告提示,我们重新来做一下。

[test] alter table test2 discard tablespace;
Query OK, 0 rows affected (0.03 sec) 同时删除刚刚拷贝过来的.exp 文件。

然后拷贝 ibd 文件到指定目录,赋权限

导入表空间信息。

[test] alter table test2 import tablespace;
Query OK, 0 rows affected (0.00 sec) 查看数据的情况,发现数据还是回来了。

[test] select *from test2;
+——+
| id  |
+——+
|  1 |
|  2 |
|  3 |
|  4 |
+——+
4 rows in set (0.00 sec) 当然这个过程中还是有很多需要注意的地方。

关于如何进行 MySQL 中的 xtrabackup 备份恢复就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-19发表,共计8044字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)