ホームページ  >  記事  >  システムチュートリアル  >  ibd ファイルを使用した MySQL データ回復のヒント?

ibd ファイルを使用した MySQL データ回復のヒント?

PHPz
PHPz転載
2024-01-02 10:42:091337ブラウズ
###導入### ディスクの不良セクタや停電などの事故は日常茶飯事ですが、遭遇するだけで「スリル」が味わえます。データベースの損傷によりデータが失われ、Binlog が利用できなくなった場合はどうすればよいですか?ビジネスの安定性を確保するために、データをロスレスで短時間で復元するために、binlog の使用に加えて、新しい復元スキルも実践しました。

以前に書いた「制御不能な研究開発者を夢中にさせるたった 1 つのトリック」をまだ覚えていますか?前述したように、私たちが毎日最もよく使用する 2 つのデータベース回復方法は次のとおりです。

ibd ファイルを使用した MySQL データ回復のヒント?

上記のどちらの方法でもリアルタイム ロールバックを実現できますが、これら 2 つのスキルがあれば十分だと思いますか?

###いいえ…。!###

この複雑なオンライン アーキテクチャには、実際には、私たちが予測できない未知の理由がたくさんあります。たとえば、次のような状況です:

ハードな作業により寿命を迎えたハードディスクには不良セクタが発生し、データベースが破損します。そして、それはたまたまibdataファイルとbinlogファイルを破損しました。したがって、定期的なバックアップによる binlog リカバリの解決策をまだ考えているとしても、それは不可能であり、復元には固定小数点バックアップのみを使用することしかできないのでしょうか。慎重に検討した結果、運用保守担当者としては、ビジネスに多大な影響を与えるため、損失を伴うロールバックは最終手段としては絶対に実行しませんが、他に何ができるでしょうか?次は大技を放つぞ! ! !

まずデータベース環境をチェックして、独立テーブルスペースが有効になっているかどうかを確認してください。有効になっている場合は、おめでとうございます。すべてのデータをリカバリできる可能性が高くなります。データ リカバリを実現するには、各データベース ディレクトリ内の frm および ibd ファイルに依存できます。一般的に、InnoDB が使用されているが独立テーブル スペースが有効になっていない場合、すべてのデータベース テーブル情報とメタデータが ibdata ファイルに書き込まれます。これは持続します。実行すると、ibdata ファイルがどんどん大きくなり、データベースのパフォーマンスが低下します。 InnoDB は、データを独立して保存できる独立テーブル スペースを有効にするパラメーターを提供します。この方法では、ibdata ファイルは一部のエンジン関連のインデックス情報を保存するためにのみ使用され、実際のデータは独立した frm および ibd ファイルに書き込まれます。

わかりました。frm ファイルと ibd ファイルを使用して、データの回復を試し始めることができます。このプロセスは、binlog の復元よりもスリリングで興味深いものです。まず、ibd と frm に関する手順を見てみましょう:

.frm ファイル: テーブル構造の定義などを含む、各テーブルのメタデータを保存します。このファイルはデータベース エンジンとは関係ありません。

.ibd ファイル: 独立テーブルスペースが有効になっている (my.ini で innodb_file_per_table = 1 が設定されている) 場合に、テーブルのデータとインデックスを保存するために InnoDB エンジンによって生成されるファイル。

InnoDB データベースの場合、データ ディレクトリ全体をコピーせず、指定したデータベース ディレクトリのみを新しいインスタンスにコピーすると、データベースが認識されないことは誰もが知っています。では、これら 2 つのファイルに基づいてデータベースを復元するにはどうすればよいでしょうか?

リカバリのアイデア:

エンジンに関する一部のインデックス情報が ibdata ファイルに保存されているため、ibdata ファイルが破損し、テーブル名のインデックスが失われ、起動できなくなります。次に、最初に古いデータ ディレクトリ全体の名前を変更してバックアップし、次にデータベースを再初期化して新しい ibdata ファイルを生成し、次に元のデータベースと対応するテーブルを再作成し、最後にバックアップ テーブル スペース ID 番号を新しいテーブルスペース ID 番号 (ibdata ファイルにはテーブルごとに一意のテーブルスペースインデックス ID が含まれており、作成される新しいテーブルの数によって増分されます)。これにより、元のデータベースを復元できます。 例えば:### ライブラリ名: test_restore テーブル構造: db_struc.sql

テーブル ファイル: G_RESTORE.ibd、G_RESTORE.frm


1. 新しいライブラリを作成し、テーブル構造をインポートします

#mysql -uroot –p**** -e “データベース test_restore の作成” #mysql -uroot –p**** test_restore

2. 新しいインスタンスの test_restore ライブラリ内のテーブル ID を表示および変更します

リーリー 文字化けした状態で直接開き、16進数に変換してご覧ください。 Vi で :%!xxd を実行して 16 進数に変換します。結果は:

写真の通り。 mysql データベースの G_RESTORE テーブルの ID は 00fe です。

ibd ファイルを使用した MySQL データ回復のヒント?バックアップされた G_RESTORE.ibd ファイルを変更します。操作は上記と同じですが、最初にバックアップする必要があることに注意してください。

リーリー

011b を 00fe に変更します。知らせ。変更が完了したら、まず vim で変更を実行する必要があります: %!xxd -r

ibd ファイルを使用した MySQL データ回復のヒント? 次に、ファイルを保存して終了します。それ以外の場合、保存された結果は 16 進数で表示されます。

結果を次のように保存します:

ibd ファイルを使用した MySQL データ回復のヒント?変更した G_RESTORE.ibd ファイルを新しいデータベースの G_RESTORE.ibd ファイルに置き換えます。

ibdataテーブルIDについての説明:

参考官方文档解释,每个表空间分配了4个字节存储了表空间id信息,最后偏移量地址为38。还有一组预留的表空间id,同样是4个字节,最后偏移量地址为42。

3. 验证并还原mysql数据

关闭mysql。修改my.conf。
innodb_force_recovery=6 innodb_purge_threads=0

启动数据库。如果不修改。数据库会认为G_RESTORE已被损坏。

Select 一下,即可查看到还原结果,但此时插入数据会报错,应尽快将数据dump出来 ,导回原来的实例中。

导出数据,再导入数据,恢复完毕!

#mysqldump -uroot –p****** test_restore > test_restore.sql

#mysql -uroot –p****** test_restore 
<p>说明:变更了新的space id后的.ibd表文件,启动数据库后只能认出数据,但不能写入,这是因为原ibdata文件不仅保存了space id索引,还同时保存了一些其它的元数据。为了使元数据补全,所以采取导出、再导入的操作。</p>
<p>以上举例为单个库表的恢复过程,看到这里大家一定会产生另一个疑问吧?线上的场景不可能是只有一个表的,数据库表很多的情况下,这样一个个表的修改,速度无疑是太慢了。那么存在大量表的情况下如何恢复呢?思路是,取得备份的ibd文件的id值,按id值顺序来建表,中间跨度随便建表语句来凑够数(每个表空间索引id由创建新表的数量依次递增)。实现方式如下:</p>
<p><span style="color: #339966;"><strong>1. 获取备份数据库ibd文件的space id号,并排序。</strong></span></p>
<pre class="brush:php;toolbar:false">for ibd in `find test_restore/ -name “*.ibd”` ; do  echo -e “${ibd///// }   /c” ;hexdump -C ${ibd} |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’ ;done | sort -n  -k 3 | column -t > /tmp/

生成的ibd.txt文件,格式如下:(库名–表名–SpaceId)

ibd ファイルを使用した MySQL データ回復のヒント?
2. 新建表,查看当前表空间id(假设space id为10)

#mysql -uroot –p****** -e”create table test.tt(a bool)”

#hexdump -C mysql/test/tt.ibd |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’

3. 先创建所有库,准备所有表结构,写脚本,依据space id号自动创建新表

准备好数据库表结构,可以从备份文件里取出来(我们备份方式是把结构和数据分开备份的),或者从其他有相同表结构的服务器上备份再拷贝过来。

参考备份语句:

mysqldump -uroot –p****** -d ${db} –T /data/backup/${db}/

创建原有的数据库:

mysql -uroot –p****** -e “create database ${db}”

恢复表id创建表脚本:

#!/bin/bash
#因为前面假设为10,所以从11开始创建
oid=11

#打开前面生成的ibd.txt文件,按行读取”库名–表名–SpaceId”
cat /tmp/ibd.txt | while read db tb id ;do

#假如我们需要恢复catetory表,他的id为415,基于id是创表自增的原则,即415-11=404,
#我们还需要循环创建404个表后,才真正导入catetory表结构。
for ((oid;oid<id do mysql table test.t bool echo ok done let oid="oid+1">
<p><span style="color: #339966;"><strong>4. 检查表空间id 和备份的是否一致</strong></span></p>
<pre class="brush:php;toolbar:false">for ibd in `find test_restore/ -name “*.ibd”` ; do  echo -e “${ibd///// }   /c” ;hexdump -C ${ibd} |head -n 3 |tail -n 1|awk ‘{print  strtonum(“0x”$6$7)}’ ;done | sort -n  -k 3 | column -t > /tmp/ibd2.txt

确认一致后,拷贝备份的.ibd文件到新数据库实例目录下,修改my.cnf

innodb_force_recovery=6

innodb_purge_threads=0

启动数据库。后续步骤如同单表恢复,直接导出恢复到原来实例中即可。

当然,这种方式是在数据库出现极端情况下,不得不采取的一种方式,线上最重要的还是做好主从同步和定时备份,从而规避此类风险。

关于InnoDB引擎独立表空间说明:

使用过MySQL的同学,刚开始接触最多的莫过于MyISAM表引擎了,这种引擎的数据库会分别创建三个文件:表结构、表索引、表数据空间。我们可以将某个数据库目录直接迁移到其他数据库也可以正常工作。然而当你使用InnoDB的时候,一切都变了。

InnoDB默认会将所有的数据库InnoDB引擎的表数据存储在一个共享空间中:ibdata1,这样就感觉不爽,增删数据库的时候,ibdata1文件不会自动收缩,单个数据库的备份也将成为问题。通常只能将数据使用mysqldump导出,然后再导入解决这个问题。

但是可以通过修改MySQL配置文件[mysqld]部分中innodb_file_per_table的参数来开启独立表空间模式,每个数据库的每个表都会生成一个数据空间。

优点:

1.每个表都有自已独立的表空间。

2.每个表的数据和索引都会存在自已的表空间中。

3.可以实现单表在不同的数据库中移动。

4.空间可以回收(除drop table操作处,表空不能自已回收)

a) Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。

b) 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。

c) 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

欠点:

単一テーブルが大きすぎます (100 G を超えるなど)。

###結論は:### 共有テーブルスペースには、挿入操作における利点がほとんどありません。他のテーブルスペースは、独立したテーブルスペースほどパフォーマンスが良くありません。独立テーブルスペースを有効にする場合は、innodb_open_files を適切に調整してください。

設定方法:

1.innodb_file_per_table 設定有効にする方法:


my.cnfの[mysqld]の下に設定します

innodb_file_per_table=1

2. 有効かどうかを確認します:

mysql> '%per_table%' のような変数を表示します;

3. 排他的テーブルスペースを閉じる

innodb_file_per_table=0 独立テーブルスペースを閉じる


mysql>「%per_table%」のような変数を表示;

以上がibd ファイルを使用した MySQL データ回復のヒント?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlinuxprobe.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。