歡迎光臨
每天分享高質量文章

記一次 MySQL 刪庫的資料恢復

(點擊上方公眾號,可快速關註)


來源:賴勇浩,

blog.csdn.net/gzlaiyonghao/article/details/53340475

昨天因為不可描述的原因,資料庫直接被 drop database刪除。在第一時間停止資料庫服務和Web服務,備份MySQL資料目錄下的所有檔案之後,開始走上資料恢復之路。

第一次乾這種事,各種不得法。因為我們既沒有備份,也沒有開啟binlog,連innodb_file_per_tabe_也沒有。一番折騰後向萬能的朋友圈求救,朋友給了兩個鏈接,最終救了一下命。以下先按編號記下 URL,後續取用之。

  1. http://dba.stackexchange.com/questions/23251/is-there-a-way-to-recover-a-dropped-mysql-database

  2. https://github.com/chhabhaiya/undrop-for-innodb

  3. Recovering The InnoDB Dictionary

其中URL1和URL3的內容基本上相同,是整個恢復工作的藍本。URL2是URL1中取用的一個twindb團隊開發的一個工具,現在他們官方已經刪除了,URL2是該工具的一個fork,或者說是備份。

恢復過程以URL3為藍本,先去URL2 git clone一份代碼下來,然後按其說明編譯,我們在ubuntu server 14.04 64bit 版本的情況下,成功編譯完成,編譯中需要安裝各種依賴不表。

然後用 stream_parser 處理ibdata1 檔案,接下來恢復SYS_TABLES 和 SYS_INDEXES,建議此過程中嚴格遵守參考資料,比如把這些資料恢復到dumps/default 目錄中,而不是隨意起名,以免橫生枝節。

這裡還有一個坑,就是URL3里用的c_parser -4f 是會出錯的,而URL1里用的是c_parser -4Df ,就不會出錯,所以大家做的時候一定要把這個D加上。感嘆一下,如果不細心的人真的沒法做這事!摔!

接下來按URL3的說明把資料字典匯入 MySQL。這一步可以不做,按URL1里高票答案的方法來獲取索引ID,比較麻煩。URL3的方法應該會出這樣的錯:

ERROR 1148 (42000) at line 2: The used command is not allowed with this MySQL version

這是因為MySQL預設不啟用LOAD DATA LOCAL INFILE 導致的,需要給mysql 命令加上–local-infile 引數。這是參考文獻的一個坑。趟過這個坑以後,我可以告訴你一個捷徑,就是URL2里的代碼里其實有一個檔案recover_dictionary.sh ,它乾的就是恢復資料字典的事情,所以你只要把這個shell腳本里的mysql 都替換成mysql –local-infile -uroot -pxxxxx 就行,其中xxxx是指你的root賬號密碼,不過前提是你很聽話的用了前面說的dumps/default 目錄,不然就再多一輪替換。

接下來的內容,大部分是參考文獻里沒有的了。

恢復資料字典後,就可以用URL3介紹的方式找出你對應的所有資料庫和表的索引ID了。這個時候就遇到為 c_parser 提供資料表建表陳述句的問題了,這個問題難就難在先有雞還是先有蛋,一般來說,資料庫都被刪掉了,哪還有辦法去搞出CREATE TABLE 這種建表陳述句呢?好就好在我們用的是django,它對資料遷移的完美支持救了我一命。在這裡講一句題外話,使用類似django/ror/laravel等有資料遷移框架在此就看出多麼重要了。只要在根據原有專案做一次migrate,資料表就建好了,這時候只要用mysqldump匯出對應表的建表陳述句即可:

mysqldump –add-drop-table=0 –add-lock=0 -d DBNAME TABLENAME -uroot -p > xxxx.sql

因為c_parser 非常弱,只處理CREATE TABLE 陳述句,多一點干擾都不行,所以上面的引數都是必要的。

接下來就是參考URL1把某一個表的資料恢復出來,這裡有一個坑,URL1里說把資料恢復到dump.tsv里,其實是不對的,這裡應該用dumps/default/TABLENAME,別問我為什麼知道,我不會告訴你我找這個原因找瞎了眼,好吧,跟你說,因為生成的load_cmd.sql 里直接取用 dumps/default/TABLENAME,無法設置。所以最後我們這裡可用的命令是:

./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000002410.page -t xxxx.sql > dumps/default/TABLENAME 2> load_cmd.sql

把資料恢復出來以後,執行

mysql –local-infile -uroot -p DBNAME < load_cmd.sql

就可以把資料導進去了,記得在資料庫里查詢一下有沒有成功,如果沒有資料恢復出來,應該是其中的某些環節出了問題。

這樣就成功恢復了某一個表,只要按這裡最後三條命令(匯出建表陳述句、恢復資料、匯入資料)重覆地做下去,你就能把基本上所有的資料都恢復出來了。之所以說是“基本上”,原因是我系統中使用了utf8mb4 編碼(為了兼容emoji),結果是如果資料中有emoji的內容就會在匯入資料的環節出錯,暫時沒有找到辦法恢復這個資料。

以上就是整個恢復過程,枯燥、壓力山大,這種事情我不想再經歷了。如果你也遇到這樣的資料恢復需求,希望這篇筆記能夠幫到你。但也不要指望我能幫到你更多了,我的經驗也僅止於此,天大地大,就此別過,不要找我。謝謝!

看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,提升Java技能

赞(0)

分享創造快樂