Восстановление 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. Делайте бэкапы.