Макс и стажёр с тяжёлой рукой
История о случайном DELETE, пользе CTAS-бэкапов, soft-delete и аудита данных перед рискованными изменениями в PostgreSQL.
КейсPostgreSQLSQLАудитБезопасность данных— Макс, помоги! — В офис ворвался Коля, новый стажёр. Лицо белое как стена.
— Что случилось? — Макс не отвёл глаз от монитора. Время не кофе пить, а тикеты разбирать.
— Я случайно удалил данные из notification_queue. Коллеги сказали, что это важные данные! Они же исчезли навсегда!
Макс медленно повернулся:
— Удалил? Как? Почему?
— Да я… Я подумал, они уже не нужны! — Коля чуть не плакал. — Выполнил DELETE FROM notification_queue WHERE status = 'error'… и всё.
— Подумал? — Макс усмехнулся. — Ну да, это ведь всегда работает. Особенно в базах данных. Только вот для стажёров после «подумал» должно быть действие «спросил у старших», а потом уже SQL-команда.
Макс сдержал дыхание и закрыл глаза. Сильно, конечно. Но не в первый раз. Он сделал глубокий вдох:
— Первое правило: прежде чем что-то удалять или редактировать, делай бэкап с помощью CTAS. У нас для бэкапов есть отдельная схема.
Макс открыл новый файл скрипта и написал:
CREATE TABLE support.notification_queue_backup ASSELECT *FROM notification_queueWHERE status = 'error';— Сначала всегда копируй данные. Удалить мы всегда успеем. А вот восстановить… — Макс бросил косой взгляд на Колю. — Ну, ты понял.
Коля кивнул, но выглядел по-прежнему растерянно.
— Второе правило. Смотри сюда, — Макс открыл схему таблицы notification_queue и указал на столбец is_deleted. — Видишь? У нас есть поле is_deleted. Это soft-delete. Вместо того чтобы физически удалять данные, мы просто помечаем их как удалённые:
UPDATE notification_queueSET is_deleted = trueWHERE status = 'error';— Так данные остаются в таблице. В любой момент можно откатить изменения или восстановить запись. А ты что сделал?
— Удалил… навсегда, — пробормотал Коля, уставившись в пол.
— Часто вместо is_deleted используют обратную логику с is_active, которое для действующих записей устанавливают в true.
— Спасибо, я запомню.
— В данном случае не нужно было удалять эти данные даже с помощью soft-delete. Вся существующая логика уже учитывает статусы.
Макс сделал ещё один глубокий вдох, достал заготовку запроса для работы с аудитом данных и нашёл все удалённые записи.
— Теперь можешь выдохнуть. Тебе повезло, что аудит был включён для этой таблицы.
Доработав запрос, он вернул удалённые записи в основную таблицу.
— Ну, теперь ты понял, почему я не удаляю данные сразу? — Макс хлопнул его по плечу. — В жизни, как и в базе, важно не спешить избавляться от того, что кажется ненужным. Особенно если у тебя тяжёлая рука и быстрые пальцы.