恢复 MySQL 数据库人为误操作丢失的数据

1. 全量备份与增量备份理论基础

1.1 全量备份

全量数据就是数据库中的所有数据,全量备份就是把数据库中所有的数据进行备份。

1.2 增量备份

增量数据就是从上次全量备份之后,到下一次全备之前时间段更新的新数据。对于 MySQL 来说,binlog 日志就是 MySQL 的增量数据。

1.3 按天全备备份:每天零点做一次全备

优点:恢复时间短,维护成本低;

缺点:占用空间多,占用系统资源多,经常锁表影响用户体验。

1.4按周全备备份:每周六零点做一次全备

优点:占用空间小(一周一个所有数据的副本),占用系统资源少,无需经常锁表,用户体验好。

缺点:维护成本高,恢复数据麻烦,耗时长。

提示:以上优缺点都是在一般情况下,排除在从库做备份的情况。

1.5 企业场景全量和增量备份的做法

① 中小公司,全量一般是每天一次,业务流量低估执行全备,备份时会锁表。

② 单台数据库(没有主从同步)的增量一般用 rsync 把所有的 binlog 备份到远程服务器;尽量做主从复制保证数据不丢失。

③ 大公司周备,每周六 0 点做一次全量备份,周日到下周六之前都是增量。

优点:节省备份时间,减小备份压力。

缺点:增量的 binlog 文件副本太多,还原会很麻烦。

④ 一主多从,会有一个从库做备份,延迟同步。

1.6 MySQL 的 mysqldump 备份什么时候能派上用场

① 迁移或者升级数据库时;

② 增加从库的时候;

③ 因为硬件问题或特殊异常情况,主库或从库宕机,主从可互相切换,这种情况下不需要备份。

④ 人为的 DDL,DML 语句误操作,导致误删数据,主从库都会执行,此时就需要备份。

⑤ 跨机房灾备,需要将全量备份拷贝到异地容灾环境。

1.7 什么情况下需要增量恢复

我们在生产环境中一般常用一主多从的数据库架构,常见的备份方案是在某一个不对外服务的从库上开启 binlog,然后实施定时全备和时时增量备份。

增量恢复:利用二进制日志和全备进行的恢复数据的过程就是增量恢复。

① 主库或从库宕机(硬件损坏)是否需要增量恢复?

答案:不需要增量恢复,只需要把其中一个同步最快的从库切换为主库即可。

② 人为操作数据库 SQL 语句破坏主库是否需要增量恢复?

答案:在数据库主库内部命令行误操作,会导致所有的数据库(包括主从库)数据丢失,例如在主库执行了 drop database test; 这样的删除语句,所有的从库也会执行这个语句,从而导致所有的数据库上的 test 库数据丢失,这样的场景是需要增量恢复的。

③ 只有一个主库是否需要增量恢复?

答案:如果公司只有一个主库的情况,首先应该做定时全量备份(一天一次)及增量备份(每隔一到十分钟对 binlog 日志做切割然后备份到其他服务器上或本地其他的硬盘里)或者写到网络文件系统(备份服务器)里。

如果不允许数据丢失,最好的办法是做从库,通过 drbd(基于磁盘快)的同步。

小结:一般由人为(或程序)逻辑的方式在数据库执行的 SQL 语句等操作,才需要增量恢复,因为此时所有的从库上也执行了误操作语句。

1.8 MySQL 增量恢复必备条件 

① 开启 MySQL 的记录 binlog 日志功能:

[root@master ~]# grep log-bin /etc/my.cnf

log-bin=mysql-bin

提示:主库和备份的从库都要开启 binlog 记录功能。

小结:增量恢复的条件:

存在一份全备加上全备之后的时刻到出问题时刻的所有增量 binlog 文件备份。

② 存在 MySQL 数据库全备:

生产环境 mysqldump 备份命令:略

在凌晨某一时刻进行数据库全备(生产场景一般通过定时任务每日凌晨执行)。

2.  MySQL 人为误操作丢失数据场景模拟

2.1 创建 student 表并插入数据做全备

[root@master ~]# mysql -uroot -p123456    

mysql> use oldboy

Database changed

mysql>  CREATE TABLE `student` (

  `id` int(4) NOT NULL AUTO_INCREMENT,

  `name` char(20) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;

INSERT INTO `student` VALUES (1,'oldboy'),(2,'oldgirl'),(3,'inca'),(4,'zuma'),(5,'kaka'),(6,'kobe'),(7,'james'),(8,'iverson'),(9,'embid');

mysql> show tables;

| Tables_in_oldboy |

| student          |

mysql> select * from student;

| id | name    |

|  1 | oldboy  |

|  2 | oldgirl   |

|  3 | inca      |

|  4 | zuma    |

|  5 | kaka     |

|  6 | kobe     |

|  7 | james   |

|  8 | iverson |

|  9 | embid   |

[root@master ~]# date -s '2018/05/11'    #  修改时间为 0 点。

Fri May 11 00:00:00 CST 2018

[root@master ~]# mkdir /server/backup  #  创建备份的目录。

[root@master ~]#  mysqldump -uroot -p123456 --master-data=2 -F -B oldboy|gzip >/server/backup/bak_$(date +%F).sql.gz   #  为 oldboy 数据库做全备。

2.2 模拟插入数据

[root@master ~]# mysql -uroot -p123456   #  登陆数据库写数据。

mysql> use oldboy

mysql> desc student;

| Field   | Type       | Null   | Key | Default | Extra                  |

| id        | int(4)       | NO    | PRI | NULL    | auto_increment |

| name  | char(20) | NO    |         | NULL    |                           |

mysql> insert into student(name) values('oldboy101');

mysql> insert into student(name) values('oldboy102');

mysql> select * from student;    #  查看上面插入的两条数据。

| 10 | oldboy101 |

| 11 | oldboy102 |

2.3 模拟用户破环数据

mysql> show databases;

| oldboy             |

mysql> drop database oldboy;  #  删除 oldboy 库。

mysql> show databases;  #  oldboy 库已经不存在。    

3. 发现故障并排查原因

       数据库出问题 10 分钟后,公司的网站运营人员报网站故障,联系运维人员解决。此时,DBA 人员或开发人员通过查看网站报错(或者查看后台日志),可以看到连不上 oldboy 库的提示,然后通过登陆数据库排查发现 oldboy 库不存在了,被同事误删了。

提示:通过对数据库权限的严格管理及审核可避免此类误操作问题的发生。

4. 增量恢复过程

4.1 恢复丢失数据前提

通过防火墙禁止 web 等应用向主库写数据或者锁表,让主库暂停时停止更新,然后再进行恢复(若允许停库最好)。

4.2 检查全备及 binlog 日志

root@master ~]# ll /server/backup/   #  检查全备。

-rw-r--r-- 1 root root 913 May 11 00:07 bak_2018-05-11.sql.gz

[root@master ~]# ll /application/mysql/data/   #  查看 binlog 日志。

-rw-rw---- 1 mysql mysql     1654 May 11 00:04 mysql-bin.000005

-rw-rw---- 1 mysql mysql      150 May 11 00:05 mysql-bin.000006

-rw-rw---- 1 mysql mysql      150 May 11 00:07 mysql-bin.000007

-rw-rw---- 1 mysql mysql      662 May 11 00:19 mysql-bin.000008

-rw-rw---- 1 mysql mysql      152 May 11 00:07 mysql-bin.index

[root@master ~]# cd /server/backup/

[root@master backup]# ll

-rw-r--r-- 1 root root 913 May 11 00:07 bak_2018-05-11.sql.gz

[root@master backup]# gzip -d bak_2018-05-11.sql.gz

[root@master backup]# grep -i "change" bak_2018-05-11.sql

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000008', MASTER_LOG_POS=107;  

4.3 立即刷新并备份出增量 binlog 数据

[root@master backup]# mysqladmin -uroot -p123456 flush-logs   #  刷新 binlog 。

[root@master backup]# ll /application/mysql/data/   #  查看。

-rw-rw---- 1 mysql mysql      705 May 11 00:42 mysql-bin.000008   #  需要恢复的 binlog(误操作语句)。

-rw-rw---- 1 mysql mysql      107 May 11 00:42 mysql-bin.000009   #  插入新数据的 binlog(人为误操作后用户插入其他数据)。

[root@master backup]# cp /application/mysql/data/mysql-bin.000008 /server/backup/  #  备份增量(全备以后的含有误操作语句的增量)。

[root@master backup]# ll /server/backup/

-rw-r--r-- 1 root root 2284 May 11 00:07 bak_2018-05-11.sql

-rw-r----- 1 root root  705 May 11 00:46 mysql-bin.000008

[root@master backup]# mysqlbinlog -d oldboy mysql-bin.000008

[root@master backup]# mysqlbinlog -d oldboy mysql-bin.000008 >bin.sql

[root@master backup]# vi bin.sql   #  找到 drop database oldboy; 误操作语句并把它删掉。

[root@master backup]# ll   #  把下面的两个恢复进去即可。

-rw-r--r-- 1 root root 2284 May 11 00:07 bak_2018-05-11.sql   #  全量。

-rw-r--r-- 1 root root 2352 May 11 00:50 bin.sql                        #  清除误操作语句的增量数据。

4.4 问题:恢复数据的语句会记录到新的 binlog 文件中

mysql> show variables like '%log_bin%';

| Variable_name                                    | Value |

| log_bin                                                | ON    |

| log_bin_trust_function_creators          | OFF   |

| sql_log_bin                                         | ON    |    

#  该参数改为 off 就可以不记录恢复过程,但是用户写入数据也无法记录了。因为此处没有用户往数据库写入数据,企业场景会通过防火墙不让用户写入或者让用户只读。

4.5 开始恢复数据

[root@master backup]# mysql -uroot -p123456 <bak_2018-05-11.sql  # 恢复全量备份。

[root@master backup]# mysql -uroot -p123456 oldboy <bin.sql                       # 恢复增量备份。

[root@master backup]#  mysql -uroot -p123456     #  查看数据恢复结果。

mysql> show databases;

| oldboy             |

mysql> use oldboy

mysql> select * from student;

|  1 | oldboy        |

|  2 | oldgirl         |

|  3 | inca            |

|  4 | zuma          |

|  5 | kaka           |

|  6 | kobe           |

|  7 | james         |

|  8 | iverson       |

|  9 | embid         |

| 10 | oldboy101 |

| 11 | oldboy102  |

5. 案例总结

5.1 增量恢复小结

① 人为 SQL 造成的误操作;

② 全备和增量;

③ 恢复时建议对外停止更新;

④ 恢复全量,然后把增量日志中有问题的 SQL 语句删除,恢复到数据库。

5.2 增量恢复核心思想

① 流程制度控制,防止问题发生。如果不做流程制度控制,就会面临停止服务和丢失数据之间的取舍;

② 在业务上对一些信息做监控,黑名单,白名单机制。(通过流程制度控制不加 while 语句不能执行等);

③ 根据业务需求容忍度,制定一个可量化的目标,根据需求来选择停库或锁表或者容忍丢失部分数据。

猜你喜欢

转载自www.cnblogs.com/alinuxer/p/9896068.html