2013/7/26 by Aleksandr Kuzminsky
InnoDBのページがいくつのレコードを含んでいるかを知るには二通りある。
- ページヘッダの
PAGE_N_RECS
フィールドを見る - レコード一覧の下限から上限まで全てを確認してレコード数を数える
Percona Data Recovery Tools for
InnoDB の
以前のリビジョン
で、 constraints_parser
コマンドで出力されたダンプデータに、短いサマリが付くようになった。
しかし、ページが失われてしまって、しかも page_parser
がこれを見つけられなかった場合、ページ内の全レコードは失われてしまう。言い換えると、ページごとのリカバリ統計情報は、テーブルのリカバリが完了したかどうかについての情報になり得るわけだ。
この問題をカバーするために、 revision
80
で使用可能になった index_check
コマンドがある。
ご存じかもしれないが、InnoDBはテーブルを PRIMARY と呼ばれるクラスタインデックス上に保存する。
PRIMARY インデックスは B+ツリー である。全リーフノードが次のリーフノードへのポインタになっているという利点があり、ポインタをたどることで、プライマリキーの順に並んだインデックス全体を読み取ることができる。InnoDBでは、この構造を拡張してあり、前のノードへのポインタも保存している。先頭の前のノードと最後尾の後のノードはNULLになっている。
この知識を元にすると、リストの全要素があるかどうかをチェックできる。あるInnoDBページからリストの最初あるいは最後へ移動することができれば、ページの集合は完璧であるということになる。
これは index_chk
コマンドがやっていることだ。このコマンドは、(page_parser
コマンドが出力した)InnoDBページが入っているディレクトリからファイルを読み出し、ページのリストを前後にたどろうとする。
例を見てみよう。壊れたInnoDB表領域を用意して、 page_parser
で分割している。
# ./page_parser -f /var/lib/mysql/ibdata1
Opening file: /var/lib/mysql/ibdata1
File information:
ID of device containing file: 64512
inode number: 27037954
protection: 100660 (regular file)
number of hard links: 1
user ID of owner: 107
group ID of owner: 116
device ID (if special file): 0
blocksize for filesystem I/O: 4096
number of blocks allocated: 86016
time of last access: 1374662334 Wed Jul 24 06:38:54 2013
time of last modification: 1374233938 Fri Jul 19 07:38:58 2013
time of last status change: 1374233938 Fri Jul 19 07:38:58 2013
total size, in bytes: 44040192 (42.000 MiB)
Size to process: 44040192 (42.000 MiB)
8.26% done. 2013-07-24 08:39:58 ETA(in 00:00 hours). Processing speed: 3637248
B/sec
...
95.70% done. 2013-07-24 08:40:09 ETA(in 00:00 hours). Processing speed:
4399053 B/sec
#
あるインデックスを取り上げて、ページが全て存在するかをチェックしてみよう。
# ls pages-1374669586/FIL_PAGE_INDEX/0-410/
00000000-00000145.page 00000000-00000235.page 00000000-00000241.page
00000000-00000247.page 00000000-00000254.page
00000000-00000147.page 00000000-00000236.page 00000000-00000243.page
00000000-00000249.page 00000000-00000255.page
00000000-00000148.page 00000000-00000239.page 00000000-00000244.page
00000000-00000251.page
# ./index_chk -f pages-1374669586/FIL_PAGE_INDEX/0-410
Couldn't open file
pages-1374669586/FIL_PAGE_INDEX/0-410/00000000-00000140.page
#
残念、ID 140のページがなくなっている!
実際のところページ#145の前はページ#140だが、それが消えてしまっている。
# hexdump -C pages-1374669586/FIL_PAGE_INDEX/0-410/00000000-00000145.page |
head -2
00000000 d4 cd 68 41 00 00 00 91 00 00 00 8c ff ff ff ff |..hA............|
00000010 00 00 00 00 2b 6c ea 90 45 bf 00 00 00 00 00 00 |....+l..E.......|
#
気分のいい終わり方のために、全ページそろっているインデックスをチェックした場合も見てみよう。
# ls pages-1374669586/FIL_PAGE_INDEX/0-2/* # this is SYS_COLUMNS table
pages-1374669586/FIL_PAGE_INDEX/0-2/00000000-00000010.page
pages-1374669586/FIL_PAGE_INDEX/0-2/00000000-00002253.page
pages-1374669586/FIL_PAGE_INDEX/0-2/00000000-00002244.page
# ./index_chk -f pages-1374669586/FIL_PAGE_INDEX/0-2
OK
#
というわけで、テーブルが完全にリカバリできるのは、以下の2つの条件を満たした場合である。
grep “Lost records: YES” table.dump | grep -v “Leaf page: NO”
が何も返さない- ./indexchk -f pages-1374669586/FILPAGEINDEX/<indeid of=”" my=”" table=”"> がOKを返す