Авг 2

История восстановления базы MySQL из файлов (InnoDB)

Опубликовано в InnoDB, MYSQL

Основные боевые действия

И вот, наступил “прекрасный” день, сервер упал. Причем, не программно, а аппаратно – “полетел” жесткий диск. Далее жесткий диск был сдан в фирму, занимающуюся восстановлением данных, и значительная часть информации с него была восстановлена. Однако, админы при восстановлении самого сервера, восстановили только всю информацию с диска D, про нашу MySQL никто и не вспомнил (по “счастливой случайности” она оказалась поставлена на диск C). Все это время я себе спокойно занимался другими проектами, про эти события и знать не знал.

Прошло еще некоторое время, и вышеупомянутый сотрудник учреждения выходит из отпуска. Звонит мне и говорит о том, что не может войти в систему. Я, как обычно, спрашиваю, какое сообщение при этом выдает система, и все такое, сходу понимаю, что что-то не так с подключением к базе. Далее узнаю уже от нее эту историю с падением сервера, с тем, что там “что-то меняли”, и понимание мое становится еще более глубоким: теперь я понял, что нашей базы данных вообще нет на сервере. Причем, как выяснилось, нет ни базы, ни самой СУБД. Расспрашиваю админов, что же там все-таки было, что восстановили, что нет… прихожу к неутешительному выводу, что базы нет, и большой вопрос, удастся ли ее восстановить. Беру себе копию восстановленной с убитого жесткого диска информации и начинаю в ней копаться.

Первым делом ищу папку Program Files, куда ставится по умолчанию MySQL. Не нахожу, но зато нахожу папку с файлами данных MySQL, в ней папка с именем той самой нашей базы. Небольшой заряд оптимизма немного разогнал тучи моего отчаяния, но… глядя на файлы *.MYD, в которых по идее должны бы быть записи таблиц, вижу, что размер их слишком мал для такого количества информации, которое было введено. Бинарные логи также не были включены, и этот вариант автоматически отпадал. Начинаю думать над этим вопросом и вспоминаю, что можно взглянуть на девелоперскую базу на нашем тестовом сервере, что я и сделал. Там я увидел, что большинство таблиц – причем, самых важных – работают на движке InnoDB, а значит, что их записи хранятся отдельно в файле ibdata* (в моем случае, только ibdata1). Выхожу на уровень выше и вижу этот заветный файл. Рядом также два лога движка InnoDB: ib_logfile0 иib_logfile1. Открыв один из логов для просмотра в текстовом редакторе среди “кракозябр” я также увидел и куски самой информации, и тут я понял, что восстановить базу можно, по крайней мере, теоретически.

Надо было выбрать машину, где произвести попытку восстановления самой базы. Т.к. во время разработки я пользуюсь тестовым сервером, доступ к которому на уровне файловой системы мне без боя никто не даст, я решаю установить MySQL Server 5.1 и MySQL GUI Tools прямо на свою девелоперскую машину, работающую под Windows XP. Итак, все стоит, СУБД запущено, и подумав, как бы подступиться к задаче, я решаю сначала сделать экспорт скрипта создания БД с тестового сервера, и запускаю его потом на своей машине. Теперь у меня есть пустая база данных с полностью идентичной структурой и со всеми хранимыми процедурами. Останавливаю сервис MySQL, и копирую все содержимое из папки с именем нашей базы с упавшего сервера в аналогичную папку свежеустановленной локально у себя MySQL (папка с именем базы, вложенная в папку data, расположенную по пути для хранения файлов с данными указанному во время установки MySQL). При настройке локальной MySQL Server я решил указать для файлов данных InnoDB отдельную папку, куда далее скидываю восстановленный файл ibdata1. После этого перекидываю файлы InnoDB-логов (ib_logfile0 и ib_logfile1) прямо в свою папку data, где они должны быть по умолчанию.

Очередная попытка запустить MySQL снова не увенчалась успехом. Не имея реально боевого опыта в администрировании СУБД (за исключением опыта, полученного на курсах, но, опять же, по другим СУБД) я решил пойти путем эксперимента, хотя сейчас понимаю, что он совсем не был необходим. Удаляю файлы логов InnoDB, запускаю сервис MySQL и вижу, что он создает сами файлы InnoDB-логов с такими же названиями, но с размером в 20Мб.

Смотрю размер “своих” файлов с логами с упавшего сервера и вижу, что он существенно отличается и составляет 81Мб. Что-ж… останавливаю сервер, и захожу через MySQL Administrator в настройки переменных запуска (Startup Variables), вкладка InnoDB. Задаю размер log-файлов равным 81 Мб и закидываю обратно “свои” лог-файлы. MySQL запустился, но данных в интересующих меня таблицах я не увидел (хотя в таблицах, работавших на движке MyISAM, они уже были восстановлены). Немного пошарив по сети, я вычитал, что нужно запустить MySQL в режиме восстановления, для чего нужно задать значение стартовой переменно InnoDB_force_recovery равным 6. Попробовал сделать это через MySQL Administrator (ясное дело, что можно задавать параметры через GUI, а можно и редактировать файлы my.ini или my.cnf [в зависимости от версии MySQL и выбранной ОС] вручную), и, то ли я что-то не доделал, то ли что-то недосмотрел, но нужного результата не увидел. MySQL запустился как обычно, но про восстановление не сказал ни слова. “Что-ж,” – подумал я – “попробуем тогда через консоль, и еще раз явно пропишем параметр innodb_force_recovery”.

Запускаю коммандную строку Windows и ввожу:

> mysqld —console —innodb_force_recovery=6

На что в ответ получаю:

110727 10:31:52 [Note] Plugin ‘FEDERATED’ is disabled.

110727 10:31:52 InnoDB: Initializing buffer pool, size = 40.0M

110727 10:31:52 InnoDB: Completed initialization of buffer pool

110727 10:31:52 InnoDB: Operating system error number 32 in a file operation.

InnoDB: The error means that another program is using InnoDB’s files.

InnoDB: This might be a backup or antivirus software or another instance

InnoDB: of MySQL. Please close it to get rid of this error.

Грешить на антивирус особого смысла не было, и я решил остановить выполнение комманды при помощи CTRL+break, затем повторить еще раз команду с включенным Task Manager. Перед запуском команды на выполнение я просмотрел список процессов, чтобы убедиться в том, что ни один экземпляр сервиса MySQL не запущен. И снова повторил команду. Увидев то же самое сообщение, я заглянул в Task Manager и увидел, что почему-то запущено сразу два процесса с именем mysqld, причем, один запущен как системный, а другой – от имени моего пользователя. Убив системный процесс, я “разорвал порочный круг”, и выполнение пошло дальше:

> mysqld —console —innodb_force_recovery=6

110727 10:31:52 [Note] Plugin ‘FEDERATED’ is disabled.

110727 10:31:52 InnoDB: Initializing buffer pool, size = 40.0M

110727 10:31:52 InnoDB: Completed initialization of buffer pool

110727 10:31:52 InnoDB: Operating system error number 32 in a file operation.

InnoDB: The error means that another program is using InnoDB’s files.

InnoDB: This might be a backup or antivirus software or another instance

InnoDB: of MySQL. Please close it to get rid of this error.

110727 10:32:02 InnoDB: Operating system error number 32 in a file operation.

InnoDB: The error means that another program is using InnoDB’s files.

InnoDB: This might be a backup or antivirus software or another instance

InnoDB: of MySQL. Please close it to get rid of this error.

110727 10:32:12 InnoDB: Operating system error number 32 in a file operation.

InnoDB: The error means that another program is using InnoDB’s files.

InnoDB: This might be a backup or antivirus software or another instance

InnoDB: of MySQL. Please close it to get rid of this error.

InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on

InnoDB: Skipping log redo

110727 10:32:22 InnoDB: Started; log sequence number 0 0

InnoDB: !!! InnoDB_force_recovery is set to 6 !!!

110727 10:32:22 [Note] Event Scheduler: Loaded 0 events

110727 10:32:22 [Note] mysqld: ready for connections.

Version: ‘5.1.58-community’ socket: » port: 3306 MySQL Community Server (GPL)

Пока что я не понял, в чем было дело, почему запускалось сразу два процесса. В том числе и потому, что радость охватила меня, и подключившись к базе данных через Toad for MySQL я увидел, что данные восстановленны! Эта радость отодвинула все вопросы на второй план.

Осознание победы и контрольный выстрел

“Не отходя от кассы”, я делаю дамп базы, чтобы впоследствии восстановить ее на рабочем сервере – том самом герое этой “сказки”, которому всего-то навсего поменяли жесткий диск и переустановили систему.

> mysqldump —routines -u «user» -p db_name > [path\]db_name.sql

Ввожу пароль, и получаю скрипт создания и заполнения всех таблиц базы, а также всех хранимых процедур в файле db_name.sql в указанной в параметре папке. Информация спасена!

Затем уже на рабочем сервере устанавливаю сам MySQL, настраиваю его, создаю пустую базу и скидываю в нее дамп:

> mysql -u «user» –p db_name < [path\]db_name.sql

В настройках клиентского приложения менять ничего не пришлось, т.к. ip-адрес и сетевое имя сервера остались теми же, что и были до падения. Зашли в систему, проверили, и – о, чудо! – вся информация на месте. Тут и сказочке конец… но остановимся на “морали сей басни».

Выводы и заключение

Для себя я в очередной раз понял несколько важных вещей, а именно:

  1. Стратегия бэкапа/восстановления должна определяться уже на стадии разработки;
  2. В вопросах бэкапа/восстановления не надо надеяться на админов, если можешь сделать это сам; и тем более, если для тебя не составит особо труда автоматизировать этот процесс (что вполне можно сделать на примитивном уровне штатными средствами);
  3. Организация на предприятии и четкое регламентирование обязанностей каждого отдельного сотрудника в каждом конкретном проекте очень важны, когда мы имеем дело с IT; и современные стандарты разделения труда на IT-предприятиях очень и очень актуальны и выросли не на пустом месте;
  4. И все-же, если база полетела и нет бэкапа – это еще не повод сразу отчаиваться и опускать руки.

Изначально я думал просто дать кратенькую инструкцию что и как делать в таком случае, но, во-первых, подобные инструкции, в принципе, имеются в сети; и, во-вторых, решил более подробно описать все как было, с “подводными камнями” и ошибками; а также счел, что подобная форма изложения может оказаться несколько интересней. На самом деле, я уверен, что с подобными подводными камнями (точнее, мелкими камушками) столкнется меньшинство, но тем не менее, считаю важным, чтобы они были описаны.

И, наконец, краткая памятка-рецепт, что делать в подобной ситуации, когда от рабочей базы с таблицами InnoDB остаются только файлы с данными и логами InnoDB:

  1. Создаем пустую базу с идентичной упавшей базе структурой, останавливаем сервис СУБД;
  2. Подменяем файлы данных и описаний таблиц (файлы *.frm, *.MYI и *.MYD, папка с именем БД);
  3. В папку c файлами данных InnoDB (по умолчанию, скорее всего, это папка data, где хранятся и бинарные логи, и папки с именами БД; в моем случае я сделал для данных InnoDB отдельную папку) скидываем все файлы ibdata*. Здесь, наверное, надо отметить, что размер файлов должен соответствовать указанному в настройках. Если размеры разнятся, то можно поступить так: удалить созданный сервером файл (или файлы) вручную, и создать новый (или, соответственно, новые) с размером равным размеру имеющегося, затем запустить сервер и остановить его, и вместо созданных им файлов подставить свои. Облегчить эту операцию – чтобы не пришлось играть с настройками вручную – может MySQL Administrator. Или можно сделать еще проще – элементарно подмениь все файлы (или файл, если он один), а в файле настроек my.ini/my.cfg просто изменить размер – по идее должно сработать.
  4. Скидываем логи InnoDB (или подменяем, если они уже есть) туда, где они должны быть (по умолчанию, это та же папка data, где хранятся файлы с данными и описаниями, но это, опять же, может быть изменено в настройках);
  5. Задаем размер логов InnoDB равным размеру наших логов (если вручную – то в байтах, если в MySQL Administrator – в Мб);
  6. Запускаем MySQL daemon в режиме восстановления
    > mysqld —console —InnoDB_force_recovery=6
    ждем сообщения о том, что cервис запущен;
  7. И, наконец, смотрим на месте ли наши данные, и если на месте – делаем дамп базы, который потом уже разворачиваем на рабочий сервер.

Подобная операция в Linux или другой Unix-подобной системе будет выглядеть примерно так же. Кроме того, насколько я понимаю, файлы данных и логов MySQL (и бинарных логов, и логов InnoDB) универсальны для всех систем, и то, что упало на Windows, таким же образом можно восстановить и на Linux, и на OS X, и на любой другой системе, где работает сама MySQL.

Источник: <http://habrahabr.ru/blogs/mysql/125358/>

Комментарии: 0 » Метки: ,

You must be logged in to post a comment.