Восстановление MySQL из бинарных логов.

21st Апрель 2011 | Категории: MySQL | Метки: , ,

Так случилось, что один гениальный программист на одном продакшн сервере выполнил запрос:

DROP DATABASE databasename

Конечно, ни один здравомыслящий человек на такое не способен, но вот врожденная криворукость и куриная слепота привела к тому, что он перепутал кнопки в PhpMyAdmin и на автомате подтвердил запрос. В итоге — база исчезла. Крики. Паника. Представление о лишении премии и т.д. Хорошо, что у этого программиста есть такой знакомый, как я.

Получив логины и пароли, я приступил к исследованию сервера.

Стоит отметить, что база использовалась для высоконагруженного форума с большой посещаемостью, и восстановить нужно было все, вплоть до последнего поста.

Перво-наперво, я обнаружил, что дамп делался очень давно. Почти 2 месяца назад. К моей великой радости были включены бинарные логи. Более подробно о бинарных логах можно почитать здесь, для читателя этой статьи я лишь отмечу несколько фактов:

  • Бинарные логи замедляют систему
  • Бинарные логи съедают место
  • Бинарные логи спасают ваши нервы

Для ведения любых логов и бэкапов нужно место. Ведение логов съедает системные ресурсы. Это очевидно. В некоторых случаях — RAID массива может оказаться не достаточно. Для большей надежности стоит включить бинарные логи.

Удобнее всего — извлечь SQL запросы на восстановление БД и записать их в файл. Это делается при помощи утилиты mysqlbinlog, её формат:

  • -d, —database — список БД, которые нужно восстановить.
  • —start-datetime и —stop-datetime — время начала и окончания периода, за который вам нужен лог запросов.
  • -t — ключ нужен для продолжения операции после окончания текущего лог файла.

Итоговая команда выглядит так:

mysqlbinlog -s -d databasename --start-datetime="2011-03-01 00:00:00" --stop-datetime="2011-04-19 18:00:00" -t mysql-bin.000038 > repair.sql

Начальное время для восстановления было выбрано неспроста: у клиента был настроен дамп базы данных по CRON на ежемесячное выполнение (который почему то не сработал 1 апреля), поэтому мне нужен лог изменений с момента последнего бэкапа.

Сам запрос на удаление таблицы произошел около 2011-04-19 17:58. При помощи vi (или любого другого консольного редактора) мы можем удалить вредный запрос.

И так, выполняем запрос, получаем файл repair.sql, который можем просмотреть и удалить лишние данные (выборочно).

Что бы восстановить таблицы MySQL из этого файла воспользуемся командой:

mysql -u user -p -q < repair.sql

ключ -q — включает игнорирование ошибок (полезно если вы оставляете на ночь восстанавливать большой объем данных, в котором есть некая не согласованность данных и дублирование индекса).

Какие существуют подводные камни?

  • Восстановление идет ОЧЕНЬ медленно. 40Мб на средней машине восстаналивались 8 часов.
  • Если бы бэкапы делались каждую ночь — то подобное восстановление заняло бы менее получаса.

Оптимальное решение:

  • Ищем последний бэкап;
  • Генерируем с помощью mysqlbinlog дамп на восстановление;
  • Восстанавливаем бэкап;
  • Восстанавливаем дамп на восстановление;

ps. Делайте бэкапы.

Subscribe without commenting


Пока комментариев нет.