一、概念:
备份:存储的数据副本;但是由于在备份操作时,数据依旧在变化。
恢复:把备份的副本还原到线上系统中;但是仅能恢复到备份操作时刻的数据状态。
备份数据是为了恢复数据,硬件故障、软件BUG、自然灾害、***、误操作 等原因,都需要涉及到数据恢复。
二、备份注意事项:
能够容忍最多丢失多少数据,决定了备份策略;
恢复数据需要在多长时间内完成;
需要恢复哪些数据。
三、备份类型:
(1)备份的数据集范围:
完全备份:整个数据集;
部分备份:数据集的一部分,又分为增量备份、差异备份。
增量备份:仅备份自上一次完全备份或增量备份以来变化的那部分数据。
优点:空间占用少,备份速度快;
缺点:每次增量备份数据都不能损坏,数据恢复慢。
差异备份:仅备份自上一次完全备份以来变化的那部分数据。
优点:只需要最近一次差异备份加上完全备份就可恢复数据,数据恢复比增量备份快;
缺点:空间占用大,备份速度慢。
(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的行已经消失了。
3、差异备份
差异备份可以看成是特殊的增量备份,只不过每次都是基于完全备份的增量备份,可以参考增量备份的配置。
结论:在数据恢复之后,要立刻做一次全新的完全备份;建议将之前恢复时用到的数据另存其他空间,以防万一。