ITPub博客

xtrabackup实现MySQL自动备份恢复

原创 作者:彩伦 时间:2018-03-21 17:20:36 0 删除 编辑

 

refencen    https://www.cnblogs.com/waynechou/p/xtrabackup_backup.html#_label2

http://www.cnblogs.com/waynechou/p/xtrabackup_intro.html

http://blog.csdn.net/jiao_fuyou/article/details/62217386

http://blog.csdn.net/yangzhawen/article/details/44857097

http://blog.csdn.net/yangzhawen/article/details/44941435

 

 

1. xtrabackup原理

1.1 xtrabackup简介

XtraBackup(PXB) 工具是 Percona 公司用 perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQlOracle)、Percona Server MariaDB,并且全部开源,真可谓是业界良心。阿里的 RDS MySQL 物理备份就是基于这个工具做的。由于是采取物理拷贝的方式来做的备份,所以速度非常快,几十G数据几分钟就搞定了,而它巧妙的利用了mysql 特性做到了在线热备份,不用像以前做物理备份那样必须关闭数据库才行,直接在线就能完成整库或者是部分库的全量备份和增量备份。新版本的xtrabackup改成了cmake安装,和以前有点不一样。

 

版本说明:这里安装的版本是2.4.6,而2.3.3之后不备份死锁了,如果数据库是mysql 5.7之后的必须要装2.4.4才可以用,当然了, 会向下兼容的。

 

工具集:软件包安装后,有以下可执行文件(版本2.4.6

bin/

├── innobackupex -> xtrabackup

├── xbcloud

├── xbcloud_osenv

├── xbcrypt

├── xbstream

└── xtrabackup

 

其中最主要的是 innobackupex xtrabackup,前者是一个 perl 脚本,后者是 C/C++ 编译的二进制。Percona 2.3 版本用C重写了 innobackupex innobackupex 功能全部集成到 xtrabackup 里面,只有一个 binary,另外为了使用上的兼容考虑,innobackupex 作为 xtrabackup 的一个软链接。对于二次开发来说,2.3 摆脱了之前2个进程协作的负担,架构上明显要好于之前版本。(Percona XtraBackup 2.3 发布之后,推荐的备份方法是使用 xtrabackup 脚本)

 

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

一般情况下,我们是希望能备份 MyISAM 表的,虽然我们可能自己不用 MyISAM 表,但是 mysql 库下的系统表是 MyISAM 的,因此备份基本都通过 innobackupex 命令进行;另外一个原因是我们可能需要保存位点信息。

 

另外几个工具相对小众些,xbcrypt 是加解密备份文件用的;xbstream 类似于tar,是 Percona 自己实现的一种支持并发写的流文件格式;两者在备份和解压时都会用到(如果备份用了加密和并发)。xbcloud 工具的作用是:把全部或部分 xbstream 档案从云上下载或上传到云。

 

 

1.2 XtraBackup 原理

2.3版本之前 innobackupex xtrabackup 2个工具之间的交互和协调是通过控制文件的创建和删除来实现的,2.3版本将 innobackupex 功能全部集成到 xtrabackup 里面,也就不需要他们之间的通信。这里介绍基于老的架构(2.2版本),但是原理和2.3是一样的,只是实现上的差别。

 

整个备份过程如下图:

 

1.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 文件(包括 frmMYDMYICSVoptpar等)。拷贝非 InnoDB 文件过程中,因为数据库处于全局只读状态,如果在业务的主库备份的话,要特别小心,非 InnoDB 表(主要是MyISAM)比较多的话整库只读时间就会比较长,这个影响一定要评估到。

 

5> innobackupex 拷贝完所有非 InnoDB 表文件后,通知 xtrabackup(通过删文件) ,同时自己进入等待(等待另一个文件被创建);

 

6> xtrabackup 收到 innobackupex 备份完非 InnoDB 通知后,就停止 redo 拷贝线程,然后通知 innobackupex redo 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 文件时已经做了flushFTWRL),磁盘上的文件也是完整的,所以最终备份集里的数据文件都是写入完整的。

 

1.4 增量备份

PXB 是支持增量备份的,但是只能对 InnoDB 做增量,InnoDB 每个 page 有个 LSN 号,LSN 是全局递增的,page 被更改时会记录当前的 LSN 号,page中的 LSN 越大,说明当前page越新(最近被更新)。每次备份会记录当前备份到的LSNxtrabackup_checkpoints 文件中),增量备份就是只拷贝LSN大于上次备份的page,比上次备份小的跳过,每个ibd文件最终备份出来的是增量 delta 文件。

 

MyISAM 是没有增量的机制的,每次增量备份都是全部拷贝的。

增量备份过程和全量备份一样,只是在 ibd 文件拷贝上有不同。

 

 

1.5 恢复过程

如果看恢复备份集的日志,会发现和 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来启动了。

注:以上原理摘自阿里云数据库内核月报。

 

 

1.6 实现细节

1> 文件权限

xtrabackupread-write模式打开innodb的数据文件,然后对其进行复制。其实它不会修改此文件。也就是说,运行xtrabackup的用户,必须对innodb的数据文件具有读写权限。为什么要用rw模式呢?直接read模式不好么?因为xtrabackup采用了其内置的innodb库来打开文件,而innodb库打开文件的时候就是rw的。

 

2> 调整操作系统缓冲区

因为XtraBackup要从文件系统中复制大量的数据,所以它尽可能地使用 posix_fadvise(),来告诉OS不要缓存读取到的数据,因为这些数据不会重用到了,从而提升性能。如果一次备份要缓存几个G的数据,会对OS的虚拟内存造成很大的压力,其它进程,比如mysqld很有可能被swap出去,这样系统就会受到很大影响了。xtrabackup 就是通过 posix_fadvise() 来避免这种情况:

posix_fadvise(file,0,0,POSIX_FADV_DONTNEED)

 

而且, xtrabackup 要求操作系统对源文件进行更多的预读优化:

posix_fadvise(file,0,0,POSIX_FADV_SEQUENTIAL)

 

3> 复制数据文件

在备份innodb page的过程中,XtraBackup 每次读写1MB的数据,1MB/16KB=64page。这个不可配置。读取1MB数据之后,XtraBackup一页一页地遍历这1MB数据,并使用innodbbuf_page_is_corrupted()函数检查此页的数据是否正常,如果数据不正常,就重新读取这一页,最多重新读取10次(注意:doublewrite buffer 中的 page 会跳过此检查)。

在复制 transactions log(redo log) 的时候,每次读写512KB的数据。同样不可以配置。

 

 

2. xtrabackup安装

 

rpm 安装(下载:https://pan.baidu.com/s/1sl4jByP

l  二进制安装/解压缩安装(下载:https://pan.baidu.com/s/1c1Vyt3q

l  编译安装

 

1> rpm 安装

这种安装方法比较简单,只需下载相应的rpm安装包安装即可(注意根据提示安装相应的依赖包)。其中需要的 libev.so.4() 安装包:https://pan.baidu.com/s/1i4EZfwT

[root@orcl ~]# cat /etc/issue

Red Hat Enterprise Linux Server release 6.5 (Santiago)

[root@orcl ~]# uname -r

2.6.32-431.el6.x86_64

 

[root@orcl ~]# rpm -ivh libev-4.15-1.el6.rf.x86_64.rpm

warning: libev-4.15-1.el6.rf.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 6b8d79e6: NOKEY

Preparing...                ########################################### [100%]

   1:libev                  ########################################### [100%]

 

#### linux 6.5还需要安装以下依赖

# yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL

 

[root@orcl ~]# rpm -ivh percona-xtrabackup-24-2.4.6-2.el6.x86_64.rpm

warning: percona-xtrabackup-24-2.4.6-2.el6.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY

Preparing...                ########################################### [100%]

   1:percona-xtrabackup-24  ########################################### [100%]

 

[root@orcl ~]# xtrabackup --version

xtrabackup version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)

 

 

2> 二进制安装/解压缩安装

这种安装方法也很简单,不需要安装依赖,只需解压安装文件,为了方便可创建软连接

# tar zxvf percona-xtrabackup-2.4.6-Linux-x86_64.tar.gz   #解压目录下有3个目录: bin  man  percona-xtrabackup-2.4-test

# mv percona-xtrabackup-2.4.6-Linux-x86_64 /usr/local/xtrabackup

# ln -sf /usr/local/xtrabackup/bin/* /usr/bin/          #给命令建个软连接

[root@centos6 ~]# xtrabackup --version

xtrabackup version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)

 

3> 编译安装

这种安装方法比较麻烦,需要安装很多依赖,也很耗时间,这里就不做介绍了

 

 

3. xtrabackup选项

xtrabackup 工具有许多参数,具体可去官网查询(xtrabackup 参数选项 | innobackupex 参数选项),这里简单介绍 innobackupex 一些常用的参数。

 

3.1 innobackupex 参数选项

--defaults-file=[MY.CNF]    //指定配置文件:只能从给定的文件中读取默认选项。 且必须作为命令行上的第一个选项;必须是一个真实的文件,它不能是一个符号链接。

 

--databases=#    //指定备份的数据库和表,格式为:--database="db1[.tb1] db2[.tb2]" 多个库之间以空格隔开,如果此选项不被指定,将会备份所有的数据库。

 

--include=REGEXP    //用正则表达式的方式指定要备份的数据库和表,格式为 --include=‘^mydb[.]mytb’ ,对每个库中的每个表逐一匹配,因此会创建所有的库,不过是空的目录。--include 传递给 xtrabackup --tables

 

--tables-file=FILE    //此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称,格式为databasename.tablename。该选项传递给 xtrabackup --tables-file,与--tables选项不同,只有要备份的表的库才会被创建。

注意:部分备份(--include、--tables-file、--database)需要开启 innodb_file_per_table 。

 

--compact    //创建紧凑型备份,忽略所有辅助索引页,只备份data page;通过--apply-log中重建索引--rebuild-indexs

 

--compress    //此选项指示xtrabackup压缩备份的InnoDB数据文件,会生成 *.qp 文件。

 

--decompress    //解压缩qp文件,为了解压缩,必须安装 qpress 工具。 Percona XtraBackup不会自动删除压缩文件,为了清理备份目录,用户应手动删除 * .qp文件:find /data/backup -name "*.qp" | xargs rm

 

--no-timestamp    //指定了这个选项备份将会直接存储在 BACKUP-DIR 目录,不再创建时间戳文件夹。

 

--apply-log    //应用 BACKUP-DIR 中的 xtrabackup_logfile 事务日志文件。一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处于不一致状态。准备的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件使得数据文件处于一致性状态。

 

--use-memory=#    //此选项接受一个字符参数(1M/1MB,1G/1GB,默认100M),仅与--apply-log一起使用,该选项指定prepare时用于崩溃恢复(crash-recovery)的内存。

 

--copy-back    //拷贝先前备份所有文件到它们的原始路径。但原路径下不能有任何文件或目录,除非指定 --force-non-empty-directories 选项。

 

--force-non-empty-directories    //恢复时指定此选项,可使 --copy-back --move-back 复制文件到非空目录,即原data目录下可以有其他文件,但是不能有与恢复文件中同名的文件,否则恢复失败。

 

--rsync    //此选项可优化本地文件(非InnoDB)的传输。rsync工具一次性拷贝所有非InnoDB文件,而不是为每个文件单独创建cp,在备份恢复很多数据库和表时非常高效。此选项不能和 --stream 一起使用。

 

--incremental    //这个选项告诉 xtrabackup 创建一个增量备份,而不是完全备份。它传递到 xtrabackup 子进程。当指定这个选项,可以设置 --incremental-lsn --incremental-basedir。如果这2个选项都没有被指定,--incremental-basedir 传递给 xtrabackup 默认值,默认值为:基础备份目录的第一个时间戳备份目录。

 

--incremental-basedir=DIRECTORY    //该选项接受一个字符串参数,该参数指定作为增量备份的基本数据集的完整备份目录。它与 --incremental 一起使用。

 

--incremental-dir=DIRECTORY    //该选项接受一个字符串参数,该参数指定了增量备份将与完整备份相结合的目录,以便进行新的完整备份。它与 --incremental 选项一起使用。

 

--redo-only    //准备基本完整备份合并所有的增量备份(除了最后一个增备)”时使用此选项。它直接传递给xtrabackup xtrabackup --apply-log-only 选项,使xtrabackup跳过"undo"阶段,只做"redo"操作。如果后面还有增量备份应用到这个全备,这是必要的。有关详细信息,请参阅xtrabackup文档。

 

--parallel=NUMBER-OF-THREADS    //此选项接受一个整数参数,指定xtrabackup子进程应用于同时备份文件的线程数。请注意,此选项仅适用于文件级别,也就是说,如果您有多个.ibd文件,则它们将被并行复制; 如果您的表一起存储在一个表空间文件中,它将不起作用。

 

3.2 xtrabackup 参数选项

--apply-log-only    //这个选项使在准备备份(prepare)时,只执行重做(redo)阶段,这对于增量备份非常重要。

 

 

4. xtrabackup 全量备份恢复

4.1 完全备份

4.1.1 备份准备

## 创建用于备份恢复的用户 pxb 并赋予权限

mysql> create user pxb@'localhost' identified by '123456';

mysql> grant reload,process,lock tables,replication client on *.* to pxb@localhost;

#### 这些权限仅仅只能完成:全备,增量备份,恢复;

一般如果需要部分备份,export表,import表,还需要:grant create tablespace on *.* to 'bkpuser'@'localhost';

如果还需要对备份的过程中对锁进行一些优化,防止发生阻塞所有DML的情况,则还需要:

grant process,super on *.* to 'bkpuser'@'localhost';

 

 

## 创建存放备份目录

[root@orcl ~]# mkdir -pv /data/pxb

mkdir: created directory `/data'

mkdir: created directory `/data/pxb'

 

 

4.1.2 全库备份

[root@orcl ~]# innobackupex ----defaults-file=/etc/my.cnf --user=pxb --password=123456 --socket=/app/mysql/tmp/mysql.sock /data/pxb/

180321 11:29:47 innobackupex: Starting the backup operation

IMPORTANT: Please check that the backup run completes successfully.

           At the end of a successful backup run innobackupex

           prints "completed OK!".

180321 11:29:47  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/app/mysql/tmp/mysql.sock' as 'pxb'  (using password: YES).

180321 11:29:47  version_check Connected to MySQL server

180321 11:29:47  version_check Executing a version check against the server...

180321 11:29:47  version_check Done.

180321 11:29:47 Connecting to MySQL server host: localhost, user: pxb, password: set, port: 3306, socket: /app/mysql/tmp/mysql.sock

Using server version 5.5.32-log

innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)

xtrabackup: uses posix_fadvise().

xtrabackup: cd to /app/mysql-5.5.32/data/

xtrabackup: open files limit requested 0, set to 1024

xtrabackup: using the following InnoDB configuration:

xtrabackup:   innodb_data_home_dir = .

xtrabackup:   innodb_data_file_path = ibdata1:10M:autoextend

xtrabackup:   innodb_log_group_home_dir = ./

xtrabackup:   innodb_log_files_in_group = 2

xtrabackup:   innodb_log_file_size = 5242880

InnoDB: Number of pools: 1

180321 11:29:47 >> log scanned up to (1610330)

xtrabackup: Generating a list of tablespaces

180321 11:29:48 [01] Copying ./ibdata1 to /data/pxb/2018-03-21_11-29-47/ibdata1

180321 11:29:48 [01]        ...done

180321 11:29:48 >> log scanned up to (1610330)

180321 11:29:49 Executing FLUSH NO_WRITE_TO_BINLOG TABLES...

180321 11:29:49 Executing FLUSH TABLES WITH READ LOCK...

180321 11:29:49 Starting to backup non-InnoDB tables and files

。。。。。。。。。

180321 11:29:50 Executing UNLOCK TABLES

180321 11:29:50 All tables unlocked

180321 11:29:50 Backup created in directory '/data/pxb/2018-03-21_11-29-47/'

MySQL binlog position: filename 'mysql-bin.000001', position '366'

180321 11:29:50 [00] Writing backup-my.cnf

180321 11:29:50 [00]        ...done

180321 11:29:50 [00] Writing xtrabackup_info

180321 11:29:50 [00]        ...done

xtrabackup: Transaction log of lsn (1610330) to (1610330) was copied.

180321 11:29:50 completed OK!

 

 

4.1.3 查看生成的文件

可以看到整个备份过程:连接数据库,开始拷贝redo log,拷贝innodb表文件,锁表、拷贝非innodb表文件,停止拷贝redo log,解锁。

 

[root@orcl ~]# ls -lrht /data/pxb/2018-03-21_11-29-47/

total 19M

-rw-r----- 1 root root  18M Mar 21 11:29 ibdata1

drwxr-x--- 2 root root 4.0K Mar 21 11:29 mysql

drwxr-x--- 2 root root 4.0K Mar 21 11:29 shaw_db

drwxr-x--- 2 root root 4.0K Mar 21 11:29 performance_schema

-rw-r----- 1 root root   21 Mar 21 11:29 xtrabackup_binlog_info

-rw-r----- 1 root root 2.5K Mar 21 11:29 xtrabackup_logfile

-rw-r----- 1 root root  113 Mar 21 11:29 xtrabackup_checkpoints

-rw-r----- 1 root root  417 Mar 21 11:29 backup-my.cnf

-rw-r----- 1 root root  530 Mar 21 11:29 xtrabackup_info

 

 

其中,mysql/ performance_schema/shaw_db/ 下存放的是数据库文件。

 

backup-my.cnf,备份命令用到的配置选项信息;

[root@orcl 2018-03-21_11-29-47]# cat backup-my.cnf

# This MySQL options file was generated by innobackupex.

# The MySQL server

[mysqld]

innodb_checksum_algorithm=innodb

innodb_log_checksum_algorithm=innodb

innodb_data_file_path=ibdata1:10M:autoextend

innodb_log_files_in_group=2

innodb_log_file_size=5242880

innodb_fast_checksum=false

innodb_page_size=16384

innodb_log_block_size=512

innodb_undo_directory=.

innodb_undo_tablespaces=0

server_id=3

redo_log_version=0

 

 

ib_buffer_pool buffer pool 中的热数据,当设置 innodb_buffer_pool_dump_at_shutdown=1 ,在关闭 MySQL 时,会把内存中的热数据保存在磁盘里 ib_buffer_pool 文件中,位于数据目录下。

 

 

ibdata1,备份的共享表空间文件;

[root@orcl 2018-03-21_11-29-47]# file ibdata1

ibdata1: data

 

 

xtrabackup_binlog_infomysql服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置;

[root@orcl 2018-03-21_11-29-47]# cat xtrabackup_binlog_info

mysql-bin.000001        366

 

 

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

[root@orcl 2018-03-21_11-29-47]# cat xtrabackup_checkpoints

backup_type = full-backuped

from_lsn = 0

to_lsn = 1610330

last_lsn = 1610330

compact = 0

recover_binlog_info = 0

 

 

xtrabackup_info,记录备份的基本信息,uuid、备份命令、备份时间、binlogLSN、以及其他加密压缩等信息。

[root@orcl 2018-03-21_11-29-47]# cat xtrabackup_info

uuid = 1cbf36cc-2cb8-11e8-8495-000c29ee24c9

name =

tool_name = innobackupex

tool_command = ----defaults-file=/etc/my.cnf --user=pxb --password=... --socket=/app/mysql/tmp/mysql.sock /data/pxb/

tool_version = 2.4.6

ibbackup_version = 2.4.6

server_version = 5.5.32-log

start_time = 2018-03-21 11:29:47

end_time = 2018-03-21 11:29:50

lock_time = 0

binlog_pos = filename 'mysql-bin.000001', position '366'

innodb_from_lsn = 0

innodb_to_lsn = 1610330

partial = N

incremental = N

format = file

compact = N

compressed = N

encrypted = N

 

 

xtrabackup_logfile,备份的重做日志文件。

[root@orcl 2018-03-21_11-29-47]# file xtrabackup_logfile

xtrabackup_logfile: data

 

4.2 全备恢复

## 关闭数据库并删除数据文件

mysql> create table shaw_db.t_zhongbak as select * from mysql.user; --没做备份的数据会丢失

[root@orcl ~]# /etc/init.d/mysqld stop

Shutting down MySQL....                                    [  OK  ]

[root@orcl ~]# cd /app/mysql/

[root@orcl mysql]# mv data/ data_bak/

[root@orcl mysql]# mkdir data

 

4.2.1 应用日志

准备(prepare)一个完全备份(两次prepare,第一次应用备份期间产生的redo log,进行前滚和回滚:replayredo log中已经提交的事务,rollback没有提交的事务): --apply-log ( /data/pxb/2018-03-21_11-29-47/ 为备份目录,执行之后 xtrabackup_checkpoints 文件中的 backup_type = full-prepared )

[root@orcl ~]# innobackupex --apply-log /data/pxb/2018-03-21_11-29-47/

180321 11:51:10 innobackupex: Starting the apply-log operation

IMPORTANT: Please check that the apply-log run completes successfully.

           At the end of a successful apply-log run innobackupex

           prints "completed OK!".

。。。。。。

xtrabackup: starting shutdown with innodb_fast_shutdown = 1

InnoDB: FTS optimize thread exiting.

InnoDB: Starting shutdown...

InnoDB: Shutdown completed; log sequence number 1610792

180321 11:51:14 completed OK!

 

## --apply-log会调用 xtrabackup --prepare两次,第一次前滚和回滚,第二次生成iblogfile[0|1]

 

4.2.2 恢复全备

直接将上面prepare好的所有文件,复制到mysqlddatadir目录(会读取my.cnf中的配置信息)

--copy--back的注意事项:

1> datadir的目录必须是空的,或者使用--force-non-empty-directories选项;

2> mysqld必须关闭,如果是--import部分恢复,则不能关闭;

3> --copy-back完成之后,需要修改datadir目录下的文件权限: chown -R mysql:mysql /var/lib/mysql

 

 

## 执行恢复操作

[root@orcl ~]# innobackupex  --defaults-file=/etc/my.cnf --copy-back --rsync /data/pxb/2018-03-21_11-29-47/

180321 12:20:29 innobackupex: Starting the copy-back operation

IMPORTANT: Please check that the copy-back run completes successfully.

           At the end of a successful copy-back run innobackupex

           prints "completed OK!".

innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)

Error: datadir must be specified.

 

## 添加datadir目录

[root@orcl ~]# vi /etc/my.cnf

datadir =/app/mysql/data

 

[root@orcl ~]# innobackupex  --defaults-file=/etc/my.cnf --copy-back --rsync /data/pxb/2018-03-21_11-29-47/

180321 12:25:39 innobackupex: Starting the copy-back operation

IMPORTANT: Please check that the copy-back run completes successfully.

           At the end of a successful copy-back run innobackupex

           prints "completed OK!".

innobackupex version 2.4.6 based on MySQL server 5.7.13 Linux (x86_64) (revision id: 8ec05b7)

180321 12:25:39 [01] Copying ib_logfile0 to /app/mysql/data/ib_logfile0

180321 12:25:39 [01]        ...done

。。。。。。

Copying ./performance_schema/events_waits_summary_by_thread_by_event_name.frm to /app/mysql/data/performance_schema/events_waits_summary_by_thread_by_event_name.frm

180321 12:25:41 [01]        ...done

180321 12:25:41 [01] Copying ./xtrabackup_info to /app/mysql/data/xtrabackup_info

180321 12:25:41 [01]        ...done

180321 12:25:41 completed OK!

 

 

## 更改 data/ 目录权限并启动mysql

[root@orcl ~]# chown -R mysql. /app/mysql/data

 

## 启动mysql服务

[root@orcl ~]# /etc/init.d/mysqld start

Starting MySQL..                                           [  OK  ]

 

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| performance_schema |

| shaw_db            |

+--------------------+

mysql> use shaw_db

Database changed

mysql> show tables;

+-------------------+

| Tables_in_shaw_db |

+-------------------+

| t_user            |

| t_zhong           |

+-------------------+

2 rows in set (0.00 sec)

 

 

 

 

 

 

5. xtrabackup 全量备份恢复

增量备份之前,必须建立一个全备,第一次增量备份是在全备的基础之上,第二次增量备份是在第一次增量备份的基础之上的,依次类推

 

5.1 增量备份1

## 新建一张表,并插入写数据,然后做增量备份

mysql> create table shaw_db.t_shaw as select * from mysql.user;

mysql> create table shaw_db.t_zhongbak as select * from shaw_db.t_zhong;

 

## 以全备为基准:(/data/pxb/2018-03-21_12-32-32/

[root@orcl ~]# innobackupex --defaults-file=/etc/my.cnf --user=pxb --password=123456 --socket=/app/mysql/tmp/mysql.sock --incremental /data/pxb/inc --incremental-basedir=/data/pxb/2018-03-21_12-32-32/ --parallel=2

180321 12:47:17 innobackupex: Starting the backup operation

IMPORTANT: Please check that the backup run completes successfully.

           At the end of a successful backup run innobackupex

           prints "completed OK!".

180321 12:47:17  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/app/mysql/tmp/mysql.sock' as 'pxb'  (using password: YES).

。。。。。。

180321 12:47:20 Executing UNLOCK TABLES

180321 12:47:20 All tables unlocked

180321 12:47:20 Backup created in directory '/data/pxb/inc/2018-03-21_12-47-17/'

MySQL binlog position: filename 'mysql-bin.000001', position '350'

180321 12:47:20 [00] Writing backup-my.cnf

180321 12:47:20 [00]        ...done

180321 12:47:20 [00] Writing xtrabackup_info

180321 12:47:20 [00]        ...done

xtrabackup: Transaction log of lsn (1631682) to (1631682) was copied.

180321 12:47:20 completed OK!

 

 

[root@orcl ~]# cat /data/pxb/inc/2018-03-21_12-47-17/xtrabackup_checkpoints

backup_type = incremental  ## 说明是增量备份

from_lsn = 1615487

to_lsn = 1631682

last_lsn = 1631682

compact = 0

recover_binlog_info = 0

 

5.2 增量备份2

## 再新建一些表,并插入写数据,然后做增量备份

mysql> create table shaw_db.t_shaw2 as select * from mysql.user;

mysql> create table shaw_db.t_zhongbak2 as select * from shaw_db.t_zhong;

 

## 以增量1为基准:(/data/pxb/inc/2018-03-21_12-47-17/

[root@orcl ~]# innobackupex --defaults-file=/etc/my.cnf --user=pxb --password=123456 --socket=/app/mysql/tmp/mysql.sock --incremental /data/pxb/inc/ --incremental-basedir=/data/pxb/inc/2018-03-21_12-47-17/ --parallel=4

180321 12:54:18 innobackupex: Starting the backup operation

IMPORTANT: Please check that the backup run completes successfully.

           At the end of a successful backup run innobackupex

           prints "completed OK!".

180321 12:54:18  version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=3306;mysql_socket=/app/mysql/tmp/mysql.sock' as 'pxb'  (using password: YES).

180321 12:54:18  version_check Connected to MySQL server

180321 12:54:18  version_check Executing a version check against the server...

180321 12:54:18  version_check Done.

180321 12:54:18 Connecting to MySQL server host: localhost, user: pxb, password: set, port: 3306, socket: /app/mysql/tmp/mysql.sock

。。。。。。

180321 12:54:22 Executing UNLOCK TABLES

180321 12:54:22 All tables unlocked

180321 12:54:22 Backup created in directory '/data/pxb/inc/2018-03-21_12-54-18/'

MySQL binlog position: filename 'mysql-bin.000001', position '589'

180321 12:54:22 [00] Writing backup-my.cnf

180321 12:54:22 [00]        ...done

180321 12:54:22 [00] Writing xtrabackup_info

180321 12:54:22 [00]        ...done

xtrabackup: Transaction log of lsn (1648889) to (1648889) was copied.

180321 12:54:22 completed OK!

 

 

 

[root@orcl ~]# cat /data/pxb/inc/2018-03-21_12-54-18/xtrabackup_checkpoints

backup_type = incremental

from_lsn = 1631682

to_lsn = 1648889

last_lsn = 1648889

compact = 0

recover_binlog_info = 0

 

 

5.3 增量备份的恢复

增量备份的恢复需要有3个步骤

1> 恢复完全备份

2> 恢复增量备份到完全备份(开始恢复的增量备份要添加--redo-only参数,到最后一次增量备份要去掉--redo-only)

3> 对整体的完全备份进行恢复,回滚未提交的数据

 

5.3.1 准备一个全备

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/2018-03-21_12-32-32/

180321 14:21:11 innobackupex: Starting the apply-log operation

IMPORTANT: Please check that the apply-log run completes successfully.

           At the end of a successful apply-log run innobackupex

           prints "completed OK!".

。。。。。。

xtrabackup: starting shutdown with innodb_fast_shutdown = 1

InnoDB: Starting shutdown...

InnoDB: Shutdown completed; log sequence number 1615930

InnoDB: Number of pools: 1

180321 14:21:13 completed OK!

 

5.3.2 将增量1应用到完全备份

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/2018-03-21_12-32-32/ --incremental-dir=/data/pxb/inc/2018-03-21_12-47-17/

180321 14:22:41 innobackupex: Starting the apply-log operation

IMPORTANT: Please check that the apply-log run completes successfully.

           At the end of a successful apply-log run innobackupex

           prints "completed OK!".

。。。。。。

180321 14:22:44 [00]        ...done

180321 14:22:44 [00] Copying /data/pxb/inc/2018-03-21_12-47-17//xtrabackup_info to ./xtrabackup_info

180321 14:22:44 [00]        ...done

180321 14:22:44 completed OK!

 

5.3.3 将增量2应用到完全备份,注意不加—redo-only参数了

[root@orcl ~]# innobackupex --apply-log /data/pxb/2018-03-21_12-32-32/ --incremental-dir=/data/pxb/inc/2018-03-21_12-54-18/

180321 14:24:29 innobackupex: Starting the apply-log operation

IMPORTANT: Please check that the apply-log run completes successfully.

           At the end of a successful apply-log run innobackupex

           prints "completed OK!".

 

5.3.4 把所有合在一起的完全备份整体进行一次apply操作,回滚未提交的数据

[root@orcl ~]# innobackupex --apply-log /data/pxb/2018-03-21_12-32-32/

180321 14:26:11 innobackupex: Starting the apply-log operation

IMPORTANT: Please check that the apply-log run completes successfully.

           At the end of a successful apply-log run innobackupex

           prints "completed OK!".

。。。。。。

InnoDB: 5.7.13 started; log sequence number 1615930

InnoDB: xtrabackup: Last MySQL binlog file position 589, file name ./mysql-bin.000001

xtrabackup: error: The transaction log file is corrupted.

xtrabackup: error: The log was not applied to the intended LSN!

xtrabackup: Log applied to lsn 1615930

xtrabackup: The intended lsn is 1648889

 

 

5.3.5 恢复数据库

## 先删除data目录

[root@orcl ~]# rm -rf /app/mysql/data

[root@orcl ~]# mkdir /app/mysql/data

 

## 恢复数据库

[root@orcl ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/pxb/2018-03-21_12-32-32/

180321 14:31:56 innobackupex: Starting the copy-back operation

IMPORTANT: Please check that the copy-back run completes successfully.

           At the end of a successful copy-back run innobackupex

           prints "completed OK!".

。。。。。。

180321 14:31:58 [01] Copying ./xtrabackup_binlog_pos_innodb to /app/mysql/data/xtrabackup_binlog_pos_innodb

180321 14:31:58 [01]        ...done

180321 14:31:58 completed OK!

 

 

[root@orcl ~]# chown -R mysql:mysql /app/mysql/data

[root@orcl ~]# /etc/init.d/mysqld start

Starting MySQL...The server quit without updating PID file [FAILED]sql/data/orcl.pid).

[root@orcl ~]# ps -ef |grep mysql

[root@orcl ~]# killall mysqld

[root@orcl ~]# /etc/init.d/mysqld start

Starting MySQL..                                           [  OK  ]

 

mysql> use shaw_db;

Database changed

mysql> show tables;

+-------------------+

| Tables_in_shaw_db |

+-------------------+

| t_shaw            |

| t_shaw2           |

| t_zhong           |

| t_zhongbak        |

| t_zhongbak2       |

+-------------------+

 

 

6. innobackupex选项优化、最佳实践

在备份非innodb数据库时,会使用:flush tables with read lock 全局锁锁住整个数据库。如果数据库中有一个长查询在运行,那么FTWRL就不能获得,会被阻塞,进而阻塞所有的DML操作。此时即使我们killFTWRL全局锁也是无法从阻塞中恢复出来的。另外在我们成功的获得了FTWRL全局锁之后,在copy非事务因为的文件的过程中,整个数据库也是被锁住的。所以我们应该让FTWRL的过程尽量的短。(copy非事务引擎数据的文件时,会阻塞innodb事务引擎。当然也会阻塞所有其他非事务引擎。)

 

--ftwrl-wait-timeout=60 防止发生阻塞

--rsync 减少FTWRL时间 缩短备份非事务引擎表的锁定时间

--parallel=4  开并行

--use-memory=4G crash recovery 期间使用的内存

 

--lock-wait-timeout=60 该选项表示:我们在FTWRL时,如果有长查询,那么我们可以最多等待60S的时间,如果60秒之内长查询执行完了,我们就可以成功执行FTWRL了,如果60秒之内没有执行完,那么就直接报错退出,放弃。默认值为0

--rsync 使用该选项来缩短备份非事务引擎表的锁定时间,如果需要备份的数据库和表数量很多时,可以加快速度。

--parallel=# 在备份阶段,压缩/解压阶段,加密/解密阶段,--apply-log--copy-back 阶段都可以并行  

--use-memory=# crash recovery 阶段,也就是 --apply-log 阶段使用该选项

 

 

 

 

 

7. 自动备份脚本

# mkdir –p /data/pxb/baklog

7.1 脚本内容

#backup.sh

#!/bin/sh

#on xtrabackup 2.2.8

# 第一次执行它的时候它会检查是否有完全备份,否则先创建一个全库备份

# 当你再次运行它的时候,它会根据脚本中的设定来基于之前的全备或增量备份进行增量备份

#ocpyang@126.com

 

INNOBACKUPEX_PATH=innobackupex  #INNOBACKUPEX的命令

INNOBACKUPEXFULL=/usr/bin/$INNOBACKUPEX_PATH  #INNOBACKUPEX的命令路径

 

#mysql目标服务器以及用户名和密码

MYSQL_CMD="--host=192.168.12.55 --user=root --password=111111 --port=3306" 

 

MYSQL_UP=" --user=root --password='111111' --port=3306 "  #mysqladmin的用户名和密码

 

TMPLOG="/data/pxb/innobackupex.$$.log"

 

MY_CNF=/etc/my.cnf #mysql的配置文件

 

MYSQL=/app/mysql/bin/mysql

 

MYSQL_ADMIN=/app/mysql/bin/mysqladmin

 

BACKUP_DIR=/data/pxb # 备份的主目录

 

FULLBACKUP_DIR=$BACKUP_DIR/full # 全库备份的目录

 

INCRBACKUP_DIR=$BACKUP_DIR/incre # 增量备份的目录

 

FULLBACKUP_INTERVAL=86400 # 全库备份的间隔周期,时间:秒

 

KEEP_FULLBACKUP=1 # 至少保留几个全库备份

 

logfiledate=backup.`date +%Y%m%d%H%M`.txt

 

#开始时间

STARTED_TIME=`date +%s`

 

 

#############################################################################

# 显示错误并退出

#############################################################################

 

error()

{

    echo "$1" 1>&2

    exit 1

}

 

 

# 检查执行环境

if [ ! -x $INNOBACKUPEXFULL ]; then

  error "$INNOBACKUPEXFULL未安装或未链接到/usr/bin."

fi

 

if [ ! -d $BACKUP_DIR ]; then

  error "备份目标文件夹:$BACKUP_DIR不存在."

fi

 

mysql_status=`netstat -nl | awk 'NR>2{if ($4 ~ /.*:3306/) {print "Yes";exit 0}}'`

if [ "$mysql_status" != "Yes" ];then

    error "MySQL 没有启动运行."

fi

 

 

if ! `echo 'exit' | $MYSQL -s $MYSQL_CMD` ; then

 error "提供的数据库用户名或密码不正确!"

fi

 

 

 

# 备份的头部信息

echo "----------------------------"

echo

echo "$0: MySQL备份脚本"

echo "开始于: `date +%F' '%T' '%w`"

echo

#新建全备和差异备份的目录

 

mkdir -p $FULLBACKUP_DIR

mkdir -p $INCRBACKUP_DIR

 

#查找最新的完全备份

LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`

 

# 查找最近修改的最新备份时间

LATEST_FULL_BACKUP_CREATED_TIME=`stat -c %Y $FULLBACKUP_DIR/$LATEST_FULL_BACKUP`

 

#如果全备有效进行增量备份否则执行完全备份

if [ "$LATEST_FULL_BACKUP" -a `expr $LATEST_FULL_BACKUP_CREATED_TIME + $FULLBACKUP_INTERVAL + 5` -ge $STARTED_TIME ] ; then

         # 如果最新的全备未过期则以最新的全备文件名命名在增量备份目录下新建目录

         echo -e "完全备份$LATEST_FULL_BACKUP未过期,将根据$LATEST_FULL_BACKUP名字作为增量备份基础目录名"

         echo "                                               "

         NEW_INCRDIR=$INCRBACKUP_DIR/$LATEST_FULL_BACKUP

         mkdir -p $NEW_INCRDIR

 

         # 查找最新的增量备份是否存在.指定一个备份的路径作为增量备份的基础

         LATEST_INCR_BACKUP=`find $NEW_INCRDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n"  | sort -nr | head -1`

                   if [ ! $LATEST_INCR_BACKUP ] ; then

                            INCRBASEDIR=$FULLBACKUP_DIR/$LATEST_FULL_BACKUP

                            echo -e "增量备份将以$INCRBASEDIR作为备份基础目录"

                            echo "                                               "

                   else

                            INCRBASEDIR=$INCRBACKUP_DIR/${LATEST_FULL_BACKUP}/${LATEST_INCR_BACKUP}

                            echo -e "增量备份将以$INCRBASEDIR作为备份基础目录"

                            echo "                                               "

                   fi

 

         echo "使用$INCRBASEDIR作为基础本次增量备份的基础目录."

         $INNOBACKUPEXFULL --defaults-file=$MY_CNF --use-memory=4G $MYSQL_CMD --incremental $NEW_INCRDIR --incremental-basedir $INCRBASEDIR > $TMPLOG 2>&1

 

         #保留一份备份的详细日志

 

         cat $TMPLOG>/data/pxb/baklog/$logfiledate

 

         if [ -z "`tail -1 $TMPLOG | grep 'completed OK!'`" ] ; then

          echo "$INNOBACKUPEX命令执行失败:"; echo

          echo -e "---------- $INNOBACKUPEX_PATH错误 ----------"

          cat $TMPLOG

          rm -f $TMPLOG

          exit 1

         fi

 

         THISBACKUP=`awk -- "/Backup created in directory/ { split( \\\$0, p, \"'\" ) ; print p[2] }" $TMPLOG`

         rm -f $TMPLOG

 

 

         echo -n "数据库成功备份到:$THISBACKUP"

         echo

 

         # 提示应该保留的备份文件起点

 

         LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`

 

         NEW_INCRDIR=$INCRBACKUP_DIR/$LATEST_FULL_BACKUP

 

         LATEST_INCR_BACKUP=`find $NEW_INCRDIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n"  | sort -nr | head -1`

 

         RES_FULL_BACKUP=${FULLBACKUP_DIR}/${LATEST_FULL_BACKUP}

 

         RES_INCRE_BACKUP=`dirname ${INCRBACKUP_DIR}/${LATEST_FULL_BACKUP}/${LATEST_INCR_BACKUP}`

 

         echo

         echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #红色

         echo -e "必须保留$KEEP_FULLBACKUP份全备即全备${RES_FULL_BACKUP}${RES_INCRE_BACKUP}目录中所有增量备份."

         echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #红色

         echo

 

 

 

else

         echo  "*********************************"

         echo -e "正在执行全新的完全备份...请稍等..."

         echo  "*********************************"

         $INNOBACKUPEXFULL --defaults-file=$MY_CNF  --use-memory=4G  $MYSQL_CMD $FULLBACKUP_DIR > $TMPLOG 2>&1

         #保留一份备份的详细日志

 

         cat $TMPLOG>/data/pxb/baklog/$logfiledate

 

 

         if [ -z "`tail -1 $TMPLOG | grep 'completed OK!'`" ] ; then

          echo "$INNOBACKUPEX命令执行失败:"; echo

          echo -e "---------- $INNOBACKUPEX_PATH错误 ----------"

          cat $TMPLOG

          rm -f $TMPLOG

          exit 1

         fi

 

          

         THISBACKUP=`awk -- "/Backup created in directory/ { split( \\\$0, p, \"'\" ) ; print p[2] }" $TMPLOG`

         rm -f $TMPLOG

 

         echo -n "数据库成功备份到:$THISBACKUP"

         echo

 

         # 提示应该保留的备份文件起点

 

         LATEST_FULL_BACKUP=`find $FULLBACKUP_DIR -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head -1`

 

         RES_FULL_BACKUP=${FULLBACKUP_DIR}/${LATEST_FULL_BACKUP}

 

         echo

         echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #红色

         echo -e "无增量备份,必须保留$KEEP_FULLBACKUP份全备即全备${RES_FULL_BACKUP}."

         echo -e '\e[31m NOTE:---------------------------------------------------------------------------------.\e[m' #红色

         echo

 

fi

 

 

 

7.2 测试脚本

## 第一次备份:

[root@orcl ~]# sh mysqlbackup.sh

----------------------------

mysqlbackup.sh: MySQL备份脚本

开始于: 2018-03-21 16:11:21 3

*********************************

正在执行全新的完全备份...请稍等...

*********************************

数据库成功备份到:/data/pxb/full/2018-03-21_16-11-21/

 NOTE:---------------------------------------------------------------------------------.

无增量备份,必须保留1份全备即全备/data/pxb/full/2018-03-21_16-11-21.

 NOTE:---------------------------------------------------------------------------------.

 

 

[root@orcl ~]# ls -lrht /data/pxb/full/

total 4.0K

drwxr-x--- 5 root root 4.0K Mar 21 16:11 2018-03-21_16-11-21

[root@orcl ~]# ls -lrht /data/pxb/incre/

total 0

[root@orcl ~]# ls -lrht /data/pxb/baklog/

total 20K

-rw-r--r-- 1 root root 18K Mar 21 16:11 backup.201803211611.txt

 

## 查看备份日志

[root@orcl ~]# tail -4 /data/pxb/baklog/backup.201803211611.txt

180321 16:11:23 [00] Writing xtrabackup_info

180321 16:11:23 [00]        ...done

xtrabackup: Transaction log of lsn (1615930) to (1615930) was copied.

180321 16:11:23 completed OK!

 

 

 

## 第二次备份

[root@orcl ~]# sh mysqlbackup.sh

----------------------------

mysqlbackup.sh: MySQL备份脚本

开始于: 2018-03-21 16:15:11 3

完全备份2018-03-21_16-11-21未过期,将根据2018-03-21_16-11-21名字作为增量备份基础目录名                                          

增量备份将以/data/pxb/full/2018-03-21_16-11-21作为备份基础目录

使用/data/pxb/full/2018-03-21_16-11-21作为基础本次增量备份的基础目录.

数据库成功备份到:/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-11/

 NOTE:---------------------------------------------------------------------------------.

必须保留1份全备即全备/data/pxb/full/2018-03-21_16-11-21/data/pxb/incre/2018-03-21_16-11-21目录中所有增量备份.

 NOTE:---------------------------------------------------------------------------------.

 

## 第三次备份

[root@orcl ~]# sh mysqlbackup.sh

----------------------------

mysqlbackup.sh: MySQL备份脚本

开始于: 2018-03-21 16:15:50 3

完全备份2018-03-21_16-11-21未过期,将根据2018-03-21_16-11-21名字作为增量备份基础目录名                                          

增量备份将以/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-11作为备份基础目录

使用/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-11作为基础本次增量备份的基础目录.

数据库成功备份到:/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-50/

 NOTE:---------------------------------------------------------------------------------.

必须保留1份全备即全备/data/pxb/full/2018-03-21_16-11-21/data/pxb/incre/2018-03-21_16-11-21目录中所有增量备份.

 NOTE:---------------------------------------------------------------------------------.

 

 

## 备份日志

[root@orcl ~]# ls -lrht /data/pxb/baklog/

total 60K

-rw-r--r-- 1 root root 18K Mar 21 16:11 backup.201803211611.txt

-rw-r--r-- 1 root root 20K Mar 21 16:15 backup.201803211615.txt

-rw-r--r-- 1 root root 20K Mar 21 16:17 backup.201803211617.txt

 

 

7.3 恢复测试

## 先准备数据

mysql> use shaw_db

mysql> create table t_zhong(id int,name varchar(20));

mysql> insert into t_zhong values(100,'name');

 

## 然后执行一次备份脚本

[root@orcl ~]# sh mysqlbackup.sh

----------------------------

mysqlbackup.sh: MySQL备份脚本

开始于: 2018-03-21 16:26:28 3

完全备份2018-03-21_16-11-21未过期,将根据2018-03-21_16-11-21名字作为增量备份基础目录名

增量备份将以/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-17-13作为备份基础目录

使用/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-17-13作为基础本次增量备份的基础目录.

数据库成功备份到:/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-26-28/

 NOTE:---------------------------------------------------------------------------------.

必须保留1份全备即全备/data/pxb/full/2018-03-21_16-11-21/data/pxb/incre/2018-03-21_16-11-21目录中所有增量备份.

 NOTE:---------------------------------------------------------------------------------.

 

 

## 删除数据库data目录

[root@orcl ~]# rm -rf /app/mysql/data/

[root@orcl ~]# mkdir /app/mysql/data/

[root@orcl ~]# killall mysql

[root@orcl ~]# killall mysqld

[root@orcl ~]# /etc/init.d/mysqld start

Starting MySQL.The server quit without updating PID file (/[FAILED]l/data/orcl.pid).

 

## 准备恢复数据库

=====>1 准备全备

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/full/2018-03-21_16-11-21/

 

# 应用增量备份

[root@orcl ~]# ls -lrht /data/pxb/incre/2018-03-21_16-11-21/

total 16K

drwxr-x--- 5 root root 4.0K Mar 21 16:15 2018-03-21_16-15-11

drwxr-x--- 5 root root 4.0K Mar 21 16:15 2018-03-21_16-15-50

drwxr-x--- 5 root root 4.0K Mar 21 16:17 2018-03-21_16-17-13

drwxr-x--- 5 root root 4.0K Mar 21 16:26 2018-03-21_16-26-28

 

=====>2 应用增量备份

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/full/2018-03-21_16-11-21/ --incremental-dir=/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-11/

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/full/2018-03-21_16-11-21/ --incremental-dir=/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-15-50/

[root@orcl ~]# innobackupex --apply-log --redo-only /data/pxb/full/2018-03-21_16-11-21/ --incremental-dir=/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-17-13/

 

=====>3 应用最后一个增量备份

[root@orcl ~]# innobackupex --apply-log /data/pxb/full/2018-03-21_16-11-21/ --incremental-dir=/data/pxb/incre/2018-03-21_16-11-21/2018-03-21_16-17-13/

 

=====>4 执行完整应用,回滚未提交事务

[root@orcl ~]# innobackupex --apply-log /data/pxb/full/2018-03-21_16-11-21/

 

=====>5 恢复数据库

[root@orcl ~]# innobackupex --defaults-file=/etc/my.cnf --copy-back --rsync /data/pxb/full/2018-03-21_16-11-21/

 

 

## 启动数据库,检查

[root@orcl ~]# chown -R mysql. /app/mysql/data/

[root@orcl ~]# /etc/init.d/mysqld start

Starting MySQL..                                           [  OK  ]

 

mysql> use shaw_db;

mysql> select * from t_zhong;

+------+------+

| id   | name |

+------+------+

|  100 | name |

+------+------+

 

8. 附,自动恢复脚本

####  根据情况修改

xtrabackup自动还原

 

************************************************************************************************

应用场景:

************************************************************************************************

 

1.备份目录为/backup/full/backup/incre的架构,前者保存全备,后者保存增量备份

 

2.如全备为/backup/full/2015-04-08_15-14-33则将全备的目录名2015-04-08_15-14-33

作为/backup/incre/下增量备份的目录名。这样设计的初衷在于只要全备不过期,那么

这个全备文件之后的增量备份也不过期.

 

3.还原时,脚本会自动找到最新的全备和最新全备命名的增量备份目录,并将增量备份

按照先后顺序应用日志到全备中,最后完成还原.

 

************************************************************************************************

脚本

************************************************************************************************

#!/bin/sh

#

# 使用方法:

# ./restore.sh /增量备份父目录

#ocpyang@126.com

 

#NOTE:恢复开始前请确保mysql服务停止以及数据和日志目录清空,

# rm -rf /usr/local/mysql/innodb_data/*

# rm -rf /usr/local/mysql/data/*

# rm -rf /usr/local/mysql/mysql_logs/innodb_log/*

 

 

INNOBACKUPEX=innobackupex

INNOBACKUPEX_PATH=/usr/local/xtrabackup/bin/$INNOBACKUPEX

TMP_LOG="/var/log/restore.$$.log"

MY_CNF=/usr/local/mysql/my.cnf

BACKUP_DIR=/backup # 你的备份主目录

FULLBACKUP_DIR=$BACKUP_DIR/full # 全库备份的目录

INCRBACKUP_DIR=$BACKUP_DIR/incre # 增量备份的目录

MEMORY=4096M # 还原的时候使用的内存限制数

ERRORLOG=`grep -i "^log-error" $MY_CNF |cut -d = -f 2`

MYSQLD_SAFE=/usr/local/mysql/bin/mysqld_safe

MYSQL_PORT=3306

 

 

#############################################################################

 

#显示错误

 

#############################################################################

 

error()

{

    echo "$1" 1>&2

    exit 1

}

 

 

 

#############################################################################

 

# 检查innobackupex错误输出

 

#############################################################################

 

check_innobackupex_fail()

{

    if [ -z "`tail -2 $TMP_LOG | grep 'completed OK!'`" ] ; then

    echo "$INNOBACKUPEX命令执行失败:"; echo

    echo "---------- $INNOBACKUPEX的错误输出 ----------"

    cat $TMP_LOG

    #保留一份备份的详细日志

    logfiledate=restore.`date +%Y%m%d%H%M`.txt

    cat $TMP_LOG>/backup/$logfiledate 

    rm -f $TMP_LOG

    exit 1

  fi

}

 

 

 

 

 

# 选项检测

if [ ! -x $INNOBACKUPEX_PATH ]; then

  error "$INNOBACKUPEX_PATH在指定路径不存在,请确认是否安装或核实链接是否正确."

fi

 

 

 

if [ ! -d $BACKUP_DIR ]; then

  error "备份目录$BACKUP_DIR不存在."

fi

 

 

 

if [ $# != 1 ] ; then

  error "使用方法: $0 使用还原目录的绝对路径"

fi

 

 

 

if [ ! -d $1 ]; then

  error "指定的备份目录:$1不存在."

fi

 

 

 

PORTNUM00=`netstat -lnt|grep ${MYSQL_PORT}|wc -l`

if [ $PORTNUM00 = 1  ];

then

echo -e '\e[31m NOTE:------------------------------------------.\e[m' #红色

echo -e '\e[31m mysql处于运行状态,请关闭mysql. \e[m' #红色

echo -e '\e[31m NOTE:------------------------------------------.\e[m' #红色

exit 0

fi      

 

 

 

input_value=$1

intpu_res=`echo ${input_value%/*}`

 

 

 

# Some info output

echo "----------------------------"

echo

echo "$0: MySQL还原脚本"

START_RESTORE_TIME=`date +%F' '%T' '%w`

echo "数据库还原开始于: $START_RESTORE_TIME"

echo

 

 

 

 

 

#PARENT_DIR=`dirname ${intpu_res}`

PARENT_DIR=${intpu_res}

 

if [ $PARENT_DIR = $FULLBACKUP_DIR ]; then

         FULLBACKUP=${intpu_res}

         echo "还原全备备份:`basename $FULLBACKUP`"

         echo

 

else

         if [ $PARENT_DIR = $INCRBACKUP_DIR ]; then

                   FULL=`ls -t $FULLBACKUP_DIR |head -1`

                   FULLBACKUP=$FULLBACKUP_DIR/$FULL

                            if [ ! -d $FULLBACKUP ]; then

                            error "全备:$FULLBACKUP不存在."

                            fi

                   INCR=`ls -t $INCRBACKUP_DIR/$FULL/ | head -1`

                   echo "还原将从全备$FULL开始,到增量$INCR结束."

                   echo

                   echo "Prepare:完整备份集..........."

                   echo "*****************************"

                   $INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1

                   check_innobackupex_fail

   

 

            # Prepare增量备份集,即将增量备份应用到全备目录中,按照增量备份顺序即按照时间从旧到最新

                   for i in `find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n `;

                   do

 

                            #判断最新全备的lsn

                            #check_full_file=`find $FULLBACKUP/ -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -nr | head  -1`

                      

                            check_full_lastlsn=$FULLBACKUP/xtrabackup_checkpoints

                      

                            fetch_full_lastlsn=`grep -i "^last_lsn" ${check_full_lastlsn} |cut -d = -f 2`

 

                            ######判断增量备份中第一个增量备份的LSN

                            check_incre_file=`find $PARENT_DIR/$FULL -mindepth 1 -maxdepth 1 -type d -printf "%P\n" | sort -n |  head -1`

                        

                            check_incre_lastlsn=$PARENT_DIR/$FULL/$i/xtrabackup_checkpoints

                        

                            fetch_incre_lastlsn=`grep -i "^last_lsn" ${check_incre_lastlsn} |cut -d = -f 2`

                            echo "完全备份的LSN:${fetch_full_lastlsn} "

                            echo "增量备份的LSN:${fetch_incre_lastlsn} "

                           

                                     if [ "${fetch_incre_lastlsn}" -eq "${fetch_full_lastlsn}" ];then

                                               echo "*****************************************"

                                               echo "LSN不需要prepare!"

                                               echo "*****************************************"

                                               echo

                                               break

                                    

                                    

                           

                                     else

                                               echo "Prepare:增量备份集$i........"

                                               echo "*****************************"

                                               $INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --redo-only --use-memory=$MEMORY $FULLBACKUP --incremental-dir=$PARENT_DIR/$FULL/$i > $TMP_LOG 2>&1

                                               check_innobackupex_fail

                             

                                               if [ $INCR = $i ]; then

                                               break

                                               fi

                       

                                     fi

                            ######判断LSN

                   done

        

         else

                   error "未知的备份类型"

         fi

fi

 

 

echo "prepare:全备集回滚那些未提交的事务..........."

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --apply-log --use-memory=$MEMORY $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

 

echo "*****************************"

echo "数据库还原中 ...请稍等"

echo "*****************************"

 

$INNOBACKUPEX_PATH --defaults-file=$MY_CNF --copy-back $FULLBACKUP > $TMP_LOG 2>&1

check_innobackupex_fail

 

 

rm -f $TMP_LOG

echo "1.恭喜,还原成功!."

echo "*****************************"

 

 

#修改目录权限

echo "修改mysql目录的权限."

mysqlcnf="/usr/local/mysql/my.cnf"

mysqldatadir=`grep -i "^basedir" $mysqlcnf |cut -d = -f 2`

`echo 'chown -R mysql:mysql' ${mysqldatadir}`

echo "2.权限修改成功!"

echo "*****************************"

 

 

#自动启动mysql

 

INIT_NUM=1

if [ ! -x $MYSQLD_SAFE ]; then

  echo "mysql安装时启动文件未安装到$MYSQLD_SAFE或无执行权限"

  exit 1  #0是执行成功,1是执行不成功

else

         echo "启动本机mysql端口为:$MYSQL_PORT的服务"

         $MYSQLD_SAFE --defaults-file=$MY_CNF  > /dev/null &

         while  [ $INIT_NUM  -le 6 ]

            do

                 PORTNUM=`netstat -lnt|grep ${MYSQL_PORT}|wc -l`

                 echo "mysql启动中....请稍等..."

                 sleep 5

                           if [ $PORTNUM = 1  ];

                           then

                         echo "mysql                                      ****启动成功****"

                           exit 0

                           fi      

                 INIT_NUM=$(($INIT_NUM +1))

            done

       echo -e "mysql启动失败或启动时间过长,请检查错误日志 `echo 'cat ' ${ERRORLOG}`"

         echo "*****************************************"

         exit 0

fi

 

 

 

 

END_RESTORE_TIME=`date +%F' '%T' '%w`

echo "数据库还原完成于: $END_RESTORE_TIME"

exit 0

 

 

 

 

 

 

 

 

 

************************************************************************************************

执行结果:

************************************************************************************************

 

 执行结果如下:

 #./restore.sh  /backup/incre/

----------------------------

 

./restore.sh: MySQL还原脚本

数据库还原开始于: 2015-04-08 15:17:14 3

 

还原将从全备2015-04-08_15-14-33开始,到增量2015-04-08_15-16-06结束.

 

Prepare:完整备份集...........

*****************************

完全备份的LSN: 62974601

增量备份的LSN: 124278446

Prepare:增量备份集2015-04-08_15-15-25........

*****************************

完全备份的LSN: 124278446

增量备份的LSN: 185584722

Prepare:增量备份集2015-04-08_15-16-06........

*****************************

prepare:全备集回滚那些未提交的事务...........

*****************************

数据库还原中 ...请稍等

*****************************

1.恭喜,还原成功!.

*****************************

修改mysql目录的权限.

2.权限修改成功!

*****************************

启动本机mysql端口为:3306的服务

3.mysql启动中....请稍等...

3.mysql启动中....请稍等...

3.mysql启动中....请稍等...

mysql                                      ****启动成功****

 

 

 

 

请登录后发表评论 登录
全部评论

注册时间:2015-02-06

  • 博文量
    137
  • 访问量
    747557