Главная Заметки Разное Mysql - как восстановить базу из .ibd и .frm файлов?



Осуществляем все этапы разработки сайтов.
Программирование под заказ (PHP, JavaScript, Delphi, базы данных).

Контакты:

телефон: 8-921-989-73-77, Юлия
8-911-400-24-42, Александр
В вашем браузере запрещен Javascript, адрес электронной почты скрыт
  267442

  4477662

Mysql - как восстановить базу из .ibd и .frm файлов? PDF Печать E-mail
Автор: Александр   
06.10.2013 19:19

База данных MySQL, состоящая из таблиц InnoDB - штука хорошая. Но она может стать источником серьёзных проблем, если однажды у вас "упадёт" сервер, и не окажется под рукой свежих бекапов. В случае с таблицами MyISAM - достаточно просто скопировать файлы из каталога погибшей базы данных в новую пустую БД. С InnoDB такой фокус, увы, не пройдёт. Но восстановление, тем не менее, почти всегда возможно. Итак, приступим.

 

Минимум, который вам потребуется для восстановления - файлы .ibd и *.frm от навернувшейся базы данных MySQL. Должно быть 2 файла от каждой таблицы. Если вы их не нашли в старой базе данных - всё совсем печально. Скорее всего это означает, что данные всех таблиц хранились в одном файле,  а это совсем другая история. В этом случае остаётся посочувствовать, и посоветовать в будущем в настройках MySQL не забывать устанавливать весьма полезный параметр:

[mysql]
innodb_file_per_table = 1

Ну а если *.ibd и *.frm нашлись - восстановление хоть и будет несколько утомительным процессом, но скорее всего завершится успешно. В первом опыте мне очень помогла вот эта (1) и эта (2) статьи, однако, пришлось идти своим путём.

Для начала, собираем новый MySQL сервер, желательно той же версии, что был на пострадавшей БД. Узнать версию можно, например, из файла лога БД. Версия ОС, в целом, не важна. Но под Unix есть больше всяких примочек. В любом случае, настоятельно рекомендую не пользоваться рабочим MySQL сервером, ибо в результате последующих шаманских действий он может накрыться, и проблем у вас только только прибавится. Под Windows кстати все благополучно прошло и с пакетом Денвер, а все команды можно выполнять из его phpMyAdmin. А вот при восстановлении InnoDB Percona Server, не осталось ничего другого, как сооружать сервер под Юниксом.

Поехали. Не забыв про innodb_file_per_table = 1 в настройках, создаем базу данных с тем же именем, что и потерпевшая. Создаём в ней таблицу, указав для нее имя восстанавливаемой:
CREATE TABLE `sometable` (`id` INT PRIMARY KEY) ENGINE=Innodb;

Теперь останавливаем MySQL, подменяем в нём .frm файл нашим старым от этой таблицы, а .ibd скопируем себе "для опытов". Запускаем MySQL, и выполняем SHOW TABLE `sometable`;

Ура! Теперь у нас есть структура погибшей таблицы! А в первой из ссылок утверждалось, что без неё ничего не восстановить. Теперь можно (не забывая при таких копированиях останавливать MySQL) попробовать подменить файл .ibd нашим, с данными. Пробуем выполнить select, и... сервер с грохотом падает. Чтобы понять в чём дело, заглянем в его лог: "Id таблицы sometable такой-то, однако должен быть таким-то!". Вот это и есть главная печаль. База данных запоминает у себя id каждой таблицы, и проверяет его (он хранится в .ibd файлах).

Теперь у вас есть 2 пути, чтобы подружить id старой таблицы, и id в новой базе данных. Один из вариантов - подменить id в самой базе данных. Ну, если у вас получится - это хорошо... Помось в этом может утилита, работающая пою Юниксом вот отсюда. У меня она успешно откомпилировалась, но при попытке выполнить ./ibdconnect -o /usr/local/mysql/ibdata1 -f /usr/local/mysql/someDB/sometable.ibd -d someDB -t sometable увы, фокус не прошёл. Она правильно указала id, но написала об ошибке при попытке его изменения. Ну чтож, можно просто перед созданием новой таблицы накрутить счётчик новой базы данных, чтобы он совпал с создаваемой таблицей. Для этого просто скриптом создаем-удаляем таблицы, как это сделать - есть в первой ссылке. Если у вас много таблиц - лучше сначала найдите таблицу с минимальным Id. Чтобы сбросить счётчик сервера MySQL - нужно пересоздать базу данных, и может быть придется удалить 3 файла ib*.

Другой путь. Подмена Id в старой таблице, чтобы он совпал с тем, который хочет новая БД. Эх, если б он там хранился в одном месте... Хранится он в 2 байтах, "по порядку", т.е. Id=13 будет записано как 00 0D. Почти в начале .ibd файла он записан дважды, с небольшим интервалом. Можете в первой статье почитать подробнее, там всё просто, обзаведитесь HEX-редактором и посмотрите сами. Если табличка была небольшая - то меняете его в верхних двух местах, подсовываете MySQL серверу, ставите в настройках

skip-innodb_checksums = 1
innodb_force_recovery = 5

Если таблица откроется - срочно её сохраняйте! :) А вот если таблица была большой - всё опять упадёт с прежней ошибкой. Дел в том, что этот id внутри файла может повторяться много раз, в начале каждой внутренней страницы. Так что придется аккуратно пройтись поиском по всему файлу, поменяв id там где он действительно id и не трогая там, где эта комбинация байт является чем-то другим. Так что "заменить всё" скорее всего не прокатит.

Ещё одни грабли: кодировка. В получившейся таблице русские буквы могли дважды перекодироваться, превратившись в нечитаемую кашу. Там что сразу обращайте внимание на внутреннюю кодировку сервера в его настройках, и на то, что написано в запросе восстанавливаемой таблицы. Например, у меня был случай, когда сама таблица имела кодировку CP1251, а внутренние поля отдельно - latin1. Восстановилась непонятная каша. Пришлось для таблицы всё повторить сначала, в запросе её создания просто поубирав latin1 для столбцов. Всё получилось.

Вот, пожалуй, и всё. Удачи, и не забывайте делать своевременные бекапы.

Если же самостоятельно восстановить базу данных нет возможности - можем помочь



Контроль за копиями этого текста: сервис TextMarket

Обновлено 06.10.2013 22:01
 

Добавить комментарий


Защитный код
Обновить