前言

相信每一个学IT的人或多或少都听说过从删库到跑路这个梗~下图也是在各种交流群屡禁不止,新人听着也是瑟瑟发抖。

人们茶余饭后,街头巷角难免要问。。。

下面技术流ken就教给各位新手们一招删库再也不用跑路的绝技~

实现原理

想要学会这个技能务必先要看我的这篇有关mysql日志的博客《MySQL系列详解三:MySQL中各类日志详解-技术流ken》。

一定要先了解二进制日志文件的作用

二进制日志记录了对数据库执行更改的所有操作,但是不包括 select 和 show 这类操作,因为这类操作对数据本身并没有修改,如果你还想记录select和show操作,那只能使用查询日志了,而不是二进制日志。
 
此外,二进制还包括了执行数据库更改操作的时间和执行时间等信息。 二进制日志主要有以下几种作用 :
 

恢复(recovery) :

 
某些数据的恢复需要二进制日志,如当一个数据库全备文件恢复后,我们可以通过二进制的日志进行 point-in-time 的恢复
 

复制(replication) :

通过复制和执行二进制日志使得一台远程的 MySQL 数据库(一般是slave 或者 standby) 与一台MySQL数据库(一般为master或者primary) 进行实时同步
 

审计(audit) :

用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入攻击

数据库备份

有人会有疑惑数据库都被我删了,哪还有什么备份?

殊不知,在你删库之前你们公司的运维工程师或者DBA已经悄悄的对数据库做了备份~

而且这个备份不是在你的电脑或者mysql服务器上面,可能已经被传送到了你们主管,DBA或者某台专用的备份服务器哪里去了,这个实现起来非常简单,运维工程师通过脚本就可以自动完成这个工作,总之他们肯定会有一份数据库的备份的~

但是他们的这个备份并不是完整备份,什么意思那

可能你们公司的数据库备份策略是周末做全量备份,周一至周六是做的增量备份,而且是每天只做一次增量备份

比如你们公司做增量备份是每天的凌晨时间,而你删库的时间是在早晨10点钟,那么这10个小时的数据,就没有备份了~

如果你们公司做的比较风生水起,在这十个小时的时间内有10万条的写入记录,你是不是会心口发塞,准备跑路了~

不要慌

第一时间去找你们公司的DBA问他有没有最新的数据库备份文件

如果他说没有。。

告诉他你把库删了,让他跟着你一起慌。。

但是你是看过我这篇博客的人,淡定

第二时间去找你们公司的运维工程师

他们肯定有!

总之无论你删了什么重要文件,都去找运维工程师,他们肯定有!他们就是一群没事爱做自动化备份的人

他们会告诉你:XX文件都被同步在了XX服务器上面了

恢复数据库

在DBA手里可以拿到全量备份以及增量备份的数据库文件,在运维工程师手里可以任何实时的二进制文件。

这个时候第一时间先去二进制服务器上面再次对二进制日志文件做一个备份!

这次能不能不跑路,就看这个二进制日志文件了。

拿到这些文件之后,现在就可以对数据库进行恢复了。

删库之后一定要先把数据库服务停掉,这是重点!

有了全量备份的文件,增量备份的文件以及二进制文件之后,就去拜托你们公司的DBA或者运维工程师来进行数据的恢复即可。

模拟删除数据表

接下来就完整演示从删表到数据恢复的过程

第一步:查看是是否开启了二进制日志

显示log_bin是开启的,没有问题

mysql> show global variables like "%log%bin%";
+----------------------------------+--------------------------------------------+
| Variable_name | Value |
+----------------------------------+--------------------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/mysql3306/logs/mysql-bin |
| log_bin_index | /data/mysql/mysql3306/logs/mysql-bin.index |
| log_bin_trust_function_creators | ON |
| log_bin_use_v1_row_events | OFF |
| log_statements_unsafe_for_binlog | ON |
+----------------------------------+--------------------------------------------+
rows in set (0.00 sec)

第二步:添加一些数据

我们首先往数据库中添加一些数据

下面我创建了一个ken数据库

ken数据库中创建了一个kenken数据表

在这个表中插入了一些数据

mysql> create database ken;
Query OK, row affected (0.00 sec) mysql> use ken;
Database changed
mysql> create table kenken(id int auto_increment primary key not null,name char()not null,tel int)
-> ;
Query OK, rows affected (0.03 sec) mysql> desc kenken;
+-------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+----------------+
| id | int() | NO | PRI | NULL | auto_increment |
| name | char() | NO | | NULL | |
| tel | int() | YES | | NULL | |
+-------+----------+------+-----+---------+----------------+
rows in set (0.06 sec) mysql> insert into kenken (id,name,tel) values (,"鲁班",);
Query OK, row affected (0.01 sec) mysql> insert into kenken (id,name,tel) values (,"后裔",);
Query OK, row affected (0.00 sec) mysql> insert into kenken (id,name,tel) values (,"韩信",);
Query OK, row affected (0.00 sec) mysql> select * from kenken;
+----+--------+------+
| id | name | tel |
+----+--------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
+----+--------+------+
rows in set (0.00 sec)

第三步:模拟DBA做全量备份

这样我们就获得了一个数据库全量备份的文件

[root@ken ~]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --set-gtid-purged=OFF --master-data= >/tmp/ken.sql
Enter password:
[root@ken ~]# tail /tmp/ken.sql /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on -- ::

第四步:模拟数据写入

备份完成之后我们模拟数据写入,相当于在凌晨到早上十点钟这段时间

下面我又增加了四条记录,在备份文件中是没有的

mysql> insert into kenken (name,tel) values ("不知火舞",);
Query OK, row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("d貂蝉",);
Query OK, row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("明世隐",);
Query OK, row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("李白",);
Query OK, row affected (0.00 sec) mysql> select * from kenken;
+----+--------------+------+
| id | name | tel |
+----+--------------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
| | 不知火舞 | |
| | d貂蝉 | |
| | 明世隐 | |
| | 李白 | |
+----+--------------+------+
rows in set (0.00 sec)

第五步:模拟数据删除

现在是早晨10点钟,你把这个表删掉了

现在在备份文件中是没有这个新添加的表中的数据的

mysql> drop table kenken;
Query OK, rows affected (0.01 sec) mysql> select * from kenken;
ERROR (42S02): Table 'ken.kenken' doesn't exist

模拟恢复数据表

第一步:查看二进制文件

进入到你们公司的二进制日志保存位置

下面这些就是二进制日志文件

[root@ken ~]# cd /data/mysql/mysql3306/logs/
[root@ken logs]# ls
mysql-bin. mysql-bin. mysql-bin. mysql-bin. mysql-bin.index

第二步:查看全量备份文件

在大约22行处记录了:

自备份起,新开始的二进制日志文件保存的位置

非常重要

[root@ken logs]# vim /tmp/ken.sql
...

/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


--
-- Position to start replication or point-in-time recovery from
--


-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000014', MASTER_LOG_POS=194;


--
-- Current Database: `ken`
--


CREATE DATABASE /*!32312 IF NOT EXISTS*/ `ken` /*!40100 DEFAULT CHARACTER SET utf8 */;


USE `ken`;

...

第三步:关闭二进制日志

第一步:先停掉数据库

第二步:修改数据库配置文件,注释掉改行

第三步:重启数据库即可

#log-bin = /data/mysql/mysql3306/logs/mysql-bin

第四步:恢复删除的表

先恢复这个全量备份的文件

感觉胜利在望,起码表和之前的数据都已经恢复了

但是还是没有我们模拟新添加的记录

mysql> source /tmp/ken.sql
mysql> select * from ken.kenken;
+----+--------+------+
| id | name | tel |
+----+--------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
+----+--------+------+
rows in set (0.00 sec)

第五步:使用备份文件

打开备份文件可以看到我的新产生的二进制是保存在了mysql-bin.000012,194处开始的

CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000014', MASTER_LOG_POS=194;

第六步:找到删除表的那条命令位置可以看到在1349处就是删除表的命令
[root@ken logs]# mysqlbinlog mysql-bin.

...
wF/6Wx4qTw8AMwAAAOUEAAAAAA8BAAAAAAEAAgAD//gRAAAABuadjueZvQsAAACuazag
'/*!*/;
# at
# :: server id end_log_pos CRC32 0x969a0e09 Xid =
COMMIT/*!*/;
# at
# :: server id end_log_pos CRC32 0x6e619553 GTID last_committed= sequence_number=rbr_only=no
SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:149'/*!*/;
# at
# :: server id end_log_pos CRC32 0x48ac1825 Query thread_id= exec_time= error_code=
use `ken`/*!*/;
SET TIMESTAMP=/*!*/;
DROP TABLE `kenken` /* generated by server */
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

第六步:截取二进制日志

开始位置是你全量备份显示的位置

停止位置是你误操作的位置

[root@ken logs]# mysqlbinlog  --start-position= --stop-position= mysql-bin. >/tmp/kenken.sql
第七步:恢复全部数据
可以发现数据一个没有丢又都回来了!
恢复完数据之后千万记得开启配置文件中的二进制!!
mysql> source /tmp/kenken.sql
mysql> select * from ken.kenken;
+----+--------------+------+
| id | name | tel |
+----+--------------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
| | 不知火舞 | |
| | d貂蝉 | |
| | 明世隐 | |
| | 李白 | |
+----+--------------+------+
rows in set (0.00 sec)

模拟删除数据库

现在我们来模拟删除一个数据库

其实和上面的步骤是一样的

千万记得恢复完数据之后重新启动二进制日志

这里我还是以上面的数据库为列

第一步:模拟备份

[root@ken logs]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --set-gtid-purged=OFF --master-data= >/tmp/ken.sql

第二步:添加数据

mysql> insert into kenken (name,tel) values ("庄周",);
Query OK, row affected (0.01 sec) mysql> insert into kenken (name,tel) values ("马可波罗",);
Query OK, row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("黄忠",);
Query OK, row affected (0.00 sec) mysql> select * from kenken;
+----+--------------+------+
| id | name | tel |
+----+--------------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
| | 不知火舞 | |
| | d貂蝉 | |
| | 明世隐 | |
| | 李白 | |
| | 东皇太一 | |
| | 项羽 | |
| | 荆轲 | |
| | 孙尚香 | |
| | 庄周 | |
| | 马可波罗 | |
| | 黄忠 | |
+----+--------------+------+
rows in set (0.00 sec)

第三步:删除ken数据库

mysql> drop database ken;
Query OK, row affected (0.01 sec) mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
rows in set (0.00 sec)

模拟恢复数据库

第一步:关闭数据库,关闭二进制日志,并重新启动

[root@ken logs]# ps aux | grep mysql
mysql 0.2 37.3 pts/ Sl : : mysqld
root 0.0 0.1 pts/ R+ : : grep --color=auto mysql
[root@ken logs]# kill -
[root@ken logs]# vim /etc/my.cnf
[]+ Killed mysqld
[root@ken logs]# mysqld &

第二步:恢复全量备份数据

可以发现现在已经恢复了数据库以及一部分的数据

但是我们最后添加的数据还是没有

mysql> source /tmp/ken.sql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ken |
| mysql |
| performance_schema |
| sys |
+--------------------+
rows in set (0.00 sec) mysql> use ken;
Database changed
mysql> select * from kenken;
+----+--------------+------+
| id | name | tel |
+----+--------------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
| | 不知火舞 | |
| | d貂蝉 | |
| | 明世隐 | |
| | 李白 | |
| | 东皇太一 | |
| | 项羽 | |
| | 荆轲 | |
| | 孙尚香 | |
+----+--------------+------+
rows in set (0.00 sec)

第三步:截取二进制日志

首先查看备份文件中开始的位置

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

再查看误操作的位置

...
# at
# :: server id end_log_pos CRC32 0x66b9786f GTID last_committed= sequence_number=rbr_only=no
SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:157'/*!*/;
# at
# :: server id end_log_pos CRC32 0x6f04e5b3 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
drop database ken
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

开始截图日志

[root@ken logs]# mysqlbinlog  --start-position= --stop-position= mysql-bin. >/tmp/kenken.sql

第四步:恢复所有的数据

发现现在所有的数据都回来了

mysql> source /tmp/kenken.sql
mysql> use ken;
Database changed
mysql> select * from kenken;
+----+--------------+------+
| id | name | tel |
+----+--------------+------+
| | 鲁班 | |
| | 后裔 | |
| | 韩信 | |
| | 不知火舞 | |
| | d貂蝉 | |
| | 明世隐 | |
| | 李白 | |
| | 东皇太一 | |
| | 项羽 | |
| | 荆轲 | |
| | 孙尚香 | |
| | 庄周 | |
| | 马可波罗 | |
| | 黄忠 | |
+----+--------------+------+
rows in set (0.00 sec)

看完这篇博客,删掉数据库你还会怕吗?

学会这个删库再也不用跑路了~ --技术流ken的更多相关文章

  1. MySQL数据库无完整备份删库,除了跑路还能怎么办?

    1.背景 前段时间,由于运维同事的一次误操作,清空了内网核心数据库,导致了公司内部管理系统长时间不可用,大量知识库内容由于没有备份险些丢失. 结合这两天微盟的删库跑路事件,我们可以看到,数据库的备份与 ...

  2. 五分钟彻底学会iptables防火墙--技术流ken

    iptables简介 IPTABLES 是与最新的 3.5 版本 Linux内核集成的 IP 信息包过滤系统.如果 Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理服务器, ...

  3. Mysql如何在删库后可以不用跑路

    我一直在想,地球上这么多程序员,应该有很多人在团队做项目的时候,出过很大的错误,比如说不小心删了库,活动福利字段多写了个零导致全服务器玩家领到数倍奖励,听了沙雕群友的话执行rm -rf命令. 记得有一 ...

  4. 学会这些CSS,再也不用切图!!!

    三角形 利用border-color支持transparent这一特性,隐藏三条边框,实现三角形. <style> .triangle { width: 0; height: 0; bor ...

  5. Yum搭建LNMP环境(动、静、库分离)(week4_day5)--技术流ken

    前言 本篇博客使用yum来搭建lnmp环境,将采用动态,静态以及数据库分开安装的方式即nginx,php,mysql.会被分开安装在不同的服务器之上,搭建出来一套lnmp环境,并部署wordpress ...

  6. 理解Linux文档的默认安全机制、隐藏属性、特殊权限,妈妈在也不用担心你从删库到跑路!!!

    写在前面 前面的章节 详解Linux文档属性.拥有者.群组.权限.差异,介绍了文档的基本权限,包括读写执行(r,w,x),还有文档若干的属性,包括是否为目录(d).文件(-).链接文件(l).拥有者. ...

  7. Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~

    导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...

  8. Oracle删库跑路

    --10g R2 startup mount exclusive restrict; alter system enable restricted session; drop database; -- ...

  9. P5270 无论怎样神树大人都会删库跑路

    题目地址:P5270 无论怎样神树大人都会删库跑路 第一眼看上去是模拟,似乎是 \(O(n)\) 的 水题 信心满满的写完: #include <bits/stdc++.h> using ...

随机推荐

  1. Day06 (黑客成长日记) 初识函数和返回值的作用

    定义函数: 1.初识函数: 我们在学习字符串时,有这样的操作: li = 'tsy be ba bvake ' print(len(li)) 这样可以打印出li的长度,我们利用了python中的len ...

  2. 洛谷P1596 [USACO10OCT]湖计数Lake Counting

    https://www.luogu.org/problemnew/show/P1596 连通块水题... 大体思路是找到是水坑的坐标然后就开始不断递归,往八个方向搜,把连在一起的都标记一遍直到找不到为 ...

  3. webservice的两种方式SOAP和REST的通俗理解

    Webservice代表所有基于web的服务,包含两种方式SOAP和REST 以SOAP为例: 一个RPC call 就是把一个XML文档post到某个URL下,这个xml文档里写明我要调用的函数名和 ...

  4. gitlab 之 cicd

    1.使用 docker 安装 gitlab docker run -d  --hostname gitlab \        --env GITLAB_OMNIBUS_CONFIG="ex ...

  5. oracle之 any、some、all 解析

    举几个例子来说明ALL和ANY的用法 1. SELECT * FROM TABLEA WHERE FLD > ALL(SELECT FLD FROM TABLEA) 这相当于 SELECT * ...

  6. git 创建项目

    Command line instructions Git global setup git config --global user.name "quliangliang" gi ...

  7. 《Pyhton语言程序设计》_第7章_对象和类

    #7.2.1_定义类 一个类的功能:数据域.定义方法.初始化程序 初始化程序总是被命名为:_ _init_ _ (两个连续的下划线) #7.2.4_self参数 #self参数是指向对象本身的参数,那 ...

  8. 无法从项目中获取SSIS包的列表

    一直做的SSIS项目,突然在生成项目的时候没有反应,crtl + alt +o 提示:无法从项目中获取SSIS包的列表,发现是最近的包没有设计数据源, 解决思路:检查最近的包,挨个运行一遍,看看有没有 ...

  9. Python-OpenCV 图像叠加加权实现

    函数说明 cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst 1 参数说明 src1 – first input ...

  10. 毕业不到一年,绩效打了个D!

    周末了,和大家来聊聊程序员工作态度的问题. 说说栈长的事迹吧,这是好多年前的事了,那时候,栈长才毕业不到一年,那次绩效打了个D!事后,我很气愤啊,我那时还在博客上写文章怒骂了部门经理,现在想起来,真是 ...