小库可每天完整备份,也用不了多少时间

大数据量备份与还原,始终是个难点。MYSQL超10G,mysqldump导出就比较慢了

MySQL自带工具并不支持真正的增量备份,二进制日志恢复是基于时间点的恢复而不是增量备份

xtrabackup,Percona CTO Vadim参与开发基于InnoDB的在线热备工具,开源,免费,备份恢复速度快(mysqldump 为单线程),占用磁盘空间小,不同情况下的多种备份形式

支持 MySQL、MariaDB 和 Percona

可提供的流备份,可以直接保存到远程机器上(本机硬盘空间不足时很有用)

或是搭建主从,用流式备份大大简化备份后的压缩复制的开销

背书,Facebook 早期用它进行增量备份

XtraBackup 是物理备份,速度很快,能自动验证备份是否有效,自带增量和差异备份功能,在上面功能实现的同时还是热备,对很多公司应用场景来说,已经算是强大到无以复加了

xtrabackup包含两个主要的工具,xtrabackup和innobackupex

  1. xtrabackup只能备份innodb和xtradb引擎的表,不能备份myisam引擎的表

  2. innobackupex前身是封装了xtrabackup的Perl脚本,后重写成可执行文件,支持同时备份innodb和myisam,对myisam备份时需要加一个全局的读锁。myisam不支持增量备份

xtrabackup中不备份表结构,innobackupex调用xtrabackup子线程后再备份表结构,故常用innobackupex,xtraback不做日常使用

备份方式

  • 热备:读写不受影响(mysqldump–>innodb)
  • 温备:仅可以执行读操作(mysqldump–>myisam)
  • 冷备:离线备份,读写都不可用
  • 逻辑:将数据导出文本文件中(mysqldump)
  • 物理:将数据文件拷贝(xtrabackup、mysqlhotcopy)
  • 完整:备份所有数据
  • 增量:仅备份上次完整备份或增量备份以来变化的数据
  • 差异:仅备份上次完整备份以来变化的数据

增量备份和物理备份原理

根据 InnoDB (XtraDB) 存储引擎底层数据结构保存机制进行备份

存储引擎最小磁盘单位“页”里的FIL_PAGE_LSN值,储在页的File Header,代表该页最后被修改的日志序列位置 LSN(Log Sequence Number,逻辑单元号)

页数据更改了之后,页的LSN 也会改变

SHOW ENGINE InnoDB STATUS\G

InnoDB 每个 page 有 LSN 号,LSN 全局递增,page 被更改时会记录当前的 LSN 号,page中的 LSN 越大,说明当前page越新(最近被更新)

每次备份会记录当前备份到的LSN(xtrabackup_checkpoints文件),增量备份就是只拷贝LSN大于上次备份的page,比上次备份小的跳过,每个 ibd 文件最终备份出来的是增量 delta 文件


物理备份,不锁表,怎么保证现有的数据(备份过程中有尚未提交或已经提交但未同步事务)与复制出来的数据一致?

MySQL修改操作先记在ib_logfile,再同步到磁盘,这个文件并重复使用

复制期间开一个线程监控ib_logfile,有修改就从上次记录的lsn开始复制新增内容到Logfile文件

复制结束后,把logfile事务日志回滚,把未完成的事务同步到ibdata1和ibd里面,来保证数据一致性。这与Mysql崩溃后恢复基本操作一样

数据一致性解决方案

LSN只解决增量备份问题,数据备份时还要考虑数据的一致性(备份时DB还在被不停修改中)

mysqldump 通过 MVCC 和全局读锁保证数据一致性

长时间备份中,没有一致性保障,可能整个备份不在一个时刻,甚至有的页头尾不一致,数据错误,导致数据不可用

XtraBackup并没有在备份的过程中保证数据是一个时刻的,但它在备份开始前,先启动 xtrabackup_log 进程,将备份过程中变动的事务日志也备份过来

且它不管数据库的变动,直接备份磁盘数据

备份完成之后,XtraBackup会得到两份数据,一份为损坏的数据文件,还有一份是在备份过程中所有的事务日志,这两份数据组合在一起,就好像 MySQL 崩溃之后的数据,完整的事务日志文件和损坏的数据文件

XtraBackup 有专门的操作来处理这些数据。这个过程叫做准备(prepare),“准备”的主要作用是通过回滚未提交的事务及同步已经提交的事务至数据文件让数据文件处于一致性状态。这样数据的一致性也能有保障了

虽然有事务日志,但是利用错误的数据进行数据恢复是不会有可能会出问题?

这个涉及事务中的持久性,在支持事务的存储引擎设计之初,就考虑到了数据库崩溃,服务器崩溃,忽然断电这些情况。并且还能在这些情况保证数据的持久性,在 InnoDB 存储引擎和 XtraBackup 存储引擎中,这个持久性就是依赖事务日志来完成

步骤图

备份

备份开始时会启一个后台检测进程,实时检测mysql redo的变化,一旦发现redo中有新的日志写入,立刻将日志记入后台日志文件xtrabackup_log中

之后复制innodb数据文件和系统表空间文件ibdata1

复制结束后,flush tables with read lock(防止数据表发生DDL操作,并且在这一时刻获得binlog的位置),复制.frm,MYI,MYD,等文件

最后unlock tables,把表设置为可读可写状态,最终停止xtrabackup_log

全备恢复

启动xtrabackup内嵌的innodb实例

回放xtrabackup日志xtrabackup_log,将提交的事务信息变更应用到innodb数据/表空间

回滚未提交的事务(类似innodb的实例恢复)

增量备份

“增量”处理,主要是相对innodb而言,对myisam和其他存储引擎而言,仍然是全拷贝(全备份)

“增量”备份的过程主要是通过拷贝innodb中有变更的”页”(”页”的LSN大于xtrabackup_checkpoints中给定的LSN)

增量备份基于全备,第一次增备的数据要基于上一次的全备,之后的每次增备都是基于上一次的增备,最终达到一致性的增备

增量备份和全备的过程很类似,区别仅在第2步

增量备份恢复

和全备恢复类似,也需要两步

一、数据文件的恢复

数据来源由3部分组成:全备份,增量备份和xtrabackup log

二、对未提交事务的回滚

锁表时间

innobackupex锁表时间是 data及log文件copy结束时,才锁表,锁表时长为拷贝non-InnoDB tables and files的时长,相对时间较短,对业务影响小

demo

http://www.percona.com/downloads/XtraBackup

yum -y install   perl-DBD-MySQL  perl-Digest-MD5 libev
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.9/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.9-1.el7.x86_64.rpm

备份

全量
innobackupex --user=root --password='root' mysql_backup 
流式并压缩
innobackupex --defaults-file=/etc/my.cnf --user=root   --password='root'  --stream=tar  mysql_backup | gzip > mysql_backup/`date +%F_%H-%M-%S`.tar.gz

还原前的准备

原理已经讲过,备份的数据是有问题的数据加上无问题的事务日志,在还原之前需要执行准备操作

innobackupex --defaults-file=/etc/my.cnf --user=root   --password='root'  --apply-log /root/mysql_backup/2018-03-24_16-42-41

恢复

数据的恢复和逻辑备份的数据恢复不同,XtraBackup 数据恢复需要将数据库先停止

systemctl stop mysqld
innobackupex --defaults-file=/etc/my.cnf --user=root   --password='root'   --copy-back   /root/mysql_backup/2018-03-24_16-42-41

增量备份和差异备份及其还原

增量和差异备份实现差不多,一个是在全量备份的基础上进行备份,另一个在增量备份的基础或者在其他差异备份的基础上再进行备份

可把增量备份看作略特殊的差异备份

以差异备份做演示

全量备份

innobackupex --user=root --password='root' mysql_backup   

增量和差异备份

第一次进行的,既可以叫增量备份,也可以叫差异备份

XXXX curd

增量(差异)备份

innobackupex --user=root  --password=root --incremental xxx --incremental-basedir=xxx
  • —incremental $BACKUP_DIR1

此次是增量备份,以--incremental-basedir指定的目录为基础。$BACKUP_DIR1是此次备份的备份目录

  • —incremental-basedir=$BACKUP_DIR2

指定增量备份的基础目录$BACKUP_DIR2是基础备份目录,此次增量(差异)备份会以里面的 LSN 为基础再进行备份

再进行一次差异备份

xxxx curd

innobackupex --user=root --password=root --incremental /backups/ --incremental-basedir=上次的增量备份地址

上面不同,上面一次--incremental-basedir指定的目录为全量备份目录,而这个指定的是一个差异备份目录,所以这个备份也是差异备份

差异备份的还原

为完全备份做“准备”,在有增量备份的情况下,需要–redo-only选项来保证未commit的事务也执行

innobackupex --apply-log --redo-only 全备地址

当全量备份做了操作之后,中间的差异备份,也需要执行和完全备份一样的”准备”

innobackupex --apply-log --redo-only 全备地址 --incremental-dir=xxx

当前面的差异备份都完成之后,最后一个差异备份需要注意,它不需要再进行 --redo-only 操作,同理,如果是增量备份,增量备份也不需要这个操作

innobackupex --apply-log 全备地址 --incremental-dir=xxx2

恢复操作

systemctl stop mysqld
mv /var/lib/mysql/ xxx
innobackupex --copy-back 全备地址
systemctl start mysqld