學會這個刪庫再也不用跑路了~ --技術流ken
前言
相信每一個學IT的人或多或少都聽說過從刪庫到跑路這個梗~下圖也是在各種交流群屢禁不止,新人聽著也是瑟瑟發抖。
人們茶餘飯後,街頭巷角難免要問。。。
下面技術流ken就教給各位新手們一招刪庫再也不用跑路的絕技~
實現原理
想要學會這個技能務必先要看我的這篇有關mysql日誌的部落格《 ofollow,noindex" target="_blank">SQL/">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| +----------------------------------+--------------------------------------------+ 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@localhost ~]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --set-gtid-purged=OFF --master-data=2 >/tmp/ken.sql Enter password: [root@localhost ~]# 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@localhost ~]# cd /data/mysql/mysql3306/logs/ [root@localhost logs]# ls mysql-bin.000009mysql-bin.000010mysql-bin.000011mysql-bin.000012mysql-bin.index
第二步:檢視全量備份檔案
在大約22行處記錄了:
自備份起,新開始的二進位制日誌檔案儲存的位置
非常重要
[root@localhost 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@localhost logs]# mysqlbinlog mysql-bin.000014 ... wF/6Wx4qTw8AMwAAAOUEAAAAAA8BAAAAAAEAAgAD//gRAAAABuadjueZvQsAAACuazag '/*!*/; # at 1253 #181125 16:39:28 server id 1003306end_log_pos 1284 CRC32 0x969a0e09Xid = 2524 COMMIT/*!*/; # at 1284 #181125 16:39:43 server id 1003306end_log_pos 1349 CRC32 0x6e619553GTIDlast_committed=4sequence_number=rbr_only=no SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:149'/*!*/; # at 1349 #181125 16:39:43 server id 1003306end_log_pos 1466 CRC32 0x48ac1825Querythread_id=18exec_time=0error_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@localhost 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@localhost 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@localhost logs]# ps aux | grep mysql mysql25150.2 37.3 1088560 186484 pts/3Sl17:010:01 mysqld root25520.00.1 112704968 pts/3R+17:110:00 grep --color=auto mysql [root@localhost logs]# kill -9 2515 [root@localhost logs]# vim /etc/my.cnf [1]+Killedmysqld [root@localhost 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 1003306end_log_pos 1075 CRC32 0x66b9786fGTIDlast_committed=3sequence_number=rbr_only=no SET @@SESSION.GTID_NEXT= '08e1a6ce-da57-11e8-a0af-000c292d5bb8:157'/*!*/; # at 1075 #181125 17:09:31 server id 1003306end_log_pos 1164 CRC32 0x6f04e5b3Querythread_id=4exec_time=0error_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@localhost 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)
看完這篇部落格,刪掉資料庫你還會怕嗎?