MySQL 备份恢复

================================================================================

概述:

  • 数据备份的介绍,类型,及工具;

  • msyqldump 备份的实现和数据恢复;

  • Xtrabackup 备份的实现和数据恢复;

================================================================================

备份和恢复(数据):

  1.介绍

备份:存储的数据副本;

  • 原始数据:持续改变;(考虑问题)

恢复:把副本应用到线上系统;

  • 仅能恢复至备份操作时刻的数据状态;

时间点恢复:

  • binary logs; (二进制日志)

为什么备份?

  • 灾难恢复:硬件故障(冗余)、软件故障(bug)、自然灾害、******、误操作、...

  • 测试;

备份时应该注意事项:

  • 能容忍最多丢失多少数据;

  • 恢复数据需要在多长时间内完成;

  • 需要恢复哪些数据;

做恢复演练:

  • 测试备份的可用性;

  • 增强恢复操作效率;

    ...

 2.备份类型

备份的数据的集范围:

完全备份和部分备份

  • 完全备份:整个数据集;

  • 部分备份:数据集的一部分,比如部分表;

完全备份、增量备份、差异备份:

  • 完全备份

  • 增量备份:仅备份自上一次完全备份或增量备份以来变量的那部分数据;

  • 差异备份:仅备份自上一次完全备份以来变量的那部数据;

物理备份、逻辑备份:

  • 物理备份:复制数据文件进行备份;

  • 逻辑备份:从数据库导出数据另存在一个或多个文件中;

根据数据服务是否在线:

  • 热备:读写操作均可进行的状态下所做的备份;

  • 温备:可读但不可写状态下进行的备份;

  • 冷备:读写操作均不可进行的状态下所做的备份;

 3.备份需要考虑的因素、备份策略及备份内容

备份需要考虑因素:

  • 锁定资源多长时间?

  • 备份过程的时长?

  • 备份时的服务器负载?

  • 恢复过程的时长?

备份策略:

  • 完全+差异+时间点还原(二进制日志binlog)

  • 完全+增量+时间点还原 (二进制日志binlog)

注意:

  • 事务日志和二进制日志应该放在有冗余能力的磁盘上,RAID10最好

备份手段:

  • 物理

  • 逻辑

备份什么?

  • 数据

  • 二进制日志、InnoDB的事务日志;

  • 代码(存储过程、存储函数、触发器、事件调度器)

  • 服务器的配置文件

备份,多久一次?

  • 数据变化量;

  • 可用的备份存储空间;

 4.备份工具:

mysqldump:mysql服务自带的备份工具;逻辑备份工具;

  • 完全、部分备份;

  • InnoDB:热备;

  • MyISAM:温备;

cp/tar

  • lvm2:快照(请求一个全局锁),之后立即释放锁,达到几乎热备的效果;物理备份;

注意:不能仅备份数据文件;要同时备份事务日志;

前提:要求数据文件和事务日志位于同一个逻辑卷;

xtrabackup:

  由Percona提供,开源工具,支持对InnoDB做热备,物理备份工具;

  • 完全备份、部分备份;

  • 完全备份、增量备份;

  • 完全备份、差异备份;

mysqlhotcopy

select:

  • 备份:SELECT cluase INTO OUTFILE 'FILENAME';

  • 恢复:CREATE TABLE 

  • 导入:LOAD DATA 

备份工具--mysqldump:

作用:

  • 逻辑备份、完全备份、部分备份;

二次封装工具:

  • mydumper     //能够实现并行备份

  • phpMyAdmin

Usage: 

  • mysqldump [OPTIONS] database [tables]

           只备份指定库中的所有表,没有create database语句

  • mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]

       可以备份多个数据库,也可以指定备份哪个数据库

  • mysqldump [OPTIONS] --all-databases [OPTIONS]

       备份所有数据库

MyISAM存储引擎:支持温备,备份时要锁定表;

  • -x, --lock-all-tables:锁定所有库的所有表,读锁;

  • -l, --lock-tables:锁定指定库所有表;

InnoDB存储引擎:支持温备和热备;

  • --single-transaction:创建一个事务,基于此快照执行备份;

注意:

  • 一定要备份时间点一致的数据!!!

其它选项:

  • -R, --routines:  //存储过程和存储函数;

  • --triggers           //触发器

  • -E, --events        //时间调度器   

  • --master-data[=#]

     记录备份那一刻开始时binlog处于哪一个文件的哪一个位置

         1:表示记录为CHANGE MASTER TO语句,此语句不被注释;

         2:表示记录为CHANGE MASTER TO语句,此语句被注释;

  • --flush-logs:锁定表完成后,即进行日志刷新操作(使二进制日志滚动一下);

使用备份脚本实现自动化备份

注意:

  • 数据备份时要保留备份时的时间戳作为备份文件名的一部分;

  • 备份好的文件要做异地另存;

演示:

 1.备份hellodb数据库的所有表,操作如下:

[root@centos7 ~]# mkdir mysql.bak  # 这里我先创建一个专门存放备份的目录

# 使用mysqldump 指明用户账户,要备份的数据库和重定向的位置即可
[root@centos7 ~]# mysqldump -uroot -hlocalhost -ptaoxiu hellodb > ./mysql.bak/hellodb.sql.1

[root@centos7 ~]# ls ./mysql.bak/
hellodb.sql.1

# 查看备份的hellodb数据库,可以看到表头显示的版本信息,数据库名称等
[root@centos7 ~]# cat mysql.bak/hellodb.sql.1 
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

 2.如上题,因为我们仅是备份指定数据库的所有表,所以没有create database语句,现在我们添加

--databases选项来备份,可以指明要备份的单个或者多个数据库,这样的话就有create database语句了;

[root@centos7 ~]# mysqldump -uroot -hlocalhost -ptaoxiu --databases hellodb > ./mysql.bak/hellodb.sql.2
[root@centos7 ~]# ll -h mysql.bak
total 16K
-rw-r--r-- 1 root root 7.6K Dec  2 18:27 hellodb.sql.1
-rw-r--r-- 1 root root 7.8K Dec  2 18:41 hellodb.sql.2

[root@centos7 ~]# cat mysql.bak/hellodb.sql.2
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `hellodb`
--
# 存在创建数据库的语句
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hellodb` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `hellodb`;

 3.备份整个数据库,使用--all-databases选项

[root@centos7 ~]# mysqldump -uroot -hlocalhost -ptaoxiu --all-databases > ./mysql.bak/data.sql.3
[root@centos7 ~]# ll -h mysql.bak
total 15M
-rw-r--r-- 1 root root  15M Dec  2 18:45 data.sql.3   # 备份的所有数据库,明显文件大很多
-rw-r--r-- 1 root root 7.6K Dec  2 18:27 hellodb.sql.1
-rw-r--r-- 1 root root 7.8K Dec  2 18:41 hellodb.sql.2

 4.假如我们的备份策略为完全+增量+binlog备份,要使用binlog二进制日志重读,就要确定从备份那一刻开始,binlog的起始文件位置,这时就要使用--master-data=[#]选项,(确保二进制日志是开启的)

[root@centos7 ~]# mysqldump -uroot -hlocalhost -ptaoxiu --master-data=2 --databases hellodb > ./mysql.bak/hellodb.sql.2

[root@centos7 ~]# cat mysql.bak/hellodb.sql.2
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Position to start replication or point-in-time recovery from
--
   # 可以看到在备份的那一刻,二进制日志处在master-log.000004,POS为245
-- CHANGE MASTER TO MASTER_LOG_FILE='master-log.000003', MASTER_LOG_POS=245;

--
-- Current Database: `hellodb`
--

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hellodb` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `hellodb`;


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

基于备份做时间点恢复数据库:

   如上,我们已经备份好了hellodb的数据库,假如在备份之后,用户又修改了hellodb数据库的内容,之后hellodb数据库因为某些原因挂了,这时,我们除了借助于备份的数据库之外,还要借助于二进制日志文件binlog才能把数据库恢复到崩溃前的时间点。

 1.为了演示效果这里我首先修改一下hellodb数据库,模拟在hellodb数据库数据备份之后,崩溃之前,用户增加,修改的hellodb数据库中的内容,如下:

MariaDB [hellodb]> SELECT * FROM courses; # 修改之前的hellodb数据库courses表
+----------+----------------+
| CourseID | Course         |
+----------+----------------+
|        1 | Hamo Gong      |
|        2 | Kuihua Baodian |
|        3 | Jinshe Jianfa  |
|        4 | Taijiquan      |
|        5 | Daiyu Zanghua  |
|        6 | Weituo Zhang   |
|        7 | Dagou Bangfa   |
|       14 | Zabbix         |
+----------+----------------+
8 rows in set (0.00 sec)

MariaDB [hellodb]> INSERT INTO courses (Course) VALUES ('Puppet'),('Ansible');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [hellodb]> DELETE FROM courses WHERE CourseID=2;
Query OK, 1 row affected (0.07 sec)

MariaDB [hellodb]> SELECT * FROM courses;  # 修改之后的hellodb数据库courses表
+----------+---------------+
| CourseID | Course        |
+----------+---------------+
|        1 | Hamo Gong     |
|        3 | Jinshe Jianfa |
|        4 | Taijiquan     |
|        5 | Daiyu Zanghua |
|        6 | Weituo Zhang  |
|        7 | Dagou Bangfa  |
|       14 | Zabbix        |
|       15 | Puppet        |
|       16 | Ansible       |
+----------+---------------+
9 rows in set (0.00 sec)


MariaDB [(none)]> drop database hellodb; # 删除hellodb数据库,模拟数据库崩溃
Query OK, 7 rows affected (0.08 sec)

 2.如上hellodb数据库已经崩溃,现在要做恢复,就要准备好备份的数据库文件hellodb.sql和要做时间点恢复的二进制日志文件,如下:

 1)首先准备要做时间点恢复的二进制日志文件

# 首先准备二进制日志文件
[root@centos7 ~]# ls /var/lib/mysql/
aria_log.00000001  centos7.log       ibdata1      ib_logfile1        master-log.000002  master-log.000004  mydb   mysql.sock          Syslog  testdb  zabbix
aria_log_control   centos7-slow.log  ib_logfile0  master-log.000001  master-log.000003  master-log.index   mysql  performance_schema  test    ultrax

因为我最后执行的那个DELETE删除hellodb数据库的命令也会被记录在二进制日志文件中,所以,
要把最后的那个position截取掉,并指明完全备份时二进制日志文件的起始位置(POS),
--start-position=245(这里本来就是起始位置,可以省略,如果不是的话就要添加),这里我重定向到/tmp/如下:
[root@centos7 ~]# mysqlbinlog --start-position=245 --stop-position=7996 /var/lib/mysql/master-log.000003 > /tmp/mylog.sql

 2)准备好备份好的hellodb数据库的备份文件hellodb.sql

[root@centos7 ~]# ls mysql.bak
data.sql.3  hellodb.sql.1  hellodb.sql.2  hellodb.sql.4

[root@centos7 ~]# cp mysql.bak/hellodb.sql.2 /tmp/hellodb.sql  # 假设在/tmp目录下
[root@centos7 ~]# ls /tmp/

 3.测试,登录数据库,因为在恢复数据时会执行大量的写操作,但没有必要记录在二进制日志文件中,所以,可以关闭当前会话的二进制日志文件;然后倒入hellodb.sql脚本,可以发现hellodb数据库正常恢复到备份的时间点的数据,如下:

[root@centos7 ~]# mysql -ptaoxiu
Welcome to the MariaDB monitor.  Commands end with ; or \g.

MariaDB [(none)]> SET sql_log_bin=OFF;  # 关闭当前会话的二进制日志文件
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> \. /tmp/hellodb.sql   # 导入hellodb.sql脚本文件
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
...

MariaDB [hellodb]> select * from courses; # 查询发现数据已经恢复到备份时间点的数据
+----------+----------------+
| CourseID | Course         |
+----------+----------------+
|        1 | Hamo Gong      |
|        2 | Kuihua Baodian |
|        3 | Jinshe Jianfa  |
|        4 | Taijiquan      |
|        5 | Daiyu Zanghua  |
|        6 | Weituo Zhang   |
|        7 | Dagou Bangfa   |
|       14 | Zabbix         |
+----------+----------------+
8 rows in set (0.00 sec)

 4.接下来,我们要想恢复到数据库崩溃之前的时间点,就要借助于二进制日志文件来恢复,如下:

MariaDB [(none)]> \. /tmp/mylog.sql  # 导入二进制日志文件的sql脚本
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
...
MariaDB [hellodb]> select * from courses; # 查看数据可以发现,hellodb库的courses表恢复到了崩溃前我们修改的数据状态了
+----------+---------------+
| CourseID | Course        |
+----------+---------------+
|        1 | Hamo Gong     |
|        3 | Jinshe Jianfa |
|        4 | Taijiquan     |
|        5 | Daiyu Zanghua |
|        6 | Weituo Zhang  |
|        7 | Dagou Bangfa  |
|       14 | Zabbix        |
|       15 | Puppet        |
|       16 | Ansible       |
+----------+---------------+
9 rows in set (0.00 sec)

MariaDB [(none)]> SET sql_log_bin=ON;  # 开启记录二进制日志的文件
Query OK, 0 rows affected (0.00 sec)




基于lvm2的备份:

备份过程如下:

wKiom1hBnoageOdbAABzxmzGT2U355.png

备份工具---Xtrabackup:

 1.介绍及安装

简介:

  • Xtrabackup是由percona提供的mysql数据库备份工具,据官方介绍,这也是世界上惟一一款开源的能够对innodb和xtradb数据库进行热备的工具。

特点:

  • 物理备份,备份过程快速、可靠;

  • 备份过程不会打断正在执行的事务;

  • 能够基于压缩等功能节约磁盘空间和流量;

  • 自动实现备份检验;

  • 还原速度快;

支持的存储引擎功能

  • MyISAM:温备,不支持增量备份;

  • InnoDB:热备,增量;

安装:

  • 其最新版的软件可从 http://www.percona.com/software/percona-xtrabackup/ 获得。

  • 本文基于CentOS 7.2的系统,因此,直接下载相应版本的rpm包安装即可,这里不再演示其过程。

演示:

 1.从官方下载好要安装的相应版本的rpm包之后,在本地使用yum安装即可(会有依赖关系),程序环境如下:

[root@centos7 xtrabackup]# ls
percona-xtrabackup-2.3.2-1.el7.x86_64.rpm
[root@centos7 xtrabackup]# yum install ./percona-xtrabackup-2.3.2-1.el7.x86_64.rpm -y

[root@centos7 xtrabackup]# rpm -ql percona-xtrabackup
/usr/bin/innobackupex
/usr/bin/xbcloud
/usr/bin/xbcloud_osenv
/usr/bin/xbcrypt
/usr/bin/xbstream
/usr/bin/xtrabackup
/usr/share/doc/percona-xtrabackup-2.3.2
/usr/share/doc/percona-xtrabackup-2.3.2/COPYING
/usr/share/man/man1/innobackupex.1.gz
/usr/share/man/man1/xbcrypt.1.gz
/usr/share/man/man1/xbstream.1.gz
/usr/share/man/man1/xtrabackup.1.gz

备份的实现

 1.完全备份

语法:

  • # innobackupex --user=DBUSER --password=DBUSERPASS  /path/to/BACKUP-DIR/

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

  • mysql> CREATE USER ’bkpuser’@'localhost’ IDENTIFIED BY ’s3cret’;

  • mysql> REVOKE ALL PRIVILEGES, GRANT OPTION FROM ’bkpuser’;

  • mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'bkpuser@’localhost’;

  • mysql> FLUSH PRIVILEGES;

注意:

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

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

xtrabackup_checkpoints

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

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

xtrabackup_binlog_info

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

xtrabackup_binlog_pos_innodb 

  • 二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position。

xtrabackup_binary 

  • 备份中用到的xtrabackup的可执行文件;

backup-my.cnf 

  • 备份命令用到的配置选项信息;

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

准备(prepare)一个完全备份

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

innobakupex命令的--apply-log选项可用于实现上述功能。如下面的命令:

  • # innobackupex --apply-log  /path/to/BACKUP-DIR

如果执行正确,其最后输出的几行信息通常如下:

wKiom1hCNByDxdMRAAAhlp7LYjA333.png

从一个完全备份中恢复数据 

注意:恢复不用启动MySQL

  • innobackupex命令的--copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器DATADIR目录中来执行恢复过程。innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息。

语法:

  • # innobackupex --copy-back  /path/to/BACKUP-DIR

如果执行正确,其输出信息的最后几行通常如下:

wKioL1hCQxvCiyWqAABEMqOvxSo920.png

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动mysqld之前还需要事先修改数据文件的属主和属组。如:

  • # chown -R  mysql:mysql  /mydata/data/

实验:

  完全备份mysql数据库,并做恢复

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

 1.首先,创建一个要备份的目录文件,如下:

[root@centos7 ~]# mkdir -pv /mydata/backup
mkdir: created directory ‘/mydata’
mkdir: created directory ‘/mydata/backup’

 2.指明用户账户,密码以及要备份的目录文件路径,执行备份

[root@centos7 ~]# innobackupex --user=root --password=taoxiu /mydata/backup/

161203 11:03:04 Executing UNLOCK TABLES
161203 11:03:04 All tables unlocked      # 执行完成后释放所有的锁
161203 11:03:04 Backup created in directory '/mydata/backup//2016-12-03_11-02-48'  # 指明备份的目录
MySQL binlog position: filename 'master-log.000006', position '28684'    # 二进制日志文件的起始位置
161203 11:03:04 [00] Writing backup-my.cnf
161203 11:03:04 [00]        ...done
161203 11:03:04 [00] Writing xtrabackup_info
161203 11:03:04 [00]        ...done
xtrabackup: Transaction log of lsn (110899897) to (110899897) was copied.
161203 11:03:05 completed OK!        # 备份成功

 3.查看备份目录中生成的文件,可以发现,除了我们的数据库目录信息外,还额外添加了一些有关备份时的一些配置信息,二进制日志信息等文件,如下:

[root@centos7 ~]# cd /mydata/backup/
[root@centos7 backup]# ls
2016-12-03_15-02-43/     # 备份后生成的以时间命名的目录

[root@centos7 backup]# ll 2016-12-03_15-02-43/
total 18532
-rw-r----- 1 root root      385 Dec  3 11:03 backup-my.cnf   # 备份命令用到的配置选项信息;
drwx------ 2 root root     4096 Dec  3 11:03 hellodb
-rw-r----- 1 root root 18874368 Dec  3 11:02 ibdata1
drwx------ 2 root root       49 Dec  3 11:03 mydb
drwx------ 2 root root     4096 Dec  3 11:02 mysql
drwx------ 2 root root     4096 Dec  3 11:02 performance_schema
drwx------ 2 root root      131 Dec  3 11:03 Syslog
drwx------ 2 root root       19 Dec  3 11:02 test
drwx------ 2 root root       79 Dec  3 11:03 testdb
drwx------ 2 root root    36864 Dec  3 11:03 ultrax
-rw-r----- 1 root root       24 Dec  3 11:03 xtrabackup_binlog_info  # 二进制日志文件的起始位置
-rw-r----- 1 root root      115 Dec  3 11:03 xtrabackup_checkpoints  # 检测点包括备份类型、状态、日志序列号
-rw-r----- 1 root root      483 Dec  3 11:03 xtrabackup_info         # xtrabackup的相关信息
-rw-r----- 1 root root     2560 Dec  3 11:03 xtrabackup_logfile      # 二进制日志文件
drwx------ 2 root root     8192 Dec  3 11:03 zabbix

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

数据恢复:

 1.要想恢复数据库,首先要准备(prepare)一个完全备份,使通过回滚未提交的事务及同步已经提交的事务至数据文件也使得数据文件处于一致性状态。我这里为了演示效果,在另一台CentOS 7-2主机上做数据恢复

# 在准备要测试恢复的主机上创建备份的文件目录
[root@centos7-2 ~]#  mkdir -pv /mydata/backup    

# 把备份好的文件和xtrabackup程序包,远程复制给测试主机
[root@centos7 xtrabackup]# scp -rp 2016-12-03_15-02-43/ 10.1.249.103:/mydata/backup/
[root@centos7 xtrabackup]# scp percona-xtrabackup-2.3.2-1.el7.x86_64.rpm 10.1.249.103:/root/xtrabackup

# 同样在远程主机上安装xtrabackup的程序
[root@centos7-2 ~]#  yum install ./percona-xtrabackup-2.3.2-1.el7.x86_64.rpm -y

# 保证测试主机mysql数据库目录中是空的
[root@centos7-2 ~]# cd /var/lib/mysql/
[root@centos7-2 mysql]# rm -fr *      
[root@centos7-2 mysql]# ls

#在测试恢复数据前,mysql服务不能启动,为了使数据处于一致状态,首先准备完全备份
[root@centos7 ~]# innobackupex --apply-log /mydata/backup/2016-12-03_15-02-43/
...
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 110999897 # 可以发现序列号和原来的不同,说明有些还没提交
161203 12:06:12 completed OK!  # 提示准备成功

 2.执行innobackupex命令的--copy-back选项,制所有备份数据相关的文件至mysql服务器DATADIR目录,完成后修改mysql数据库目录中所有文件的属主和属组为mysql

[root@centos7 ~]# innobackupex --copy-back /mydata/backup/2016-12-03_11-02-48/
...
161203 12:10:59 completed OK!   # 出现此信息,提示恢复成功

# 进到数据库目录中,发现这里的属主和属组为root,还不能启动,要修改为mysql
[root@centos7 ~]# cd /var/lib/mysql/
[root@centos7 mysql]# ll            
total 116824
drwx------ 2 root root     4096 Dec  3 12:10 hellodb
-rw-r----- 1 root root 18874368 Dec  3 12:10 ibdata1
-rw-r----- 1 root root 50331648 Dec  3 12:10 ib_logfile0
-rw-r----- 1 root root 50331648 Dec  3 12:10 ib_logfile1
drwx------ 2 root root       49 Dec  3 12:10 mydb
drwx------ 2 root root     4096 Dec  3 12:10 mysql
drwx------ 2 root root     4096 Dec  3 12:10 performance_schema
drwx------ 2 root root      131 Dec  3 12:10 Syslog
drwx------ 2 root root       19 Dec  3 12:10 test
drwx------ 2 root root       79 Dec  3 12:10 testdb
drwx------ 2 root root    36864 Dec  3 12:10 ultrax
-rw-r----- 1 root root       26 Dec  3 12:10 xtrabackup_binlog_pos_innodb
-rw-r----- 1 root root      483 Dec  3 12:10 xtrabackup_info
drwx------ 2 root root     8192 Dec  3 12:10 zabbix

 # 修改文件的属主和属组为mysql
[root@centos7 mysql]# chown -R mysql.mysql ./*   
[root@centos7 mysql]# ll
total 116824
drwx------ 2 mysql mysql     4096 Dec  3 12:10 hellodb
-rw-r----- 1 mysql mysql 18874368 Dec  3 12:10 ibdata1
-rw-r----- 1 mysql mysql 50331648 Dec  3 12:10 ib_logfile0  
-rw-r----- 1 mysql mysql 50331648 Dec  3 12:10 ib_logfile1
drwx------ 2 mysql mysql       49 Dec  3 12:10 mydb
drwx------ 2 mysql mysql     4096 Dec  3 12:10 mysql
drwx------ 2 mysql mysql     4096 Dec  3 12:10 performance_schema
drwx------ 2 mysql mysql      131 Dec  3 12:10 Syslog
drwx------ 2 mysql mysql       19 Dec  3 12:10 test
drwx------ 2 mysql mysql       79 Dec  3 12:10 testdb
drwx------ 2 mysql mysql    36864 Dec  3 12:10 ultrax
-rw-r----- 1 mysql mysql       26 Dec  3 12:10 xtrabackup_binlog_pos_innodb
-rw-r----- 1 mysql mysql      483 Dec  3 12:10 xtrabackup_info
drwx------ 2 mysql mysql     8192 Dec  3 12:10 zabbix

 3.此时我们启动服务,发现还是启动不了,这是因为备份后生成的事务日志无人能建ib_logfile为50331648(48M)和mysql默认配置中的数据大小不相同,这里编辑一下配置文件,如下:

[root@centos7 mysql]# vim /etc/my.cnf
innodb_log_file_size = 50331648   # 添加事务日志大小和生成的大小一致即可

[root@centos7 mysql]# systemctl start mariadb.service  # 正常启动服务

MariaDB [hellodb]> select * from courses;  # 查询hellodb数据库中的courses表,发现和备份那一刻前的数据相同
+----------+---------------+
| CourseID | Course        |
+----------+---------------+
|        1 | Hamo Gong     |
|        3 | Jinshe Jianfa |
|        4 | Taijiquan     |
|        5 | Daiyu Zanghua |
|        6 | Weituo Zhang  |
|        7 | Dagou Bangfa  |
|       14 | Zabbix        |
|       15 | Puppet        |
|       16 | Ansible       |
+----------+---------------+
9 rows in set (0.00 sec)

 如上,就是基于xtrabackup完全备份及恢复数据的整个过程...



 2.增量备份

原理:

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

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

  • # innobackupex --incremental /backup --incremental-basedir=BASEDIR

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

注意:

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

准备(prepare)

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

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

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

操作步骤如下:

  • # 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指的是第二次增量备份的目录,其它依次类推,即如果有多次增量备份,每一次都要执行如上操作;

案例:

   在上题完全备份的基础上实现完全+增量+binlog备份并恢复数据

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

 1.在完全备份的基础上,为了演示增量备份,我这里手动修改一下数据,模拟完全备份后的数据改变;

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

MariaDB [hellodb]> INSERT INTO teachers (Name,Age,Gender) VALUES ('Miejue Shitai',48,'F');
Query OK, 1 row affected (0.07 sec)

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
5 rows in set (0.00 sec)

 2.第一次做增量备份时是基于完全备份的,所以要指明基于备份的完全备份的目录,如下:

root@centos7 ~]# innobackupex --user=root --password=taoxiu --incremental /mydata/backup/ --incremental-basedir=/mydata/backup/2016-12-03_15-02-43/
161203 16:14:48 Executing UNLOCK TABLES
161203 16:14:48 All tables unlocked
161203 16:14:48 Backup created in directory '/mydata/backup//2016-12-03_16-14-27'
MySQL binlog position: filename 'master-log.000001', position '15475756'
161203 16:14:48 [00] Writing backup-my.cnf
161203 16:14:48 [00]        ...done
161203 16:14:48 [00] Writing xtrabackup_info
161203 16:14:48 [00]        ...done
xtrabackup: Transaction log of lsn (110911268) to (110911268) was copied.
161203 16:14:48 completed OK!  # 说明增量备份成功

 3.查看增量备份的目录中的xtrabackup_checkpoints点中的开始序列号是否是在上次完全备份的基础上累加的;

[root@centos7 ~]# cd /mydata/backup/
[root@centos7 backup]# ls
2016-12-03_15-02-43  2016-12-03_16-14-27 # 增量备份的目录

[root@centos7 backup]# cd 2016-12-03_16-14-27/
[root@centos7 2016-12-03_16-14-27]# ls
backup-my.cnf  ibdata1.delta  mydb   performance_schema  test    ultrax                  xtrabackup_checkpoints  xtrabackup_logfile
hellodb        ibdata1.meta   mysql  Syslog              testdb  xtrabackup_binlog_info  xtrabackup_info         zabbix
[root@centos7 2016-12-03_16-14-27]# cat xtrabackup_checkpoints 
backup_type = incremental #  增量备份
from_lsn = 110899897     # 从这个完全备份的序列号开始备份
to_lsn = 110911268       # 到这个序列号结束
last_lsn = 110911268
compact = 0
recover_binlog_info = 0

 4.为了演示效果,这里我再一次修改数据,然后再做增量备份,如下:

MariaDB [hellodb]> DELETE FROM teachers WHERE TID=3;
Query OK, 1 row affected (0.06 sec)

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

 这时如果基于完全备份目录的话为差异备份,如果基于上一次增量备份的话即为增量备份,如下:

[root@centos7 ~]# innobackupex --user=root --password=taoxiu --incremental /mydata/backup/ --incremental-basedir=/mydata/backup/2016-12-03_16-14-27/^C

[root@centos7 ~]# cd /mydata/backup/
[root@centos7 backup]# ls
2016-12-03_15-02-43  2016-12-03_16-14-27  2016-12-03_16-32-58 #(生成的目录)
[root@centos7 backup]# cd 2016-12-03_16-32-58/
[root@centos7 2016-12-03_16-32-58]# ls
backup-my.cnf  ibdata1.delta  mydb   performance_schema  test    ultrax                  xtrabackup_checkpoints  xtrabackup_logfile
hellodb        ibdata1.meta   mysql  Syslog              testdb  xtrabackup_binlog_info  xtrabackup_info         zabbix
[root@centos7 2016-12-03_16-32-58]# cat xtrabackup_checkpoints 
backup_type = incremental
from_lsn = 110911268   # 从上一次增量备份的序列号开始
to_lsn = 110914652
last_lsn = 110914652
compact = 0
recover_binlog_info = 0

 5.再次修改数据库,来模拟还没来得及备份,数据库因为某些原因挂了的情况,这时就要启用二进制日志文件binlog进行恢复;

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

MariaDB [hellodb]> DELETE FROM teachers WHERE TID=2;
Query OK, 1 row affected (0.06 sec)

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
3 rows in set (0.00 sec)

 6.查看最后一次备份记录的二进制日志文件的结束位置,作为二进制日志文件时间点恢复的起始位置,读取二进制日志文件,重定向到/mydata/data/binlog.sql

[root@centos7 2016-12-03_16-32-58]# pwd
/mydata/backup/2016-12-03_16-32-58

[root@centos7 2016-12-03_16-32-58]# cat xtrabackup_binlog_info 
master-log.000001	15478298 # 最后一次增量备份二进制日志文件的结束位置

# 以最后一次增量备份的二进制日志文件的结束位置为起始位置导出二进制日志文件
[root@centos7 ~]# mysqlbinlog --start-position=15478298 /var/lib/mysql/master-log.000001 > /mydata/backup/binlog.sql

 7.把恢复数据所需要的所有文件远程复制给需要数据恢复的主机

[root@centos7 ~]# cd /mydata/backup/
[root@centos7 backup]# ls
2016-12-03_15-02-43  2016-12-03_16-14-27  2016-12-03_16-32-58  binlog.sql

[root@centos7 backup]# scp -rp ./* 10.1.249.103:/mydata/backup/

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

恢复数据: 

  如上整个备份的过程就已经结束,现在在CentOS 7-1测试主机上使用完全+增量+binlog恢复数据,操作过程如下:


 1.首先在要测试的主机上停掉mysql服务,把所有的数据文件全部删除,模拟mysql故障,配置文件还原到最开始的配置

[root@centos7 ~]# systemctl stop mariadb.service 
[root@centos7 ~]# rm -fr /var/lib/mysql/*
[root@centos7 ~]# ls /var/lib/mysql/      # 现在已经没有任何数据了

 2.查看恢复数据的文件,没有问题要做准备(prepare),首先将完全备份的数据提交“重放”,注意,这里不做回滚,只在最后一次备份准备prepare是才做回滚

[root@centos7 ~]# innobackupex --apply-log --redo-only /mydata/backup/2016-12-03_15-02-43/
 xtrabackup: starting shutdown with innodb_fast_shutdown = 1
 InnoDB: Starting shutdown...
 InnoDB: Shutdown completed; log sequence number 110899897
 161203 17:30:46 completed OK!

 3.把第一次增量备份的数据合并到完全备份上去,同样只做redo,不做回滚,如下:

[root@centos7 ~]# innobackupex --apply-log --redo-only /mydata/backup/2016-12-03_15-02-43/ --incremental-dir=/mydata/backup/2016-12-03_16-14-27

# 查看完全备份文件的检测点可以发现,日志序号已经位于第一次增量的起始位置
[root@centos7 backup]# cat 2016-12-03_15-02-43/xtrabackup_checkpoints 
backup_type = log-applied
from_lsn = 0
to_lsn = 110911268
last_lsn = 110911268
compact = 0
recover_binlog_info = 0

 4.同样,把最后一次增量备份的数据合并到完全备份上去,最后一次不用加redo,也就是说既要提交也要回滚,如下:

[root@centos7 ~]# innobackupex --apply-log /mydata/backup/2016-12-03_15-02-43/ --incremental-dir=/mydata/backup/2016-12-03_16-32-58

[root@centos7 backup]# cat  2016-12-03_15-02-43/xtrabackup_checkpoints 
 backup_type = log-applied
 from_lsn = 0
 to_lsn = 110914652
 last_lsn = 110914652
 compact = 0
 recover_binlog_info = 0

  5.如上整个准备(prepare)就已经完成,所有的增量都已经合并到完全备份的目录中,接下来执行--copy -back即可,执行成功后,改变属主和属组为mysql

[root@centos7 ~]# innobackupex --copy-back /mydata/backup/2016-12-03_15-02-43/
...
161203 18:43:31 completed OK!  # 执行成功

[root@centos7 ~]# cd /var/lib/mysql/
[root@centos7 mysql]# chown -R mysql.mysql ./*  # 改变属主和属组
[root@centos7 mysql]# ll
total 18520
drwx------ 2 mysql mysql     4096 Dec  3 18:43 hellodb
-rw-r----- 1 mysql mysql 18874368 Dec  3 18:43 ibdata1
drwx------ 2 mysql mysql       49 Dec  3 18:43 mydb
drwx------ 2 mysql mysql     4096 Dec  3 18:43 mysql
drwx------ 2 mysql mysql     4096 Dec  3 18:43 performance_schema
drwx------ 2 mysql mysql      131 Dec  3 18:43 Syslog
drwx------ 2 mysql mysql       19 Dec  3 18:43 test
drwx------ 2 mysql mysql       79 Dec  3 18:43 testdb
drwx------ 2 mysql mysql    36864 Dec  3 18:43 ultrax
-rw-r----- 1 mysql mysql       29 Dec  3 18:43 xtrabackup_binlog_pos_innodb
-rw-r----- 1 mysql mysql      487 Dec  3 18:43 xtrabackup_info
drwx------ 2 mysql mysql     8192 Dec  3 18:43 zabbix

  6.因为这里没有出现事务日志的文件,所以不需要在配置文件中定义事务日志文件的大小,所以我把上次完全备份恢复时在配置文件中定义的事务日志大小删除掉,然后启动服务,查看数据库,发现已经恢复到两次增量备份前的状态,如下:

[root@centos7 mysql]# systemctl start mariadb.service 

[root@centos7 mysql]# mysql -ptaoxiu
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.44-MariaDB MariaDB Server

Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> USE hellodb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
4 rows in set (0.00 sec)

  7.现在做基于二进制日志文件做时间点恢复,导入/mydata/backup/binlog.sql,然后查看数据库,发现已经恢复到数据崩溃那一刻的数据状态,如下:

[root@centos7 mysql]# mysql -uroot -hlocalhost -ptaoxiu < /mydata/backup/binlog.sql 

MariaDB [hellodb]> SELECT * FROM teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | Miejue Shitai |  48 | F      |
+-----+---------------+-----+--------+
3 rows in set (0.00 sec)


 如上,就是完全+增量+binlog备份及恢复的整个过程...