Если у нас есть страницы InnoDB, есть два способа узнать, сколько записей они содержат:
- Поле PAGE_N_RECS в заголовке страницы
- Подсчет записей при ходьбе по списку записей от минимума до супремума
В какой — то предыдущей версии из инструмента восстановления краткого резюме было добавлено на свалку , которая производится с помощью constraints_parser.
Но если страница потеряна и page_parser не нашел ее, все записи с этой страницы будут потеряны. Другими словами, статистика восстановления на странице дает нам мало представления о том, является ли восстановленная таблица полной.
Чтобы устранить этот недостаток, в ревизии 80 введен новый инструмент index_check.
Как вы знаете, InnoDB хранит таблицу в кластерном индексе с именем PRIMARY.
ПЕРВИЧНЫЙ индекс — это структура дерева B + . Приятно, что все конечные узлы имеют указатели на следующий конечный узел, поэтому следуя указателям, мы можем прочитать весь индекс в порядке первичного ключа. InnoDB расширяет структуру и сохраняет также указатель на предыдущий узел. Предыдущий узел головы равен NULL, а также следующий узел хвоста.
Основываясь на этих знаниях, мы можем проверить, есть ли у нас все элементы списка. Если мы сможем перейти с любой страницы InnoDB в начало и конец списка, то наш набор страниц завершен.
Это именно то, что делает index_chk — он читает файлы из каталога со страницами InnoDB (который создается page_parser) и пытается просмотреть список страниц вперед и назад.
Давайте рассмотрим пример. Я взял поврежденное табличное пространство 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 #
Плохие новости, страница с идентификатором 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 #
Таким образом, таблица полностью восстанавливается, если и только если выполняются два условия:
- Команда grep «Потерянные записи: ДА» table.dump | grep -v «Страница листа: НЕТ» ничего не выводит
- ./index_chk -f pages-1374669586 / FIL_PAGE_INDEX / <inde_id of = ”» my = ”» table = »»> сообщает о ОК