前言
相信每一個學IT的人或多或少都聽說過從刪庫到跑路這個梗~下圖也是在各種交流群屢禁不止,新人聽着也是瑟瑟發抖。
人們茶余飯后,街頭巷角難免要問。。。
下面技術流ken就教給各位新手們一招刪庫再也不用跑路的絕技~
實現原理
想要學會這個技能務必先要看我的這篇有關mysql日志的博客《MySQL系列詳解三:MySQL中各類日志詳解-技術流ken》。
一定要先了解二進制日志文件的作用
恢復(recovery) :
復制(replication) :
審計(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 | +----------------------------------+--------------------------------------------+ 6 rows in set (0.00 sec)
第二步:添加一些數據
我們首先往數據庫中添加一些數據
下面我創建了一個ken數據庫
ken數據庫中創建了一個kenken數據表
在這個表中插入了一些數據
mysql> create database ken; Query OK, 1 row affected (0.00 sec) mysql> use ken; Database changed mysql> create table kenken(id int auto_increment primary key not null,name char(30)not null,tel int) -> ; Query OK, 0 rows affected (0.03 sec) mysql> desc kenken; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | char(30) | NO | | NULL | | | tel | int(11) | YES | | NULL | | +-------+----------+------+-----+---------+----------------+ 3 rows in set (0.06 sec) mysql> insert into kenken (id,name,tel) values (10,"魯班",123); Query OK, 1 row affected (0.01 sec) mysql> insert into kenken (id,name,tel) values (12,"后裔",1233); Query OK, 1 row affected (0.00 sec) mysql> insert into kenken (id,name,tel) values (13,"韓信",1234); Query OK, 1 row affected (0.00 sec) mysql> select * from kenken; +----+--------+------+ | id | name | tel | +----+--------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | +----+--------+------+ 3 rows in set (0.00 sec)
第三步:模擬DBA做全量備份
這樣我們就獲得了一個數據庫全量備份的文件
[root@ken ~]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --set-gtid-purged=OFF --master-data=2 >/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 2018-11-25 15:57:20
第四步:模擬數據寫入
備份完成之后我們模擬數據寫入,相當於在凌晨到早上十點鍾這段時間
下面我又增加了四條記錄,在備份文件中是沒有的
mysql> insert into kenken (name,tel) values ("不知火舞",11); Query OK, 1 row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("d貂蟬",11); Query OK, 1 row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("明世隱",11); Query OK, 1 row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("李白",11); Query OK, 1 row affected (0.00 sec) mysql> select * from kenken; +----+--------------+------+ | id | name | tel | +----+--------------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | | 14 | 不知火舞 | 11 | | 15 | d貂蟬 | 11 | | 16 | 明世隱 | 11 | | 17 | 李白 | 11 | +----+--------------+------+ 7 rows in set (0.00 sec)
第五步:模擬數據刪除
現在是早晨10點鍾,你把這個表刪掉了
現在在備份文件中是沒有這個新添加的表中的數據的
mysql> drop table kenken; Query OK, 0 rows affected (0.01 sec) mysql> select * from kenken; ERROR 1146 (42S02): Table 'ken.kenken' doesn't exist
模擬恢復數據表
第一步:查看二進制文件
進入到你們公司的二進制日志保存位置
下面這些就是二進制日志文件
[root@ken ~]# cd /data/mysql/mysql3306/logs/ [root@ken logs]# ls mysql-bin.000009 mysql-bin.000010 mysql-bin.000011 mysql-bin.000012 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 | +----+--------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | +----+--------+------+ 3 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.000014 ... wF/6Wx4qTw8AMwAAAOUEAAAAAA8BAAAAAAEAAgAD//gRAAAABuadjueZvQsAAACuazag '/*!*/; # at 1253 #181125 16:39:28 server id 1003306 end_log_pos 1284 CRC32 0x969a0e09 Xid = 2524 COMMIT/*!*/; # at 1284 #181125 16:39:43 server id 1003306 end_log_pos 1349 CRC32 0x6e619553 GTID last_committed=4 sequence_number=rbr_only=no SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:149'/*!*/; # at 1349 #181125 16:39:43 server id 1003306 end_log_pos 1466 CRC32 0x48ac1825 Query thread_id=18 exec_time=0 error_code=0 use `ken`/*!*/; SET TIMESTAMP=1543135183/*!*/; 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=194 --stop-position=1349 mysql-bin.000014 >/tmp/kenken.sql
第七步:恢復全部數據
可以發現數據一個沒有丟又都回來了!
恢復完數據之后千萬記得開啟配置文件中的二進制!!
mysql> source /tmp/kenken.sql mysql> select * from ken.kenken; +----+--------------+------+ | id | name | tel | +----+--------------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | | 14 | 不知火舞 | 11 | | 15 | d貂蟬 | 11 | | 16 | 明世隱 | 11 | | 17 | 李白 | 11 | +----+--------------+------+ 7 rows in set (0.00 sec)
模擬刪除數據庫
現在我們來模擬刪除一個數據庫
其實和上面的步驟是一樣的
千萬記得恢復完數據之后重新啟動二進制日志
這里我還是以上面的數據庫為列
第一步:模擬備份
[root@ken logs]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --set-gtid-purged=OFF --master-data=2 >/tmp/ken.sql
第二步:添加數據
mysql> insert into kenken (name,tel) values ("庄周",121); Query OK, 1 row affected (0.01 sec) mysql> insert into kenken (name,tel) values ("馬可波羅",121); Query OK, 1 row affected (0.00 sec) mysql> insert into kenken (name,tel) values ("黃忠",121); Query OK, 1 row affected (0.00 sec) mysql> select * from kenken; +----+--------------+------+ | id | name | tel | +----+--------------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | | 14 | 不知火舞 | 11 | | 15 | d貂蟬 | 11 | | 16 | 明世隱 | 11 | | 17 | 李白 | 11 | | 18 | 東皇太一 | 121 | | 19 | 項羽 | 121 | | 20 | 荊軻 | 121 | | 21 | 孫尚香 | 121 | | 22 | 庄周 | 121 | | 23 | 馬可波羅 | 121 | | 24 | 黃忠 | 121 | +----+--------------+------+ 14 rows in set (0.00 sec)
第三步:刪除ken數據庫
mysql> drop database ken; Query OK, 1 row affected (0.01 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec)
模擬恢復數據庫
第一步:關閉數據庫,關閉二進制日志,並重新啟動
[root@ken logs]# ps aux | grep mysql mysql 2515 0.2 37.3 1088560 186484 pts/3 Sl 17:01 0:01 mysqld root 2552 0.0 0.1 112704 968 pts/3 R+ 17:11 0:00 grep --color=auto mysql [root@ken logs]# kill -9 2515 [root@ken logs]# vim /etc/my.cnf [1]+ Killed mysqld [root@ken logs]# mysqld &
第二步:恢復全量備份數據
可以發現現在已經恢復了數據庫以及一部分的數據
但是我們最后添加的數據還是沒有
mysql> source /tmp/ken.sql mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | ken | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use ken; Database changed mysql> select * from kenken; +----+--------------+------+ | id | name | tel | +----+--------------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | | 14 | 不知火舞 | 11 | | 15 | d貂蟬 | 11 | | 16 | 明世隱 | 11 | | 17 | 李白 | 11 | | 18 | 東皇太一 | 121 | | 19 | 項羽 | 121 | | 20 | 荊軻 | 121 | | 21 | 孫尚香 | 121 | +----+--------------+------+ 11 rows in set (0.00 sec)
第三步:截取二進制日志
首先查看備份文件中開始的位置
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=194;
再查看誤操作的位置
... # at 1010 #181125 17:09:31 server id 1003306 end_log_pos 1075 CRC32 0x66b9786f GTID last_committed=3 sequence_number=rbr_only=no SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:157'/*!*/; # at 1075 #181125 17:09:31 server id 1003306 end_log_pos 1164 CRC32 0x6f04e5b3 Query thread_id=4 exec_time=0 error_code=0 SET TIMESTAMP=1543136971/*!*/; 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=194 --stop-position=1075 mysql-bin.000016 >/tmp/kenken.sql
第四步:恢復所有的數據
發現現在所有的數據都回來了
mysql> source /tmp/kenken.sql mysql> use ken; Database changed mysql> select * from kenken; +----+--------------+------+ | id | name | tel | +----+--------------+------+ | 10 | 魯班 | 123 | | 12 | 后裔 | 1233 | | 13 | 韓信 | 1234 | | 14 | 不知火舞 | 11 | | 15 | d貂蟬 | 11 | | 16 | 明世隱 | 11 | | 17 | 李白 | 11 | | 18 | 東皇太一 | 121 | | 19 | 項羽 | 121 | | 20 | 荊軻 | 121 | | 21 | 孫尚香 | 121 | | 22 | 庄周 | 121 | | 23 | 馬可波羅 | 121 | | 24 | 黃忠 | 121 | +----+--------------+------+ 14 rows in set (0.00 sec)
看完這篇博客,刪掉數據庫你還會怕嗎?