mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据
適用于:
MySQL服務(wù)器版本4.1到5.6 [發(fā)行版4.1到5.6]
本文信息適用于所有平臺(tái)。
目標(biāo)
如何使用undrop for innodb從損壞的表中提取數(shù)據(jù)
解決方案
使用工具有時(shí)可能從無(wú)法用innodb_force_recovery讀取的表中恢復(fù)數(shù)據(jù)。
undrop可以直接讀取數(shù)據(jù)庫(kù)的ibdata1文件,來(lái)獲取數(shù)據(jù)字典信息和必要的恢復(fù)信息。
通常,該工具從整個(gè)(多個(gè))ibdata文件且/或獨(dú)立的InnoDB tablespace文件 (innodb_file_per_table在使用中的.ibd文件)提取索引頁(yè)。Blob頁(yè)被提取到可應(yīng)用的另外的子目錄
一旦數(shù)據(jù)被提取到索引頁(yè),下一步就是從數(shù)據(jù)目錄恢復(fù)主鍵或一般聚類索引ID,然后將數(shù)據(jù)提取到適于使用LOAD DATA INFILE的文件。
如果可以的話,以要恢復(fù)的(多個(gè))數(shù)據(jù)庫(kù)的至少一個(gè)schema dump啟動(dòng),需要時(shí)使用innodb_force_recovery。即使一個(gè)過(guò)時(shí)的備份也好過(guò)什么都沒(méi)有。雖然UnDROP有時(shí)能從ibdata文件中提取一個(gè)有效表定義,它不擅于處理所有列類型。如果你完全沒(méi)有備份,.frm文件能被用于重建表定義。如果你沒(méi)有任何備份或.frm文件,那么最后一招就是UnDROP 能從idbata提取的表定義能嘗試至少恢復(fù)一些數(shù)據(jù)。
首先stream_parser是用于從ibdata提取頁(yè)的工具。它的使用很簡(jiǎn)單:
./stream_parser -f
頁(yè)會(huì)被默認(rèn)提取到”pages-”。索引頁(yè)被儲(chǔ)存在子目錄FIL_PAGE_INDEX,且blob頁(yè)被儲(chǔ)存在子目錄FIL_PAGE_TYPE_BLOB。
要提取表的所有數(shù)據(jù),有必要識(shí)別表的主鍵的數(shù)據(jù)目錄索引ID (在沒(méi)有主鍵時(shí)的一般索引)。這能通過(guò)使用UnDROP工具的”recover_dictionary.sh”腳本,將從被提取的索引頁(yè)提取的字典數(shù)據(jù)放到在運(yùn)行服務(wù)器的’test’ schema,像這樣:
$ ./recover_dictionary.sh
Generating dictionary tables dumps... OK
Creating test database ... OK
Creating dictionary tables in database test:
SYS_TABLES ... OK
SYS_COLUMNS ... OK
SYS_INDEXES ... OK
SYS_FIELDS ... OK
All OK
Loading dictionary tables data:
SYS_TABLES ... 1845 recs OK
SYS_COLUMNS ... 22029 recs OK
SYS_INDEXES ... 4994 recs OK
SYS_FIELDS ... 6070 recs OK
All OK
現(xiàn)在字典能被查詢來(lái)找出索引相對(duì)于任何給定表的索引ID。
給出的示例是對(duì)于在moodle2 schema中的表mdl2_user:
mysql> SELECT SYS_TABLES.NAME TABLE_NAME, SYS_TABLES.ID TABLE_ID,
SYS_INDEXES.NAME INDEX_NAME, SYS_INDEXES.ID INDEX_ID FROM SYS_TABLES LEFT JOIN
SYS_INDEXES ON SYS_TABLES.ID = SYS_INDEXES.TABLE_ID WHERE SYS_INDEXES.NAME LIKE '%PRIMARY%' AND SYS_TABLES.NAME LIKE 'moodle2/mdl2_user' AND SYS_INDEXES.NAME IN ('PRIMARY', 'GENERAL_CLUSTERED_INDEX');
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐ ‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+
| TABLE_NAME | TABLE_ID | INDEX_NAME | INDEX_ID |
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐ ‐‐‐‐‐‐+
| moodle2/mdl2_user | 646 | PRIMARY | 1867 |
+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐ +‐‐‐‐‐‐‐‐‐‐+
1 row in set (0.00 sec)
INDEX_ID返回與名稱1相應(yīng)的提取的頁(yè)文件:
$ ls pages‐ibdata1/FIL_PAGE_INDEX/*1867.page
pages‐ibdata1/FIL_PAGE_INDEX/0000000000001867.page
c_parser
此時(shí)有了已知的表定義,數(shù)據(jù)能被c_parser恢復(fù),像這樣,其中mdl2_user.sql 包含表定義:
$ ./c_parser ‐b "./pages‐ibdata1/FIL_PAGE_TYPE_BLOB" ‐p "dumps/moodle2" ‐l
dumps/moodle/mdl2_user.load ‐5f pagesibdata1/
FIL_PAGE_INDEX/0000000000001867.page ‐t mdl2_user.sql
對(duì)每個(gè)schema使用以下腳本和在轉(zhuǎn)儲(chǔ)目錄中的給定表定義,所有在數(shù)據(jù)目錄找到的表能被提取到適合LOAD DATA INFILE的文件,以及分開(kāi)的.load文件來(lái)加載它們。如果原始表定義不能被提供或從.frm文件被提取,反注釋sys_parser行只作為最后方法。如果原始表defs能被提供,它們應(yīng)該被作為分開(kāi)的sql文件儲(chǔ)存在dumps//
#!/bin/bash
RECOVERY_DB="test"
USER="root"
PASS="somepass"
DUMPS="dumps"
# Create schema
echo > ${DUMPS}/schema.sql
for DB in `mysql ‐‐user=${USER} ‐‐password=${PASS} ‐NBe "select name from
${RECOVERY_DB}.sys_tables" | sed ‐r "s/^(.*)\/.*$//" | grep ‐v SYS_ | sort ‐u `
do
mkdir ‐p ${DUMPS}/${DB}
echo "Creating schema for $DB..."
echo >> ${DUMPS}/schema.sql
echo "CREATE DATABASE IF NOT EXISTS $DB;" >> ${DUMPS}/schema.sql
for TABLE in `mysql ${RECOVERY_DB} ‐‐user=${USER} ‐‐password=${PASS} ‐NBe
"SELECT NAME FROM SYS_TABLES WHERE NAME LIKE '${DB}/%'"`
do
echo $TABLE
# ./sys_parser ‐u${USER} ‐p${PASS} ‐d ${RECOVERY_DB} ${TABLE} | tee
${DUMPS}/${TABLE}.sql >> ${DUMPS}/schema.sql
PKEY=`mysql ${RECOVERY_DB} ‐BNe "SELECT SYS_INDEXES.ID FROM SYS_TABLES
LEFT JOIN SYS_INDEXES ON (SYS_TABLES.ID = SYS_INDEXES.TABLE_ID) WHERE
SYS_TABLES.NAME = \"${TABLE}\" AND SYS_INDEXES.NAME=\"PRIMARY\""`
echo "pkey = $PKEY"
PAGE="pages‐ibdata1/FIL_PAGE_INDEX/`printf '%016u' ${PKEY}`.page"
echo "PAGE = $PAGE"
./c_parser ‐b "./pages‐ibdata1/FIL_PAGE_TYPE_BLOB" ‐p "./${DUMPS}/${DB}" ‐
l ${DUMPS}/${TABLE}.load ‐5f ${PAGE} ‐t ${DUMPS}/${TABLE}.sql > ${DUMPS}/${TABLE}
done
done
sys_parser
像之前所說(shuō)的,sys_parser能被用于從ibdata文件提取表定義,但它僅應(yīng)當(dāng)作為最后手段。可能需要一些猜測(cè),而且如果不能提供有效的表定義,從ibdata完整提取可用數(shù)據(jù)就不太可能了。
從.frm文件提取有效表定義
使用MySQL Utilities包的mysqlfrm從未損壞的.frm文件提取有效定義是可能的。要注意的是在診斷模式下使用mysqlfrm可能遇到與使用sys_parser從ibdata提取數(shù)據(jù)相同的問(wèn)題。所以使用mysqlfrm與服務(wù)器標(biāo)識(shí)是很重要的。輸出必須被調(diào)整來(lái)與c_parser運(yùn)作,因?yàn)槿绻钚?#xff0c;警告,或默認(rèn)字符集信息在表定義中被找到,c_parser會(huì)終止。這里是提取表定義和單個(gè)schema.sql被用于從在給定目錄中找到的所有.frm文件創(chuàng)建schema(s)的方式:
#!/bin/bash
for FRM in `find ../datadir/ ‐type f ‐wholename "*frm" | sort`
do
mysqlfrm ‐‐server=root:somepass@localhost:../datadir/mysql.sock ‐‐port=33307
$FRM | extract_schema.pl
if [ ${PIPESTATUS[0]} ‐ne 0 ]; then
echo "$FRM is corrupt"
fi
done
extract_schema.pl像這樣:
!/usr/bin/perl
open (SCHEMAFILE, '>>', "schema.sql") or die "Can not write to schema.sql $!";
$schema = "";
$table = "";
while () {
$origline = $ _;
chomp;
if (/^ CREATE TABLE.*$/) {
m/.*CREATE TABLE \`(. *)\`\.\`(.*)\`[[:space:]]\(/;
$schema = $1;
$table = $2;
print "Creat ing $schema.$table\n";
unless (‐e $schema or mkdir $schem a) {
die "Unable to create dir for sche ma $schema";
}
print SCHEMAFILE "CREATE DATABASE IF NOT EXISTS $schema;\n";
print SCHEMAFILE "USE $schema;\n";
print SCHEMAFILE "$origline";
open (TABLEFILE, '>', "$schem a/$table.sql") or die "Can not write to $schema/$table.sql";
print TABLEF ILE "CREATE TABLE $table (\n";
}
else {
s/ENGINE=(.*?)[[:space:]].*/ENGINE=;/;
s/`PRIMARY`//;
s/^#.*$//;
s/^WARNING.*$//;
$origline =~ s/(.*ENGINE.*$)/;/;
$origline =~ s/^#.*$//;
$origline =~ s/^WARNING.*$//;
print SCHEMAFILE "$origline" if (!/^\s*$/);
print TABLEFILE "$_\n" if (!/^\s*$/);
}
}
盡管undrop 可用令人高興 , 但遇到必須使用它的情況是非常糟糕的。
當(dāng)數(shù)據(jù)庫(kù)損壞時(shí),它不能保證任何數(shù)據(jù)能被恢復(fù)。避免陷入這種情況的方法就是使用MySQL Enterprise Backup來(lái)定期創(chuàng)建可用的備份,以及至少一個(gè)復(fù)制slave。關(guān)心數(shù)據(jù)安全的聰明管理員會(huì)在遠(yuǎn)程創(chuàng)建一個(gè)復(fù)制slave,將服務(wù)器的定期備份作為災(zāi)難恢復(fù)的準(zhǔn)備。
總結(jié)
以上是生活随笔為你收集整理的mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (DFS or BFS)Find The
- 下一篇: mysql dnslog_dnslog小