Экстренное восстановление данных в таблице mysql с минимальной потерей времени

Доброго времени суток хабрачитатели. Совсем не давно на работе произошел инцидент который подпортил нервы и привел к длительным рассуждениям. Суть: при обновлении записи в БД mysql забыл прописать условие where и в результате изменились все записи в таблице.

Как этого можно было избежать:
  1. Всегда внимательно перечитывать запрос на рабочем сервере перед запуском (может спасти… но… может и не спасти)
  2. В конце обновляющих запросов всегда ставить limit 1, если не требуется обратное (Спасет, но дело привычки, к тому же все равно потом искать правленную строку).
  3. Использовать специальную утилиту типа phpmyadmin (пожалуй самое рационально, но не всегда доступное)
  4. Всегда делать дамп. (А это по идее обязательно даже при соблюдении остальных пунктов).

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

Итак что у нас есть:

 

  1. Работающая база с неправильными данными
  2. Дамп правильной базы, без данных за определенный период (прошедший с момента создания дампа)
  3. Время в течении которого с базой продолжают работать, тем самым плодя ошибки и добавляя данные, которых нет в дампе.

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

Суть: Вместо перезаливки таблицы мы обновим ее значения используя старые данные из дампа.

 

Конкретно:

 

  1. Делаем копию дампа
  2. Редактируем копию дампа, удаляем данные о всех таблицах кроме нужной
  3. Заменяем все вхождения имени старой таблицы на новое (например temp_имя_старой таблицы)
  4. Загружаем исправленную копию дампа
  5. Выполняем запрос:
    update имя_старой_таблицы t1 join имя_новой таблицы t2 on (t1.id=t2.id) set t1.имя_поля_некорректными данными=t2.имя_этого_самого поля во второй таблице;
  6. Удаляем новую таблицу с измененным именем.

 

Итог:

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