日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据

發布時間:2025/3/12 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

適用于:

MySQL服務器版本4.1到5.6 [發行版4.1到5.6]

本文信息適用于所有平臺。

目標

如何使用undrop for innodb從損壞的表中提取數據

解決方案

使用工具有時可能從無法用innodb_force_recovery讀取的表中恢復數據。

undrop可以直接讀取數據庫的ibdata1文件,來獲取數據字典信息和必要的恢復信息。

通常,該工具從整個(多個)ibdata文件且/或獨立的InnoDB tablespace文件 (innodb_file_per_table在使用中的.ibd文件)提取索引頁。Blob頁被提取到可應用的另外的子目錄

一旦數據被提取到索引頁,下一步就是從數據目錄恢復主鍵或一般聚類索引ID,然后將數據提取到適于使用LOAD DATA INFILE的文件。

如果可以的話,以要恢復的(多個)數據庫的至少一個schema dump啟動,需要時使用innodb_force_recovery。即使一個過時的備份也好過什么都沒有。雖然UnDROP有時能從ibdata文件中提取一個有效表定義,它不擅于處理所有列類型。如果你完全沒有備份,.frm文件能被用于重建表定義。如果你沒有任何備份或.frm文件,那么最后一招就是UnDROP 能從idbata提取的表定義能嘗試至少恢復一些數據。

首先stream_parser是用于從ibdata提取頁的工具。它的使用很簡單:

./stream_parser -f

頁會被默認提取到”pages-”。索引頁被儲存在子目錄FIL_PAGE_INDEX,且blob頁被儲存在子目錄FIL_PAGE_TYPE_BLOB。

要提取表的所有數據,有必要識別表的主鍵的數據目錄索引ID (在沒有主鍵時的一般索引)。這能通過使用UnDROP工具的”recover_dictionary.sh”腳本,將從被提取的索引頁提取的字典數據放到在運行服務器的’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

現在字典能被查詢來找出索引相對于任何給定表的索引ID。

給出的示例是對于在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相應的提取的頁文件:

$ ls pages‐ibdata1/FIL_PAGE_INDEX/*1867.page

pages‐ibdata1/FIL_PAGE_INDEX/0000000000001867.page

c_parser

此時有了已知的表定義,數據能被c_parser恢復,像這樣,其中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

對每個schema使用以下腳本和在轉儲目錄中的給定表定義,所有在數據目錄找到的表能被提取到適合LOAD DATA INFILE的文件,以及分開的.load文件來加載它們。如果原始表定義不能被提供或從.frm文件被提取,反注釋sys_parser行只作為最后方法。如果原始表defs能被提供,它們應該被作為分開的sql文件儲存在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

像之前所說的,sys_parser能被用于從ibdata文件提取表定義,但它僅應當作為最后手段。可能需要一些猜測,而且如果不能提供有效的表定義,從ibdata完整提取可用數據就不太可能了。

從.frm文件提取有效表定義

使用MySQL Utilities包的mysqlfrm從未損壞的.frm文件提取有效定義是可能的。要注意的是在診斷模式下使用mysqlfrm可能遇到與使用sys_parser從ibdata提取數據相同的問題。所以使用mysqlfrm與服務器標識是很重要的。輸出必須被調整來與c_parser運作,因為如果命令行,警告,或默認字符集信息在表定義中被找到,c_parser會終止。這里是提取表定義和單個schema.sql被用于從在給定目錄中找到的所有.frm文件創建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 可用令人高興 , 但遇到必須使用它的情況是非常糟糕的。

當數據庫損壞時,它不能保證任何數據能被恢復。避免陷入這種情況的方法就是使用MySQL Enterprise Backup來定期創建可用的備份,以及至少一個復制slave。關心數據安全的聰明管理員會在遠程創建一個復制slave,將服務器的定期備份作為災難恢復的準備。

總結

以上是生活随笔為你收集整理的mysql undrop_MySQL 如何对InnoDB使用Undrop来恢复InnoDB数据的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。