?

Log in

No account? Create an account
Road

yapatha


Просто жизнь, просто свет, просто путь


Previous Entry Share Next Entry
Как восстановить базы MySQL InnoDB имея на руках только frm и ibd файлы
Road
yapatha
Случилось у нас тут недавно.... вобщем бэкапы мы вроде как делаем, но, отчего то именно в этот раз всё пошло не так и получилось так, что архивная база оказалась без бэкапа. А файлики ib_logfile* и ibdata* успешно похерились, что привело ненадолго в состояние уныния, но, вспомнив, что уныние есть грех и вобще нефиг там и тут, что сервер был запущен с включеным параметром innodb_file_per_table = 1 (что означает - держим таблички не скопом, а каждый в отдельном файлике), а так же вооружившись гуглом, решил всё таки докопаться до истины и ситуацию исправить.

Итак, что мы имеем:
1. Каталог базы данных с файлами вида *.frm (структура таблицы) и *.ibd (собственно данные).
2. MySQL который в упор не видит эти таблички объявляя базу данных пустой, причём не видит из под phpmyadmin, например, из под консольного клиента по использованию show tables вполне видит таблички, но, при попытке хоть что то сделать с табличками кричит "ERROR 1146 (42S02): Table XXX.xxx_xxx' doesn't exist" (оно и понятно, файл с tablespace то стёрт).
3. В логах сообщение:
"Cannot find or open table XXX/xxx_xxx from
the internal data dictionary of InnoDB though the .frm file for the
table exists. Maybe you have deleted and recreated InnoDB data
files but have forgotten to delete the corresponding .frm files
of InnoDB tables, or you have moved .frm files to another database?
or, the table contains indexes that this version of the engine
doesn't support."

Вооружаемся:
1. Статьями отсюда http://www.chriscalender.com/?p=28=1 и отсюда http://www.mysqlperformanceblog.com/2011/05/13/connecting-orphaned-ibd-files/ (вот прямо по этим статьям у меня ничего не получилось, поэтому пришлось искать свой путь).
2. Комплектом отличных программ для восстановления баз данных innodb отсюда - https://launchpad.net/percona-innodb-recovery-tool
3. Терпением.

Поехали!

Надо всё таки сказать сразу что для экспериментов я быстренько поднял сервер баз данных аналогичный потерпевшему, что в принципе не является критичным - лишь бы мажорная версия MySQL совпадала, платформа, кстати, тоже особой роли не играет, за исключением того, что Percona Data Recovery Tool for InnoDB штука не кроссплатформенная, поэтому unixway всё таки приветствуется.

Итак, создаём на экспериментальном сервере базу данных аналогичную потерпевшей -
mysql CREATE DATABASE XXX;

после чего, создаём табличку из потерпевшей базы данных:
mysql CREATE TABLE `xxx_xxx` (`id` INT PRIMARY KEY) ENGINE=Innodb;

, но вот в чём закавыка - табличку то надо создать со структурой 100% идентичной потерпевшей, а если мы не знаем структуру, как быть.... быть то как я вас спрашиваю?
Да проще простого - не выходя из mysql (например в соседней консоли) копируем старый *.frm файл поверх нового, возвращаемся в mysql, делаем show create table xxx_xxx и видим свою структуру таблички, но, так работать не будет, поэтому, экспортируем табличку, уничтожаем её и создаем импортом (я всё это делал при помощи phpMyAdmin).

Так, структура таблицы на месте, двигаемся далее. теперь имеем логичное желание увидеть данные или хотя бы (обязательно) сделать нормальную резервную копию.

Останавливаем mysql сервер.
Копируем *.ibd файл нашей таблички от потерпевшей базы поверх нового.
Поправляем владельца файла и права доступа чтобы не поймать в дальнейшем ошибку о том что движок InnoDB не видит файл который есть на диске (чесслово - полдня убил пытаясь понять что происходит - файл то вот он, а движок его в упор не видит).
chown -R mysql:mysql /var/db/mysql/XXX
chmod 660 /var/db/mysql/XXX/xxx_xxx.ibd

И, затем, самое интересное - корректируем существующий в новом файле ibdata1 (или как у вас там) id таблицы в соответствии с тем id который имеет место быть у старого файла. Для этого нам и пригодится чудо инструмент Percona Data Recovery Tool for InnoDB, а именно ibdconnect в его составе.

Делаем магию
ibdconnect -o /var/db/mysql/ibdata1 -f /var/db/mysql/XXX/xxx_xxx.ibd -d XXX -t xxx_xxx

После этого Александр Кузьминский рекомендует сделать ещё innochecksum -f /var/db/mysql/ibdata1, для того, чтобы подкорректировать контрольную сумму файла, иначе движок innodb рухнет со страшным грохотом и криками про несовпадение контрольной суммы. Но я запускаю экспериментальный сервер MySQL с параметром "skip-innodb_checksums" и плюваю на контрольные суммы в целом - это же разовый момент, зачем оно нам?

Финально задаём задаём в my.cnf параметр innodb_force_recovery = 6, зажмурившись запускам MySQL сервер и ... ВУАЛЯ!!! - наши данные видно даже в phpmyadmin, работать с ними конечно не рекомендуется, так как таблица всё таки инвалид в прошлом, и как она будет жить дальше малоизвестно, поэтому сразу же бэкапим всё что только можно:
mysqldump --force --compress --triggers --routines --create-options -u someuser -p --databases XXX > /var/spool/mygreatbackup.sql

Можно всё это дело теперь обернуть в какой скрипт чтобы восстановить все таблицы скопом, а самим идти пить пиво или что там кому, периодически проверяя жизнь на марсе... то есть процесс выполнения, потом схватить дрожащими ручонками бэкап нашей базы, записать его на компакт диск или любой другой твёрдый носитель (да хоть распечатать) и на подкашивающихся ногах запихать вышеупомянутый твёрдый носитель в сейф шепча про себя "да чтобы я ещё раз, да чтобы я... да чтобы без бэкапа..."

Нескушных летних ночей и почаще заглядывайте в крон занося строчки бэкапа всего что важно и нужно.