不小心drop掉資料庫怎麼辦

不小心drop掉資料庫怎麼半.md

不小心刪掉了mysql資料庫怎麼辦

前情提要

  • 不小心把資料庫給drop掉了、把table刪掉了。
    我的情況是把database整個drop掉、沒有開bin_log紀錄。
  • 因為資料庫版本是5.6,預設innodb_file_per_table=off,因此資料在被drop掉後,紀錄仍然會在ibdata1裡面。

當下處置和準備

1. 趕緊將資料庫服務整個關掉,要記得把所有mysql的process砍掉。

sudo service stop mysqld
  • P.S.最好再用ps aux |grep "mysql" 檢查一下

2. 把mysql資料夾內的ibdata1檔案抓出來。

3. 準備一下原本create 要恢復的 table的sql

我因為是使用django,所以能夠用migrate重現原本的table
因此,只要在使用show create table tableName; 就可以拿到create的sql了

P.S. 如果沒有辦法重現的話,twinDB的恢復工具,裡面有sys_parser工具,可以用ibdata1的資料來產生

4. clone 恢復工具

git clone git@github.com:twindb/undrop-for-innodb.git

5. 產生恢復工具(需要gcc、bison、flex、make)

在clone下來的資料夾內編工具

make

P.S. 假如需要sys_parser工具的話,需要再額外去編這個工具(需要對應的mysql dev package,可以用yum provides "*/mysql_config",來show出可以下載的dev package)

編譯指令

gcc `mysql_config --cflags` `mysql_config --libs` -o sys_parser sys_parser.c

mysql_config 是mysql的設定檔(通常就叫做mysql_config)。

開始修復

接下來的動作,都是在clone下來的工具的資料夾下操作

手動查的流程

1. 使用stream_parser把ibdata1導成page

./stream_parser -f ibdata1檔案

2. 使用c_parser來parse第1個page(可以在這分析出table id),並找到對應的database/table

EX: 要找django_database下的user table

./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql |grep "django_database/user"

會得到類似這樣的結果,其中,在table名稱後面的,就是他的table Id
000000000521 3B00000149047E SYS_TABLES "django_database/user" 152 3 33 0 64 "" 0 SET FOREIGN_KEY_CHECKS=0;

3. 使用c_parser來parse第三個page(可以在這分析出index id)

EX: 要找的table id 是 152

./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql | grep '152'

會得到類似這樣的結果,接在table id後面的,就是這個key的index id了
000000000521 3B0000014903A2 SYS_INDEXES 153 45 "PRIMARY" 1 3 0 4294967295 SET FOREIGN_KEY_CHECKS=0;
000000000521 3B0000014903A2 SYS_INDEXES 152 49 "Foreign" 1 3 0 4294967295
這邊選擇Primary key id 45

其實剛剛編好的工具裡面,可以產生相對應的查詢表

1. 把recover_dictionary.sh 裡面的435058行的mysql改成自己mysql登入的指令 例如: mysql -u root -p"密碼"

2. 執行recover_dictionary.sh

./recover_dictionary.sh

這樣就會在這台mysql裡面建立一個database 叫test

3. 就可以直接在這個database裡面下sql來查對應的index id了。

#查詢 table id
select * from SYS_TABLES where name like 'django_database/user%';
#查詢 index id
select * from SYS_INDEXES where table_id=152;

可以很輕鬆的查到對應的index id。

接著真的要開始修復了

1. 先查一下對應index_id的page名稱

ls pages-ibdata1/FIL_PAGE_INDEX/*剛剛查到的index_id*

output : 0000000000000043.page

2. 檢查看看數據是否存在

c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000000043.page -t /tmp/t2.sql |head -20

這邊t2.sql是前置準備時生出來的建表sql
如果無誤的話,應該可以看到被刪掉的資料在上面。
P.S. 這邊的6 可以看一下c_parser --help 看對應的是不是自己資料的格式,以免復原後資料怪怪的(有亂碼之類的)

3. 接下來就可以開始生成恢復的sql了

./c_parser -6f pages-ibdata1/FIL_PAGE_INDEX/0000000000000043.page -t /tmp/t2.sql > dumps/default/user 2> dumps/default/user_load.sql

極重要 : 這邊後面dumps/default/裡面的兩個檔案名稱要和要恢復的table名稱一樣。

user 、user_load.sql

4. 接下來進到要恢復的database裡面,建表還有拿回資料,就可以了。

# 建表
[mysql]> source /home/root/t2.sql  
# 導入數據
[mysql]> source /home/root/undrop-for-innodb/dumps/default/user_load.sql

5. 接下來就是查table 的primary key 的 id -->> 找到page -->> 倒出 tableName_load.sql -->> 導回資料庫 的loop了

Refference:

留言

這個網誌中的熱門文章

淺談在Golang上面的物件導向

咖啡杯、隨行杯、保溫杯的清潔除臭

Reserved Instance 介紹