InnoDB引擎Myslq數據庫數據恢復


首先祝願看到這片文章的你永遠不要有機會用到它...

本文指針對用InnoDB引擎的Mysql數據庫的數據恢復,如果是其它引擎的Mysql或其它數據庫請自行google...

如果有一天你手挫不小心刪掉了正式數據庫中的數據,甚至把整個庫給drop掉了,瞬間感覺眼前一黑有木有,感覺就像世界末日到了有木有,如果你有數據庫備份還好,回復備份中的數據即可,或者你開了Mysql的二進制日志記錄好像也可以從里面恢復,可是如果木有備份又木有開二進制日志記錄是不是感覺苦逼了無從下手,下面的內容就針對這種情況給出一些解決方法...

1.首先你要盡快停掉mysql服務,把mysql數據庫data文件夾下的內容全部拷出來,防止之后的操作覆蓋刪掉的數據。

 

2.准備一個Linux系統我用的是Ubuntu 12.04。

 

3.准備數據庫恢復工具percona-data-recovery-tool-for-innodb,關於percona-data-recovery-tool-for-innodb:

  3.1.這個工具只能對InnoDB/XtraDB表有效,而無法恢復MyISAM表。

  3.2.這個工具是以保存的MySQL數據文件進行恢復的,而不用MySQL Server運行。

  3.3.不能保證數據總一定可被恢復。例如,被重寫的數據不能被恢復。

  3.4.使用這個工具需要手動做一些工作,並不是全自動完成的。

  3.5.恢復過程依賴於你對丟失數據的了解程度,在恢復過程中可能需要在不同版本的數據之間做出選擇。那么如果你越了解自己的數據,恢復的可能性就越大。

 

4.下載percona-data-recovery-tool-for-innodb並解壓,打開終端,輸入以下命令: 

wget https://launchpad.net/percona-data-recovery-tool-for-innodb/trunk/release-0.5/+download/percona-data-recovery-tool-for-innodb-0.5.tar.gz
tar -zxvf percona-data-recovery-tool-for-innodb-0.5.tar.gz

  4.1.轉到解壓后的目錄的mysql-source子目錄,運行配置命令:

cd percona-data-recovery-tool-for-innodb-0.5/mysql-source
./configure

  4.2.完成配置步驟后,回到解壓后的根目錄,運行make命令,編譯生成page_parserconstraints_parser工具(如果編譯過程中出現問題,諸如包依賴之類的,請根據錯誤提示自行補全)

cd ..
make

 

5.提取數據

  InnoDB頁的默認大小是16K,每個頁屬於一個特定表中的一個特定的index。page_parser工具通過讀取數據文件,根據頁頭中的index ID,拷貝每個頁到一個單獨的文件中。

  如果你的MySQL server被配置為innodb_file_per_table=1,那么系統已經幫你實現上述過程。所有需要的頁都在.ibd文件,而且通常你不需要再切分它。然而,如果.ibd文件中可能包含多個index,那么將頁單獨切分開還是有必要的。如果MySQL server沒有配置innodb_file_per_table,那么數據會被保存在一個全局的表命名空間(通常是一個名為ibdata1的文件,本文屬於這種情況),這時候就需要按頁對文件進行切分。

  5.1.切分頁--在解壓后的根目錄下新建dbfile文件夾並把你拷的data目錄下的ibdata1文件復制到該文件夾。

    5.1.1.如果MySQL是5.0之前的版本,InnoDB采取的是REDUNDANT格式,在終端運行以下命令:

./page_parser -4 -f ./dbfile/ibdata1

    5.1.2.如果MySQL是5.0及以上版本,InnoDB采取的是COMPACT格式,在終端運行以下命令:

./page_parser -5 -f ./dbfile/ibdata1

  5.2.運行后,page_parser工具會創建一個pages-<TIMESTAMP>的目錄,其中TIMESTAMP是UNIX系統時間戳。在這個目錄下,為每個index ID,以頁的index ID創建一個子目錄。如圖:

  5.3.選擇需要的Index ID

    5.3.1.如果你只是刪除了表中的數據而沒有刪除表,那么可以啟動InnoDB Tablespace Monitor,輸出所有表和indexes,index IDs到MySQL server的錯誤日志文件。創建innodb_table_monitor表用於收集innodb存儲引擎表及其索引的存儲方式:

mysql> CREATE TABLE innodb_table_monitor (id int) ENGINE=InnoDB;

如果innodb_table_monitor已經存在,drop表然后重新create表。等MySQL錯誤日志輸出后,可以drop掉這張表以停止打印輸出更多的監控。一個輸出的例子如下:

TABLE: name sakila/customer, id 0 142, columns 13, indexes 4, appr.rows 0
  COLUMNS: customer_id: DATA_INT len 2 prec 0; store_id: DATA_INT len 1 prec 0; first_name: type 12 len 135 prec 0; last_name: type 12 len 135 prec 0; email:
 type 12 len 150 prec 0; address_id: DATA_INT len 2 prec 0; active: DATA_INT len 1 prec 0; create_date: DATA_INT len 8 prec 0; last_update: DATA_INT len 4 pr
ec 0; DB_ROW_ID: DATA_SYS prtype 256 len 6 prec 0; DB_TRX_ID: DATA_SYS prtype 257 len 6 prec 0; DB_ROLL_PTR: DATA_SYS prtype 258 len 7 prec 0; 
  INDEX: name PRIMARY, id 0 286, fields 1/11, type 3
   root page 50, appr.key vals 0, leaf pages 1, size pages 1
   FIELDS:  customer_id DB_TRX_ID DB_ROLL_PTR store_id first_name last_name email address_id active create_date last_update
  INDEX: name idx_fk_store_id, id 0 287, fields 1/2, type 0
   root page 56, appr.key vals 0, leaf pages 1, size pages 1
   FIELDS:  store_id customer_id
  INDEX: name idx_fk_address_id, id 0 288, fields 1/2, type 0
   root page 63, appr.key vals 0, leaf pages 1, size pages 1
   FIELDS:  address_id customer_id
  INDEX: name idx_last_name, id 0 289, fields 1/2, type 0
   root page 1493, appr.key vals 0, leaf pages 1, size pages 1
   FIELDS:  last_name customer_id

這里,我們恢復的是sakila庫下的customer表,從上面可以獲取其主鍵信息:

INDEX: name PRIMARY, id 0 286, fields 1/11, type 3

    5.3.2如果你把整個數據庫都drop掉了,那是沒辦法按照上面的方法找到需要的Index ID的,那么你可以用一下的方法來獲取需要的Index ID:

      A:如果你能確定需要的表中有一些字段會有特殊值只在這個表中有記錄,那么可以用以下命令搜索全部切分后的頁:

grep -r "CP201310090001" pages-1384167811

        搜索后的結果如圖(可以看到0-968就是需要的Index ID):

      B:如果找不出特殊值,官方教程好像說可以通過表字段名稱搜索全部切分后的頁,可是由於上面說的很籠統,我測試半天沒有成功,有需要可以參考鏈接:http://www.percona.com/docs/wiki/innodb-data-recovery-tool:mysql-data-recovery:advanced_techniques#finding_index_ids

      C:最后方法,暴力破解,由於我要恢復的表除A方法里面的之外其它的沒有特殊值,B方法也沒研究出來,只能通過腳本循環所有文件來比對了,首先需要執行5.4,5.5步驟,生成好要查找的表定義並編譯constraints_parser工具,然后在解壓根目錄新建一個shell腳本,我命名的是test.sh,腳本內容:

#!/bin/bash
function ergodic(){
for file in ` ls $1`
do
                if [ -d $1"/"$file ]
                then
                      ergodic $1"/"$file
                else
                      echo $1"/"$file #輸出文件的完整的路徑
              ./constraints_parser -5 -f $1"/"$file #提取數據
              echo $1"/"$file #輸出文件的完整的路徑
              sleep  1 #暫停一秒
               fi

done
}
INIT_PATH="pages-1384167811/FIL_PAGE_INDEX" #這里是分頁后頁面文件所在的文件夾
ergodic $INIT_PATH 

        然后在終端輸入./test.sh執行腳本,盯着終端直到終端輸出有數據,且不是亂碼的時候,那么當前提取的文件所在的文件夾名就是你要找的Index ID,然后執行5.6,5.7的過程即可,截圖如下:

  5.4.生成表定義,這需要你知道要恢復表的結構,最簡單的方法在測試服務器上新建一個與要恢復數據庫一樣的數據庫,然后在終端輸入(如果不知道表結構,也有可能通過表定義文件.frm回復,詳細請參考:http://www.percona.com/docs/wiki/innodb-data-recovery-tool:mysql-data-recovery:advanced_techniques#getting_create_table_from_frm_files):

./create_defs.pl --host=服務器地址 --user=用戶名 --password=密碼 --db=數據庫名 --table=表名 > include/table_defs.h

然后轉到解壓根目錄下的include子目錄打開table_defs.h文件,檢查一下生成的是否正確,防止你在上面的數據庫或表名寫錯而生成定義為空的文件,如圖:

5.5.編譯constraints_parser工具(每次生成表定義后都要重新編譯):

make
gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -g -I include -I mysql-source/include -I mysql-source/innobase/include -c tables_dict.c -o lib/tables_dict.o
gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -g -I include -I mysql-source/include -I mysql-source/innobase/include -o constraints_parser constraints_parser.c lib/tables_dict.o lib/print_data.o lib/check_data.o lib/libut.a lib/libmystrings.a
gcc -DHAVE_OFFSET64_T -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -g -I include -I mysql-source/include -I mysql-source/innobase/include -o page_parser page_parser.c lib/tables_dict.o lib/libut.a

5.6.合並頁,切分頁后生成的Index號碼的文件夾下面會有好多文件,提取記錄前需要先把這些文件合並成一個文件:

find pages-1384167811/FIL_PAGE_INDEX/0-968/ -type f -name '*.page' | sort -n | xargs cat > pages-1384167811/FIL_PAGE_INDEX/0-968/customer_pages_concatenated

合並后如圖:

5.7.提取合並后的數據:

./constraints_parser -5 -f pages-1384167811/FIL_PAGE_INDEX/0-968/customer_pages_concatenated > pages-1384167811/FIL_PAGE_INDEX/0-968/customer_data.tsv

提取后的文件如圖:

文件中的內容就是表中的記錄,你可以直接把tsv文件中的內容導入到數據庫,也可以打開tsv文件把內容復制到excel表格中,用你習慣的方式導入。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM