Я хотел бы реализовать функцию «восстановить» в веб-приложении, чтобы пользователь мог передумать и восстановить удаленную запись. Мысли о том, как это реализовать? Некоторые варианты, которые я рассмотрел, на самом деле - удаление рассматриваемой записи и сохранение изменений в отдельной таблице аудита, или не удаление записи и использование логического столбца «удалено», чтобы пометить ее как удаленную. Последнее решение потребовало бы дополнительной логики приложения, чтобы игнорировать «удаленные» записи при нормальных обстоятельствах, но значительно упростило бы процесс восстановления записей на стороне приложения.
44
Ответы:
Да, я бы определенно выбрал второй вариант, но я бы добавил еще одно поле в поле даты.
Итак, вы добавляете:
Это позволило бы вам дать время для восстановления действий.
Если время меньше часа, можно восстановить.
Чтобы действительно удалить удаленную запись, просто создайте хранимую процедуру, которая будет очищать каждую запись с удалением, установленным в значение true, и временем, превышающим один час, и помещать ее как вкладку cron, которая запускается каждые 24 часа.
Час это только пример.
источник
cleaned
или что-то - что указывает на то, что данные, связанные с этой записью, были правильно, полностью удалены. Запись может быть восстановлена, еслиcleaned
она не истинна, и в этом случае она не подлежит восстановлению .deleted_at
содержащее как семантикуdelete
логического значения, так иdelete_date
метку времени. Если дескрипторdeleted_at
is,NULL
регистрdelete
естьFALSE
иdelete_date
естьNULL
,deleted_at
содержит дескриптор метки времени, регистрdelete
isTRUE
иdelete_date
содержит метку времени, экономя время, память и логику приложения.deleted
поле может значительно повысить производительность, когда вы запрашиваете не удаленные строкиВ наших приложениях мы действительно ничего не удаляем по запросу пользователей в любом случае (наши клиенты находятся в регулируемой среде, где удаление чего-либо может потенциально привести к юридическим проблемам).
Мы храним старые версии в отдельной таблице аудита (поэтому для таблицы some_table где также есть таблица с именем some_table_audit), которая идентична тому, что имеет дополнительный идентификатор версии (временную метку, если ваша БД поддерживает временные значения достаточно гранулярно, целочисленный номер версии или UUID, который является внешним ключом к общей таблице аудита, и т. д.), и обновлять таблицу аудита автоматически по триггеру (поэтому нам не нужно сообщать весь код, который обновляет записи, о требовании аудита).
Сюда:
Если вы используете временную метку вместо (или вместе с ней) целочисленного номера версии, вы можете использовать ее для удаления более старых копий через определенное время, если это необходимо. Но дисковое пространство в наши дни относительно дешевое, поэтому, если у нас нет причин удалять старые данные (например, правила защиты данных, согласно которым вы должны удалять клиентские данные через X месяцев / лет), мы бы этого не сделали.
Этот ответ был около нескольких лет, и несколько ключевых вещей, которые могли повлиять на такого рода планирование, изменились с тех пор. Я не буду вдаваться в подробности, но вкратце в пользу людей, читающих это сегодня:
SQL Server 2016 представил «временные таблицы с системными версиями», которые выполняют большую часть этой работы за вас, и, кроме того, предоставляется некоторый приятный синтаксический сахар для упрощения создания и поддержки исторических запросов, и они координируют подмножество изменений схемы между таблицы базы и истории. Они не без своих предостережений, но они являются мощным инструментом для такого рода целей. Аналогичные функции также доступны в других системах БД.
Изменения в законодательстве о защите данных, в частности введение GDPR, могут существенно изменить вопрос о том, когда данные должны быть жестко удалены. Вы должны взвесить баланс, чтобы не удалять данные, которые могут быть полезны (или действительно необходимы по закону) для целей аудита на более позднем этапе, против необходимости уважать права людей (как в целом, так и в соответствии с конкретными положениями соответствующего законодательства) при рассмотрении ваши проекты. Это может быть проблемой с системными версионными временными таблицами, поскольку вы не можете изменить историю, чтобы очистить личные данные без кратковременных изменений схемы, чтобы отключить отслеживание истории, пока вы вносите изменения.
источник
С удаленным логическим столбцом у вас начнутся проблемы, если ваша таблица начнет расти и станет действительно большой. Я предлагаю вам перемещать удаленные столбцы один раз в неделю (более или менее в зависимости от ваших спецификаций) в другую таблицу. Таким образом, у вас есть хорошая маленькая активная таблица и большая таблица, содержащая все записи, собранные с течением времени.
источник
Я бы пошел с отдельной таблицей. В Ruby on Rails есть
acts_as_versioned
плагин, который в основном сохраняет строку в другой таблице с постфиксом,_version
прежде чем обновляет его. Хотя вам не нужно такое точное поведение, оно также должно работать для вашего случая (скопируйте перед удалением).Как и @Spredzy, я бы также порекомендовал добавить
delete_date
столбец, чтобы иметь возможность программно очищать записи, которые не были восстановлены после X часов / дней / чего бы то ни было.источник
Решение, которое мы используем для этого внутри компании, состоит в том, чтобы иметь столбец состояния с некоторыми жестко закодированными значениями для некоторых конкретных состояний объекта: Удаленный, Активный, Неактивный, Открытый, Закрытый, Заблокированный - каждый статус с некоторым значением, используемым в приложении. С точки зрения БД мы не удаляем объекты, мы просто меняем статус и храним историю каждого изменения в таблице объектов.
источник
Когда вы говорите, что «последнее решение потребует дополнительной логики приложения, чтобы игнорировать« удаленные »записи», простое решение - иметь представление, которое отфильтровывает их.
источник
Подобно тому, что предложил Spredzy, мы используем поле метки времени для удаления во всех наших приложениях. Логическое значение излишне, так как установленная метка времени указывает, что запись была удалена. Таким образом, наш PDO всегда добавляет
AND (deleted IS NULL OR deleted = 0)
к операторам выбора, если модель явно не запрашивает включение удаленных записей.В настоящее время мы не занимаемся сборкой мусора ни для каких таблиц, кроме таблиц, содержащих двоичные объекты или тексты; пространство является тривиальным, если записи хорошо нормализованы, а индексирование
deleted
поля оказывает ограниченное влияние на скорость выбора.источник
В качестве альтернативы вы можете возложить ответственность на пользователей (и разработчиков) и перейти к последовательности «Вы уверены?», «Вы определенно уверены?» и "Вы абсолютно, хорошо и действительно уверены?" вопросы до удаления записи. Мягко шутливый, но стоит задуматься.
источник
Я привык видеть строки таблицы со столбцами типа «DeletedDate», и они мне не нравятся. Само понятие «удалено» заключается в том, что запись не должна была быть сделана в первую очередь. Практически, они не могут быть удалены из базы данных, но я не хочу, чтобы они были с моими горячими данными. Логически удаленные строки, по определению, являются холодными данными, если кто-то специально не хочет видеть удаленные данные.
Кроме того, каждый написанный запрос должен специально исключать их, а индексы также должны их учитывать.
Я хотел бы увидеть изменение на уровне архитектуры базы данных и на уровне приложения: создать схему под названием «удаленный». Каждая определенная пользователем таблица имеет идентичный эквивалент в «удаленной» схеме с дополнительным полем, содержащим метаданные - пользователя, который его удалил и когда. Внешние ключи требуют создания.
Затем, удаление становится вставкой-удалением. Сначала удаляемая строка вставляется в ее «удаленную» копию схемы. Соответствующая строка в основной таблице может быть удалена. Однако необходимо добавить дополнительную логику где-то вдоль линии. Нарушения внешнего ключа могут быть обработаны.
Внешние ключи должны быть правильно обработаны. Это плохая практика, когда логически удаляется строка, но у первичной / уникальной строки есть столбцы в других таблицах, которые на нее ссылаются. Такого не должно быть. Обычное задание может удалять строки вдов (строки, первичные ключи которых не имеют ссылок в других таблицах, несмотря на наличие внешнего ключа. Это, однако, бизнес-логика.
Общее преимущество заключается в сокращении метаданных в таблице и улучшении производительности, которое она приносит. Столбец «deleteDate» говорит, что эта строка на самом деле не должна быть здесь, но для удобства мы оставляем ее там и позволяем SQL-запросу обрабатывать ее. Если копия удаленной строки хранится в «удаленной» схеме, то основная таблица с горячими данными имеет более высокий процент горячих данных (при условии, что они своевременно заархивированы) и меньше ненужных столбцов метаданных. Индексы и запросы больше не должны учитывать это поле. Чем короче размер строки, тем больше строк можно разместить на странице, тем быстрее может работать SQL Server.
Основным недостатком является размер операции. Теперь есть две операции вместо одной, а также дополнительная логика и обработка ошибок. Это может привести к большей блокировке, чем в противном случае потребовалось бы обновление одного столбца. Транзакция удерживает блокировки таблицы дольше, и в ней участвуют две таблицы. Удаление данных о производстве, по крайней мере, по моему опыту, делается редко. Тем не менее, в одной из основных таблиц 7,5% из почти 100 миллионов записей имеют запись в столбце «DeletedDate».
В качестве ответа на вопрос, приложение должно быть осведомлено о «undelete's». Для этого просто нужно сделать то же самое в обратном порядке: вставить строку из «удаленной» схемы в основную таблицу, а затем удалить строку из «удаленной схемы». Опять же, необходима дополнительная логика и обработка ошибок, чтобы избежать ошибок, проблем с внешними ключами и тому подобного.
источник