一、概念:

      备份:存储的数据副本;但是由于在备份操作时,数据依旧在变化。

      恢复:把备份的副本还原到线上系统中;但是仅能恢复到备份操作时刻的数据状态。

     备份数据是为了恢复数据,硬件故障、软件BUG、自然灾害、***、误操作 等原因,都需要涉及到数据恢复。


二、备份注意事项:

    能够容忍最多丢失多少数据,决定了备份策略;

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

     需要恢复哪些数据。


三、备份类型:

    (1)备份的数据集范围:

        完全备份:整个数据集;

          部分备份:数据集的一部分,又分为增量备份差异备份

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

                   优点:空间占用少,备份速度快;

                   缺点:每次增量备份数据都不能损坏,数据恢复慢。

                   MySQL数据库备份与恢复_第1张图片

               差异备份:仅备份自上一次完全备份以来变化的那部分数据。

                   优点:只需要最近一次差异备份加上完全备份就可恢复数据,数据恢复比增量备份快;

                   缺点:空间占用大,备份速度慢。

                  MySQL数据库备份与恢复_第2张图片


    (2)根据备份的手段:

       物理备份:直接复制文件;

         逻辑备份:导出数据另存为一个或多个文件中。


     (3)根据数据服务在线情况: 

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

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

         冷备:读写操作均不可进行的状态下进行备份。


四、备份需要考虑的因素:

    锁定资源时间;

      备份过程时长;

      备份时服务器负载量;

      恢复时长。

  

备份的策略一般为:完全备份+差异备份+binlog完全备份+增量备份+binlog

数据的备份周期一般由数据变化量、可用备份存储空间等因素来决定。

备份的内容一般有:数据、二进制日志、InnoDB事务日志、代码(存储过程、存储函数、触发器、时间调度器)、服务器配置文件等。

 

五、常用备份工具:

      mysqldump:mysql服务自带的逻辑备份工具;支持部分备份和完全备份;存储引擎为InnoDB时,最高能支持热备;存储引擎为MyISAM时最高能支持到温备。

    xtrabackup:由Percona提供,支持对InnoDB做物理热备、增量备份,速度快且可靠;备份完成后自动校验备份结果集的可用性;还原速度快。但对于MyISAM最高只支持温备,且不支持增量备份。


六、InnoDB支持热备的原理:

   InnoDB表空间中的数据都是以datablock存放,每块datablock都有一个LSN(日志序列号)标志,如果datablock发生变动,则相应的LSN也会发生变化,增量备份时,备份内容就会记录变化的datablock内容。


                    

七、实践:

示例一:使用mysqldump备份及数据恢复

备份数据

 mysqldump --user=root --host=localhost --password=root --databases hellodb --single-transaction -R --triggers -E --master-data=2 --flush-logs > /root/hellodb-$(date +%F) 

     

 MariaDB [hellodb]> SHOW MASTER LOGS;

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

  | Log_name          | File_size |

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

  | master-log.000001 |       264 |

  | master-log.000002 |       264 |

  | master-log.000003 |       437 |

  | master-log.000004 |       289 |

  | master-log.000005 |      9016 |

  | master-log.000006 |       245 |

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

由上可知,目前正在使用的是master-log.000006的二进制日志文件。


模拟数据备份后持续变化:

MariaDB [(none)]> USE hellodb;

MariaDB [hellodb]> INSERT INTO teachers VALUES (6,'Mo Yuan',100,'M');

 

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 | Feng Qingyang |  99 | M      |

|   6 | Mo Yuan       | 100 | M      |

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


模拟数据丢失:

MariaDB [hellodb]> SET @@sql_log_bin=OFF;   #关闭二进制日志记录功能,因为数据丢失不需要记录到二进制日志中

MariaDB [hellodb]> DROP DATABASE hellodb;   #删除hellodb数据库,模拟数据丢失


导出完全备份之后的二进制文件:

[root@node7 ~]# mysqlbinlog /var/lib/mysql/master-log.000006 > /root/bin.log


恢复数据:

[root@node7 ~]# mysql -uroot -hlocalhost -proot < /root/hellodb-2017-02-20  #完全备份恢复

MariaDB [hellodb]> source /root/bin.log;  #二进制文件恢复

 

MariaDB [(none)]> SHOW DATABASES;

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

| Database           |

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

| information_schema |

| mydb               |

| mysql              |

| performance_schema |

| test               |

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

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 | Feng Qingyang |  99 | M      |

|   6 | Mo Yuan       | 100 | M      |

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


示例二:使用xtrabackup备份及数据恢复

下载percona-xtrabackup软件包,并安装:

   yum install ./percona-xtrabackup-2.3.2-1.el7.x86_64.rpm

   此软件包会依赖到另外两个软件包libev、rsync。


  查看安装生成的文件

  [root@node7 ~]# 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

  innobackupex使用perl语言对xtrabackup进行的二次封装,比xtrabackup自身更易用。


② 第一次备份要进行一次完全备份,备份文件存放路径为/data/backup:

   innobackupex --user=root --host=localhost --password=root /data/backup

   命令执行后,一定要确认最后有“completed OK!”的字样!

                       

  [root@node7 ~]# cd /data/backup/

   [root@node7 backup]# ls

    2017-02-20_04-06-47

  可以看到已经生成了一个以当前日期和时间命名的目录,该目录存放有以下文件:

  [root@node7 2017-02-20_04-06-47]# ls -1

    backup-my.cnf              # my.cnf文件备份,运行参数

    hellodb

    ibdata1

    mydb

    mysql

    performance_schema

    test

    xtrabackup_binlog_info    # 记录备份操作时,使用的二进制日志文件及位置

    xtrabackup_checkpoints    # 检查点文件

    xtrabackup_info           # 记录执行backup时,自身的环境信息

    xtrabackup_logfile        # 事务日志信息


③ 之后对仅完全备份恢复、增量备份恢复和差异备份恢复三种情况进行模拟:

1、完全备份恢复

模拟数据库数据丢失:

[root@node7 ~]# cd /var/lib/mysql/

[root@node7 mysql]# rm -rf *

           

准备一个完全备份,使用innobackupex命令的--apply-log选项可以实现:

[root@node7 mysql]# cd /data/backup/

[root@node7 backup]# innobackupex --apply-log 2017-02-20_04-06-47/

同样要确定有“completed OK!”的字样!


但是这里有个问题存在:

命令执行过程中,innodb_log_file_size被设置了一个初始化值:xtrabackup:   innodb_log_file_size = 50331648

,而backup-my.cnf文件中的配置为:innodb_log_file_size=5242880,所以需要将/etc/my.cnf.d/server.cnf的[mysqld]字段中添加:innodb_log_file_size=50331648

[mysqld]

innodb_log_file_size=50331648

       

还原操作,使用innobackupex命令的--copy-back选项可以实现:

[root@node7 backup]# innobackupex --copy-back ./2017-02-20_04-06-47/

同样要确定有“completed OK!”的字样!

               

这样已经恢复数据库中的数据,但是还得修改其属主属组为mysql用户或用户组:

[root@node7 backup]# cd /var/lib/mysql/

[root@node7 mysql]# chown -R mysql:mysql *

 

启动数据库检查数据:

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

[root@node7 mysql]# mysql -u root -h 127.0.0.1 -p

Enter password:

MariaDB [(none)]> SHOW DATABASES;

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

| Database           |

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

| information_schema |

| hellodb            |

| mydb               |

| mysql              |

| performance_schema |

| test               |

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

6 rows in set (0.12 sec)

          

恢复数据之后,二进制日志文件会重新记录:                            

MariaDB [(none)]> SHOW MASTER LOGS;

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

| Log_name          | File_size |

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

| master-log.000001 |       245 |

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

1 row in set (0.00 sec)

 

 

注意:

   (1) 备份任务脚本化、周期性执行;

   (2) 备份结果单独存放,最好异地备份;

   (3) 执行脚本前,要对备份的结果进行测试。



2、增量备份恢复(完全备份+增量备份+binlog)

此次完全备份为:/data/backup/2017-02-20_05-03-12,操作参考上文。

查看此次完全备份的xtrabackup_checkpoints文件信息:

[root@node7 2017-02-20_05-03-12]# less xtrabackup_checkpoints

backup_type = full-backuped     #备份类型

from_lsn = 0                    #开始的lsn编号

to_lsn = 1648662                #结束的lsn编号

last_lsn = 1648662              #最后的lsn编号

compact = 0

recover_binlog_info = 0


对数据进行第一次写操作,模拟数据变化:

MariaDB [(none)]> USE hellodb

MariaDB [hellodb]> CREATE TABLE hisen (id INT NOT NULL PRIMARY KEY ,name VARCHAR(100));

MariaDB [hellodb]> INSERT INTO hisen VALUES (1,'hisen'),(2,'xuhe'),(3,'wulei');                   

MariaDB [hellodb]> SELECT * FROM hisen;

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

| id | name  |

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

|  1 | hisen |

|  2 | xuhe  |

|  3 | wulei |

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

3 rows in set (0.00 sec)

 

对数据进行第一次增量备份:

[root@node7 ~]# innobackupex --incremental --user=root --host=localhost --password=root /data/backup/ --incremental-basedir=/data/backup/2017-02-20_05-03-12/

/data/backup为增量备份保存路径,/data/backup/2017-02-20_05-03-12/为完全备份路径。


查看一下第一次增量备份的xtrabackup_checkpoints文件信息:

[root@node7 2017-02-20_05-12-29]# less xtrabackup_checkpoints

backup_type = incremental    #备份类型

from_lsn = 1648662           #lsn开始编号

to_lsn = 1652217             #lsn结束编号

last_lsn = 1652217           #最后的lsn编号

compact = 0

recover_binlog_info = 0

对比完全备份的xtrabackup_checkpoints文件信息发现:此次增量备份的lsn编号完全能对上完全备份的最后一个lsn编号。

如果第一次增量备份是基于完全备份,其他增量备份基于自己上次增量备份,则备份为增量备份;

而如果所有备份都是基于完全备份,则备份为差异备份。

 

对数据进行第二次写操作,模拟数据变化:

MariaDB [hellodb]> INSERT INTO hisen VALUES(4,'tiantao'),(5,'liangjuntao');

MariaDB [hellodb]> SELECT * FROM hisen;

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

| id | name        |

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

|  1 | hisen       |

|  2 | xuhe        |

|  3 | wulei       |

|  4 | tiantao     |

|  5 | liangjuntao |

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

5 rows in set (0.01 sec)

 

对数据进行第二次增量备份:

innobackupex --incremental --user=root --host=localhost --password=root /data/backup/ --incremental-basedir=/data/backup/2017-02-20_05-12-29/

/data/backup为增量备份保存路径,/data/backup/2017-02-20_05-12-29/为上一次增量备份路径。


查看一下第二次增量备份的xtrabackup_checkpoints文件信息:

[root@node7 2017-02-20_05-33-01]# less xtrabackup_checkpoints

backup_type = incremental  #增量类型

from_lsn = 1652217         #lsn开始编号

to_lsn = 1652590           #lsn结束编号

last_lsn = 1652590         #最后的lsn编号

compact = 0

recover_binlog_info = 0

对比第一次增量备份的xtrabackup_checkpoints文件信息发现:第二次增量备份的lsn编号完全能对上第一次增量备份的最后一个lsn编号。

 

对数据进行第三次写操作,模拟数据变化:

此次数据变化之后,不再进行增量备份,恢复完整数据还得需要binlog。

MariaDB [hellodb]> DELETE FROM hisen WHERE id=1;                     

MariaDB [hellodb]> SELECT * FROM hisen;

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

| id | name        |

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

|  2 | xuhe        |

|  3 | wulei       |

|  4 | tiantao     |

|  5 | liangjuntao |

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

4 rows in set (0.00 sec)

 

查看最后一次进行增量备份的xtrabackup_binlog_info文件中,binlog执行的位置,除了恢复完全备份数据+增量备份数据之外,还需要恢复820之后的binlog数据;

[root@node7 2017-02-20_05-33-01]# less xtrabackup_binlog_info

master-log.000001       820

  

将820之后的binlog日志导出到一文件目录下:

[root@node7 ~]# mysqlbinlog /var/lib/mysql/master-log.000001 --start-position=820 > /tmp/bin.log

 

模拟数据损坏:

[root@node7 ~]# cd /var/lib/mysql/

[root@node7 mysql]# rm -rf *

 

准备完全备份:

[root@node7 backup]# innobackupex --apply-log --redo-only ./2017-02-20_05-03-12/

 

对第一次增量备份与完全备份进行整合:

[root@node7 backup]# innobackupex --apply-log --redo-only 2017-02-20_05-03-12/ --incremental-dir=/data/backup/2017-02-20_05-12-29/

 

对第二次增量备份与完全备份进行整合:

[root@node7 backup]# innobackupex --apply-log --redo-only 2017-02-20_05-03-12/ --incremental-dir=/data/backup/2017-02-20_05-33-01/

 

现在再次查看整合后的完全备份的xtrabackup_binlog_info文件信息:           

[root@node7 2017-02-20_05-03-12]# less xtrabackup_checkpoints

backup_type = log-applied   #整合后类型

from_lsn = 0                #开始lsn编号

to_lsn = 1652590            #结束lsn编号

last_lsn = 1652590          #最后lsn编号

compact = 0

recover_binlog_info = 0

由上信息发现:整合后的lsn的开始编号为完全备份时的开始lsn编号,lsn结束编号则为最后一次增量最后的lsn编号。

       

根据整合后的完全备份恢复数据:

[root@node7 backup]# innobackupex --copy-back 2017-02-20_05-03-12/

 

修改恢复后的数据文件属主属组:

[root@node7 backup]# cd /var/lib/mysql/

[root@node7 mysql]# chown -R mysql:mysql *  

       

[root@node7 ~]# systemctl start mariadb.service   #启动数据库服务

[root@node7 ~]# mysql -uroot -h 127.0.0.1 -p      #连接至数据库

MariaDB [(none)]> USE hellodb;                   #使用hellodb数据库         

MariaDB [hellodb]> SELECT * FROM hisen;           #查看hisen表

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

| id | name        |

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

|  1 | hisen       |

|  2 | xuhe        |

|  3 | wulei       |

|  4 | tiantao     |

|  5 | liangjuntao |

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

5 rows in set (0.01 sec)

发现id=1的行还在,只能用binlog恢复最后一次增量备份之后的数据。

      

恢复binlog日志文件,需要先关闭binlog记录日志功能:

MariaDB [(none)]> SET @@session.log_bin=OFF;   #关闭binlog日志记录功能

MariaDB [hellodb]> source /tmp/bin.log         #导入bin.log文件

MariaDB [hellodb]> SELECT * FROM hisen;

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

| id | name        |

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

|  2 | xuhe        |

|  3 | wulei       |

|  4 | tiantao     |

|  5 | liangjuntao |

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

4 rows in set (0.01 sec)

发现id=1的行已经消失了。   

MySQL数据库备份与恢复_第3张图片

3、差异备份

   差异备份可以看成是特殊的增量备份,只不过每次都是基于完全备份的增量备份,可以参考增量备份的配置。

MySQL数据库备份与恢复_第4张图片

结论:在数据恢复之后,要立刻做一次全新的完全备份;建议将之前恢复时用到的数据另存其他空间,以防万一。