Право на забвение в базе данных — Примеры
Пример 1 — Один идентификатор, который достаёт до всего
Пришёл запрос на удаление, и команда вручную ищет клиента: идентификатор пользователя есть в одних хранилищах, адрес почты — в других. Схема ниже копирует почту человека в каждую таблицу, которой касается. Разберитесь, что делает следующий запрос дешёвым, и напишите поля, которые несут связь вместо копии.
users.id
orders.customer_email скопирован, а не связан
events.email
Решение
users.id идентификатор субъекта, выданный один раз
orders.user_id ссылайтесь на users.id; email не копируйте
events.subject_id тот же идентификатор, распространённый на аналитику
logs.subject_id структурное логирование несёт его рядом с IP
Распространение одного устойчивого идентификатора на каждое хранилище — базу, логи, аналитику, очередь, поисковый индекс и хранилище данных — превращает следующий запрос в запрос к базе, а не в неделю поиска связей. Скопированный адрес почты — вторая вещь, которую надо найти и удалить, и забывают обычно именно копию. Обычная ошибка — проектировать это после прихода запроса; всё, что нужно, — один идентификатор, а внедрение задним числом дороже ровно в ту же работу.
Пример 2 — Удалить, обезличить или сохранить
Пишется процедура удаления, и первый черновик удаляет каждую строку, где упомянут человек, включая заказы, нужные бухгалтерии. Решите по каждому полю для одного человека и сохраните процедуру, чтобы второй запрос был выполнением, а не проектом.
черновик процедуры
delete from users where id = ?
delete from orders where user_id = ?
Решение
begin;
delete from users where id = :subject; -- профиль, email, телефон
update orders
set customer_ref = 'erased-' || :hash -- обезличить ссылку
where user_id = :subject;
-- сохранить: сумму заказа, дату, позиции (нормативное хранение)
insert into erasure_log (subject, run_at, action) values (:subject, now(), 'erased');
commit;
Удаление не означает удалить заказ: транзакция нужна бухгалтерии, а персональные поля внутри неё — нет, поэтому ссылка заменяется надгробием, а агрегат остаётся. Если написать процедуру и её журнал скриптом, следующий запрос даст доказательство того, что было удалено или сохранено. Обычная ошибка — забыть неизменяемые копии: резервные копии, журналы только для добавления и потоки событий возвращают данные после восстановления, если не применять список надгробий при восстановлении.