(一)概述

在日常MySQL数据库运维过程中,可能会遇到用户误删除数据,常见的误删除数据操作有:

  • 用户执行delete,因为条件不对,删除了不应该删除的数据(DML操作);
  • 用户执行update,因为条件不对,更新数据出错(DML操作);
  • 用户误删除表drop table(DDL操作);
  • 用户误清空表truncate(DDL操作);
  • 用户删除数据库drop database,跑路(DDL操作)
  • …等

这些情况虽然不会经常遇到,但是遇到了,我们需要有能力将其恢复,下面讲述如何恢复。

(二)恢复原理

如果要将数据库恢复到故障点之前,那么需要有数据库全备和全备之后产生的所有二进制日志。

全备作用 :使用全备将数据库恢复到上一次完整备份的位置;

二进制日志作用:利用全备的备份集将数据库恢复到上一次完整备份的位置之后,需要对上一次全备之后数据库产生的所有动作进行重做,而重做的过程就是解析二进制日志文件为SQL语句,然后放到数据库里面再次执行。

举个例子:小明在4月1日晚上8:00使用了mysqldump对数据库进行了备份,在4月2日早上12:00的时候,小华不小心删除了数据库,那么,在执行数据库恢复的时候,需要使用4月1日晚上的完整备份将数据库恢复到“4月1日晚上8:00”,那4月1日晚上8:00以后到4月2日早上12:00之前的数据如何恢复呢?就得通过解析二进制日志来对这段时间执行过的SQL进行重做。

(三)删库恢复测试

(3.1)实验目的

在本次实验中,我直接测试删库,执行drop database lijiamandb,确认是否可以恢复。

(3.2)测试过程

在测试数据库lijiamandb中创建测试表test01和test02,然后执行mysqldump对数据库进行全备,之后执行drop database,确认database是否可以恢复。

STEP1:创建测试数据,为了模拟日常繁忙的生产环境,频繁的操作数据库产生大量二进制日志,我特地使用存储过程和EVENT产生大量数据。

创建测试表:

use lijiamandb;create table test01 ( id1 int not null auto_increment, name varchar(30), primary key(id1) );create table test02 ( id2 int not null auto_increment, name varchar(30), primary key(id2) );
CREATE DEFINER=`root`@`%` PROCEDURE `p_insert`()BEGIN#Routine body goes here...DECLARE str1 varchar(30);DECLARE str2 varchar(30);DECLARE i int;set i = 0;while i < 10000 do set str1 = substring(md5(rand()),1,25); insert into test01(name) values(str1); set str2 = substring(md5(rand()),1,25); insert into test02(name) values(str1); set i = i + 1; end while; END
use lijiamandb; create event if not exists e_insert on schedule every 10 second on completion preserve do call p_insert();
mysql> show variables like '%event_scheduler%';+----------------------------------------------------------+-------+| Variable_name | Value |+----------------------------------------------------------+-------+| event_scheduler | OFF |+----------------------------------------------------------+-------+mysql> set global event_scheduler = on; Query OK, 0 rows affected (0.08 sec)

注意:必须要添加--master-data=2,这样才会备份集里面mysqldump备份的终点位置。

--过3分钟。。。

STEP3:为了便于数据库删除前与删除后数据一致性校验,先停止表的数据插入,此时test01和test02都有930000行数据,我们后续恢复也要保证有930000行数据。

mysql> set global event_scheduler = off;Query OK, 0 rows affected (0.00 sec)mysql> select count(*) from test01; +----------+ | count(*) | +----------+ | 930000 | +----------+row in set (0.14 sec)mysql> select count(*) from test02; +----------+ | count(*) | +----------+ | 930000 | +----------+row in set (0.13 sec)
mysql> drop database lijiamandb;Query OK, 2 rows affected (0.07 sec)
mysql> create database lijiamandb;Query OK, 1 row affected (0.01 sec)mysql> exit Bye [root@masterdb binlog]# mysql -uroot -p123456 lijiamandb < /mysql/backup/lijiamandb.sql  mysql: [Warning] Using a password on the command line interface can be insecure.
[root@masterdb binlog]# mysql -uroot -p123456 lijiamandb mysql> select count(*) from test01; +----------+ | count(*) | +----------+ | 753238 | +----------+row in set (0.12 sec)mysql> select count(*) from test02; +----------+ | count(*) | +----------+ | 753238 | +----------+row in set (0.11 sec)

使用mysqlbinlog进行增量日志恢复最重要的就是确定待恢复的起始位置(start-position)和终止位置(stop-position),起始位置(start-position)是我们执行全被之后的位置,而终止位置则是故障发生之前的位置。
STEP6:确认mysqldump备份到的最终位置

[root@masterdb backup]# cat lijiamandb.sql |grep "CHANGE MASTER"-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000044', MASTER_LOG_POS=8526828

--接下来确认要恢复的终点位置,即执行"DROP DATABASE LIJIAMAN"之前的位置,需要到binlog里面确认。

[root@masterdb binlog]# ls master-bin.000001 master-bin.000010 master-bin.000019 master-bin.000028 master-bin.000037 master-bin.000046 master-bin.000055 master-bin.000002 master-bin.000011 master-bin.000020 master-bin.000029 master-bin.000038 master-bin.000047 master-bin.000056 master-bin.000003 master-bin.000012 master-bin.000021 master-bin.000030 master-bin.000039 master-bin.000048 master-bin.000057 master-bin.000004 master-bin.000013 master-bin.000022 master-bin.000031 master-bin.000040 master-bin.000049 master-bin.000058 master-bin.000005 master-bin.000014 master-bin.000023 master-bin.000032 master-bin.000041 master-bin.000050 master-bin.000059 master-bin.000006 master-bin.000015 master-bin.000024 master-bin.000033 master-bin.000042 master-bin.000051 master-bin.index master-bin.000007 master-bin.000016 master-bin.000025 master-bin.000034 master-bin.000043 master-bin.000052 master-bin.000008 master-bin.000017 master-bin.000026 master-bin.000035 master-bin.000044 master-bin.000053 master-bin.000009 master-bin.000018 master-bin.000027 master-bin.000036 master-bin.000045 master-bin.000054# 多次查找,发现drop database在54号日志文件[root@masterdb binlog]# mysqlbinlog -v master-bin.000056 | grep -i "drop database lijiamandb" [root@masterdb binlog]# mysqlbinlog -v master-bin.000055 | grep -i "drop database lijiamandb" [root@masterdb binlog]# mysqlbinlog -v master-bin.000055 | grep -i "drop database lijiamandb" [root@masterdb binlog]# mysqlbinlog -v master-bin.000054 | grep -i "drop database lijiamandb"drop database lijiamandb# 保存到文本,便于搜索[root@masterdb binlog]# mysqlbinlog -v master-bin.000054 > master-bin.txt# 确认drop database之前的位置为:54号文件的9019487 # at 9019422 #200423 16:07:46 server id 11 end_log_pos 9019487 CRC32 0x86f13148 Anonymous_GTID last_committed=30266 sequence_number=30267 rbr_only=no SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 9019487 #200423 16:07:46 server id 11 end_log_pos 9019597 CRC32 0xbd6ea5dd Query thread_id=100 exec_time=0 error_code=0 SET TIMESTAMP=1587629266/*!*/; SET @@session.sql_auto_is_null=0/*!*/; /*!\C utf8 *//*!*/; SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/; drop database lijiamandb /*!*/; # at 9019597 #200423 16:09:25 server id 11 end_log_pos 9019662 CRC32 0x8f7b11dc Anonymous_GTID last_committed=30267 sequence_number=30268 rbr_only=noSET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 9019662 #200423 16:09:25 server id 11 end_log_pos 9019774 CRC32 0x9b42423d Query thread_id=100 exec_time=0 error_code=0 SET TIMESTAMP=1587629365/*!*/; create database lijiamandb

STEP7:确定了开始结束点,执行增量恢复
开始:44号日志的8526828
结束:54号文件的9019487

这里分为3条命令执行,起始日志文件涉及到参数start-position参数,单独执行;中止文件涉及到stop-position参数,单独执行;中间的日志文件不涉及到特殊参数,全部一起执行。

# 起始日志文件

# 起始日志文件mysqlbinlog --start-position=8526828 /mysql/binlog/master-bin.000044 | mysql -uroot -p123456 # 中间日志文件mysqlbinlog /mysql/binlog/master-bin.000045 /mysql/binlog/master-bin.000046 /mysql/binlog/master-bin.000047 /mysql/binlog/master-bin.000048 /mysql/binlog/master-bin.000049 /mysql/binlog/master-bin.000050 /mysql/binlog/master-bin.000051 /mysql/binlog/master-bin.000052 /mysql/binlog/master-bin.000053 | mysql -uroot -p123456 # 终止日志文件mysqlbinlog --stop-position=9019487 /mysql/binlog/master-bin.000054 | mysql -uroot -p123456
[root@masterdb binlog]# mysql -uroot -p123456 lijiamandbmysql> select count(*) from test01;+----------+| count(*) |+----------+| 930000 |+----------+row in set (0.15 sec)mysql> select count(*) from test02;+----------+ | count(*) |+----------+ | 930000 |+----------+row in set (0.13 sec)

1.对于DML操作,binlog记录了所有的DML数据变化:
--对于insert,binlog记录了insert的行数据
--对于update,binlog记录了改变前的行数据和改变后的行数据
--对于delete,binlog记录了删除前的数据
假如用户不小心误执行了DML操作,可以使用mysqlbinlog将数据库恢复到故障点之前。

2.对于DDL操作,binlog只记录用户行为,而不记录行变化,但是并不影响我们将数据库恢复到故障点之前。

总之,使用mysqldump全备加binlog日志,可以将数据恢复到故障前的任意时刻。

更多相关文章

  1. IM-A820L限制GSM,WCDMA上网的原理(其他泛泰机型可参考)7.13
  2. Android布局优化:ViewStub标签实现延迟加载(源码解析原理)
  3. tab上显示数字
  4. android页面管理器。可以实现完整退出android软件
  5. Android之SharedPreferences详解与原理分析
  6. Android测试之Monkey原理及源码分析(二)
  7. Android(安卓)APK安装过程及原理详解
  8. 《新浪微博Android客户端开发完整视频 Touch Android版》
  9. android中wifi原理及流程分析(很经典)

随机推荐

  1. 使用没有实体类的本机SQL查询
  2. 如果作者是Post的作者那么做点什么?
  3. 数据库是存储我的Web应用程序数据的最佳
  4. How can clear screen in php cli (like
  5. PHP / MySQL - 有时会将空白条目添加到
  6. Laravel手把手系列教程之一环安装和环境
  7. php和django位于同一个lighttpd服务器上
  8. 如何加载json文件?
  9. 将node.js服务器更改为Apache服务器
  10. 纯真ip数据库查询的php实现(补充分组查询)