MySQL增量备份与恢复

技能目标

  • 理解MySQL增量备份的概念
  • 理解MySQL增量备份与恢复的方法

1:增量备份的概念

完全备份每次把所有文件全部备份一边占用空间较大,增量备份就解决了这一问题它可以在你完全备份后如果做了修改或者需要备份的文件不大就用增量备份去解决这一问题
2:增量备份的特点
(1)二进制文件保存了所有更新或者可能更新数据库操作
(2)二进制文件在启动MySQL服务后开始记录
(3)只需要执行刷新就能创建新日志

增量备份实战演练

下面是生产环境中的案例,对它进行增量备份操作

1.需求描述

某公司用户信息数据库为client,用户资源表为user_info

需求如下

(1):请为该公司每周进行完全备份

(2):每天为该公司进行增量备份

(3):新增加用户信息如下

id name zifei
1 wang-1 10
2 wang-2 20
实现增量备份
#1:先把下列原有的表进行完全备份在备份前先刷新一次
[root@localhost data] mysqladmin -u root -p flush-logs
mysql> select * from user_info;
+------+---------+-------+
| id   | name    | zifei |
+------+---------+-------+
|    1 | zhang-1 |    10 |
|    2 | zhang-2 |    20 |
|    3 | zhang-3 |     5 |
+------+---------+-------+
3 rows in set (0.00 sec)
[root@localhost data] mysqldump -u root -p client user_info > /usr/local/mysql/data/client-user_info.sql
Enter password
[root@localhost data] ls
client-user_info.sql

#2:添加wang-1信息后进行增量备份
mysql> insert into user_info (id,name,zifei) values (4,'wang-1',10);
Query OK, 1 row affected (0.00 sec)
[root@localhost data] mysqladmin -uroot -p flush-logs
Enter password:       #上面的命令刷新保存在mysql-bin.000001里面
[root@localhost data]# ls # mysql-bin.000002是 mysql-bin.000001保存之后会生成一个空的日志等待下一次增量备份
mysql-bin.000001
mysql-bin.000002 
#3:添加wang-2的信息后进行增量备份
mysql> insert into user_info (id,name,zifei) values (5,'wang-2',20);
Query OK, 1 row affected (0.00 sec)
[root@localhost data] mysqladmin -uroot -p flush-logs
Enter password: 
[root@localhost data]# ls
mysql-bin.000002 
mysql-bin.000003
每一次增量备份后它都会生成一个空的二进制文件,以便下一次的增量备份,恢复的时候是逆推恢复就是说你恢复mysql-bin.000002其实是恢复的你上一次所做的操作

MySQL增量恢复

1:加入你把原表中wang-1,wang-2删除需要恢复此增量文件需做如下操作
#下表中wang-1,wang-2已被删除
mysql> select * from user_info;
+------+---------+-------+
| id   | name    | zifei |
+------+---------+-------+
|    1 | zhang-1 |    10 |
|    2 | zhang-2 |    20 |
|    3 | zhang-3 |     5 |
+------+---------+-------+
5 rows in set (0.00 sec)

#恢复wang-1
[root@localhost data] mysqlbinlog --no-defaults mysql-bin.000002 | mysql -u root -p 
#先恢复mysql-bin.000002我们看一下
mysql> select * from user_info;
+------+---------+-------+
| id   | name    | zifei |
+------+---------+-------+
|    1 | zhang-1 |    10 |
|    2 | zhang-2 |    20 |
|    3 | zhang-3 |     5 |
|    5 | wang-2  |    20 |
+------+---------+-------+
4 rows in set (0.00 sec)
#恢复的是我最后一次操作备份wang-2的数据

#恢复mysql-bin.000001看一下
[root@localhost data]# mysqlbinlog --no-defaults mysql-bin.000001 | mysql -u root -p
mysql> select * from user_info;
+------+---------+-------+
| id   | name    | zifei |
+------+---------+-------+
|    1 | zhang-1 |    10 |
|    2 | zhang-2 |    20 |
|    3 | zhang-3 |     5 |
|    4 | wang-2  |    10 |
|    5 | wang-2  |    20 |
+------+---------+-------+
4 rows in set (0.00 sec)

查看二进制文件如果你直接用下面的语句操作他会看不到你操作的语句会自动给你加密

[root@localhost data] mysqlbinlog --no-defaults mysql-bin.000001
BINLOG ' #下面加密的哪一行就是你在数据库进行操作
PCE7WxMBAAAAOgAAAEkIAAAAANsAAAAAAAEABmNsaWVudAAJdXNlcl9pbmZvAAMDDwMCHgAH7bXH
3w==
PCE7WyABAAAAMwAAAHwIAAAAANsAAAAAAAEAAgAD//gFAAAABndhbmctMhQAAABJK6gI
'/*!*/;
# at 2172

#想要解密这个加密文件用下列语句
[root@localhost data] mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000001
### DELETE FROM `client`.`user_info`
### WHERE #下面就是之前看不到的加密的部分
###   @1=5
###   @2='wang-2'
###   @3=20

节点和位置恢复

(在增量备份的时候中间有一个错误操作跳过如果在正常的恢复增量操作的话会把原来需要的数据还是一并给删除所以我们就可以跳过中间的错误操作继续只能错误操作下面的正确语句)

操作演示

#下面有一张表先对它进行完全备份
mysql> select * from user;
+-------+-------+
| name  | sroce |
+-------+-------+
| tom   |    88 |
| jarry |    88 |
+-------+-------+
2 rows in set (0.00 sec)
[root@localhost ~]# mysqldump -u root -p cilent > /opt/cilent.sql
Enter password: 
[root@localhost ~]# ls /opt/
cilent.sql 

#刷新二进制日志
[root@localhost data]# mysqladmin -u root -p flush-logs
Enter password:
 mysql-bin.000001  mysql-bin.000002

 #下面进行添加表中内容中间加入一个误操作
mysql> insert into user (name,sroce) values ('test01',70); #添加测试用户test01
Query OK, 1 row affected (0.00 sec)                   
mysql> delete from user where name='tom';                   #删除表中原有的tom用户
Query OK, 1 row affected (0.01 sec)
mysql> insert into user (name,sroce) values ('test02',70);  #再添加测试用户test02
Query OK, 1 row affected (0.01 sec)
mysql> select * from user;
+--------+-------+
| name   | sroce |
+--------+-------+
| jarry  |    88 |
| test01 |    70 |
| test02 |    70 |
+--------+-------+
3 rows in set (0.00 sec)
先从时间节点恢复
#删除数据库中原有表,恢复之前的完全备份
mysql> drop table user;
Query OK, 0 rows affected (0.05 sec)
mysql> show tables;
Empty set (0.00 sec)
mysql> select * from user; #tom被误操作通过对完全备份的恢复已经恢复过来
+-------+-------+
| name  | sroce |
+-------+-------+
| tom   |    88 |
| jarry |    88 |
+-------+-------+
2 rows in set (0.00 sec)
恢复之前的完全备份后查看二进制日志并记录开始和结束时间
#把下面解析出来的二进制日志另外生成一个文件方便后面查询
[root@localhost data]# mysqlbinlog --no-defaults --base64-output=decode-rows -v mysql-bin.000002 > /opt/mysql-bin.txt
下面是错误操作错误操作的起始时间是第一次节点的停止时间 180704 10:14:12

#180704 10:14:12 server id 1  end_log_pos 658 CRC32 0x4379f2f8  Delete_rows: table id 219 flags: STMT_END_F
### DELETE FROM `cilent`.`user`  

恢复第一个test01的正确操作

[root@localhost data]# mysqlbinlog --no-defaults --stop-datetime='2018-07-04 10:14:12' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
Enter password: 
mysql> select * from user;  #恢复了test01
+--------+-------+
| name   | sroce |
+--------+-------+
| tom    |    88 |
| jarry  |    88 |
| test01 |    70 |
+--------+-------+
3 rows in set (0.00 sec)
下面这一条是错误操作的结束时间是第二次开始增量恢复的开始时间 180704 10:14:20
#180704 10:14:20 server id 1  end_log_pos 754 CRC32 0x60352ff6  Anonymous_GTID  last_committed=2        sequence_number=3
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
#跳过删除tom的操作恢复test02
[root@localhost data]# mysqlbinlog --no-defaults --start-datetime='2018-07-04 10:14:20' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
Enter password: 
mysql> select * from user;
+--------+-------+
| name   | sroce |
+--------+-------+
| tom    |    88 |
| jarry  |    88 |
| test01 |    70 |
| test02 |    70 |
+--------+-------+
4 rows in set (0.00 sec)
位置序号节点恢复,找到对应序号并记录下来
# at 488  #第一次恢复的停止节点“488”
#180704 10:14:12 server id 1  end_log_pos 562 CRC32 0xff99725b  Query   thread_id=9     exec_time=0     error_code=0
[root@localhost data]# mysqlbinlog --no-defaults --stop-position='488' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
mysql> select * from user;
+--------+-------+
| name   | sroce |
+--------+-------+
| tom    |    88 |
| jarry  |    88 |
| test01 |    70 |
+--------+-------+
3 rows in set (0.00 sec)
找到正确操作的起始时间并记录
# at 689 #跳过错误操作的正确操作的起始时间“689
#180704 10:14:20 server id 1  end_log_pos 754 CRC32 0x60352ff6  Anonymous_GTID  last_committed=2        sequence_number=3
[root@localhost data]# mysqlbinlog --no-defaults --start-position='689' /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -p
mysql> select * from user;
+--------+-------+
| name   | sroce |
+--------+-------+
| tom    |    88 |
| jarry  |    88 |
| test01 |    70 |
| test02 |    70 |
+--------+-------+
4 rows in set (0.00 sec)