В чем преимущество выполнения логического / мягкого удаления записи (т. Е. Установки флага, указывающего, что запись удалена) по сравнению с фактическим или физическим удалением записи?
Это обычная практика?
Это безопасно?
@DaveJarvis, можете ли вы объяснить, почему использование временных меток - лучший подход к флагам?
Флаг не предоставляет никакой информации о когда, строка была удалена. Временная информация имеет множество применений, включая системную отладку.
Я мягкое удаление не добавляет полезных данных аудита. Если вы намереваетесь создать историю аудита, создайте дополнительную таблицу, ориентированную на это намерение. Он может даже хранить предыдущие версии и не делает разработку и создание отчетов серьезной проблемой.


Преимущества в том, что вы храните историю (что удобно для аудита), и вам не нужно беспокоиться о каскадном удалении через различные другие таблицы в базе данных, которые ссылаются на строку, которую вы удаляете. Недостатком является то, что вам нужно закодировать любые методы отчетности / отображения, чтобы учитывать флаг.
Насколько это обычная практика - я бы сказал, что да, но, как и во всем, что вы используете, зависит от потребностей вашего бизнеса.
Обновлено: Мысль о другом недостатке - если у вас есть уникальные индексы в таблице, удаленные записи по-прежнему будут занимать «одну» запись, поэтому вам также придется закодировать эту возможность (например, таблица User с уникальным индексом на имя пользователя; удаленная запись по-прежнему будет блокировать имя пользователя удаленных пользователей для новых записей. Обходя это, вы можете привязать GUID к столбцу удаленного имени пользователя, но это очень хитрый обходной путь, который я бы не рекомендовал. Вероятно, в таких обстоятельствах это было бы Лучше просто иметь правило, согласно которому одноразовое имя пользователя никогда не может быть заменено.)
Отображать как активных / деактивированных пользователей =) С другой стороны, если это уникальный индекс (при условии, что вы имеете в виду, что база данных контролирует уникальный индекс), что вы имеете в виду - он все равно будет блокировать имя пользователя удаленных пользователей для новых записей ??
@CodeBlend - как я описал выше, если у вас есть таблица User с уникальным индексом в столбце Username, то если вы выполните мягкое / логическое удаление пользователя с именем «Chris Shaffer», то это имя пользователя не станет доступным для нового пользователь, с которым нужно создать новую учетную запись, тогда как если вы сделали жесткое / физическое удаление, имя пользователя снова будет доступно.
Ах, я думал в терминах строки, а не имени пользователя (имени пользователя). Если вы хотите сохранить полную историю, поэтому, если был «заказ» или что-то, связанное с этим пользователем, вам необходимо выполнить мягкое / логическое удаление.
@ChrisShaffer В качестве альтернативы вместо GUID можно выбрать индексирование только не удаленных строк. Например: CREATE UNIQUE INDEX ... WHERE DELETED_AT is null (в PostgreSQL), и тогда все строки с любой датой удаления не индексируются. (Вместо этого они могут быть включены в неуникальный индекс.)
@Chris Shaffer: Цитата: «Вам не нужно беспокоиться о каскадном удалении через различные другие таблицы». Неправда, вам придется пересылать мягкое удаление вручную, что является большой головной болью и вызывает несоответствия. На самом деле это недостаток, потому что больше не применяется принудительная связь с внешним ключом. Очень скоро вы получите мусор данных.
@Chris Shaffer: Цитата: «Вы храните историю (хорошо для аудита)». Опять же, нет. Если я обновляю (или случайно обновляю через SSMS) значения в таблице, у вас не будет записи старого значения. Если я случайно удалю (реальным удалением) строку, у вас тоже не останется записи. Мягкое удаление не может заменить аудит.
@KajMagnus: Это не кажется хорошей идеей в контексте, поскольку, если ключ будет повторно использован, все записи в связанных таблицах будут связаны с новой строкой !!?!
@BenVoigt Если проблема в том, что связанные таблицы становятся "связанный с новой строкой", я бы счел это ошибкой. - Не индексируется, например. имя пользователя безопасно, например в данном случае: таблица пользователей, PK - идентификатор пользователя (число). Имена пользователей должны быть уникальными, и можно повторно использовать удаленные имена пользователей. Тогда имеет смысл вести записи об удаленных пользователях для целей аудита. - Например, Twitter позволяет вам повторно использовать другое имя пользователя, но для этого требуется несколько административных шагов (вам нужно связаться с Twitter и попросить раскрыть имя пользователя (которое должно быть неактивным) и пояснить, почему).
@BenVoigt Повторное использование адреса электронной почты удаленного пользователя может быть лучшим примером, если адреса электронной почты не отображаются публично (поэтому их повторное использование не вызывает путаницы, как это может сделать повторное использование имен пользователей), а используется только для связи с пользователем. Возможно, вам понадобится ПК только для активных адресов электронной почты пользователей и разрешить пользователю удалить своего текущего пользователя и создать нового с тем же адресом электронной почты.
@KajMagnus: О, я перешел от «в этом ответе говорится об избежании каскадных удалений» к «столбец используется как ключ для отношений между таблицами». Но, конечно, можно, чтобы столбец уникального индексированного имени пользователя был отделен от первичного ключа; Я не думал об этом.
«Ошибка: сбой ограничения внешнего ключа» и контрольный журнал. Место на диске дешевое, найти потерянную историю не так уж и много.
Для случая использования повторного использования имен пользователей в вашем EDIT, вероятно, было бы лучше закодировать это в бизнес-логике, учитывая, насколько сложными и динамичными могут быть требования к продукту.
Ограничения заключаются в обеспечении соблюдения логики. Условия гонки могут сделать недействительными проверки, выполняемые в бизнес-логике.
Я обычно использую логические удаления - я считаю, что они хорошо работают, когда вы также периодически архивируете «удаленные» данные в заархивированной таблице (в которой можно выполнять поиск при необходимости), таким образом, не имея возможности повлиять на производительность приложения.
Это хорошо работает, потому что у вас все еще есть данные, если вы когда-либо проходили аудит. Если удалить физически, это ушло!
Я большой поклонник логического удаления, особенно для бизнес-приложений или в контексте учетных записей пользователей. Мои причины просты: часто я не хочу, чтобы пользователь мог больше использовать систему (поэтому учетная запись помечается как удаленная), но если мы удалим пользователя, мы потеряем всю его работу и тому подобное.
Другой распространенный сценарий состоит в том, что пользователи могут быть воссозданы через некоторое время после удаления. Для пользователя гораздо приятнее иметь все свои данные в том виде, в котором они были до удаления, а не создавать их заново.
Я обычно думаю об удалении пользователей скорее как о «приостановке» их на неопределенный срок. Никогда не знаешь, когда им законно нужно будет вернуться.
Разве мы не должны использовать здесь что-то вроде активации / деактивации учетной записи вместо логического удаления? @ jon-dewees
Один из распространенных шаблонов для этого - создание двухуровневой структуры пользовательских данных. Таким образом, у пользователя будет учетная запись для входа, в которой вы можете выполнять единый вход с другой системой, и есть еще одна системная учетная запись, которая связана со всеми бизнес-записями. Вы можете удалить учетную запись пользователя первого уровня, сохранив при этом возможность повторно связать нижнюю системную учетную запись позже, если это необходимо.
Логические удаления, если это плохо для ссылочной целостности.
Это правильное решение, когда есть временной аспект данных таблицы (действительны FROM_DATE - TO_DATE).
В противном случае переместите данные в таблицу аудита и удалите запись.
С положительной стороны:
Это наиболее простой способ отката (если это вообще возможно).
Легко увидеть, каким было состояние в определенный момент времени.
Re: "Это безопасно?" - это зависит от того, что вы имеете в виду.
Если вы имеете в виду, что, выполняя физическое удаление, вы получите запретить кому-либо найти удаленные данные, тогда да, это более или менее верно; вам будет безопаснее физически удалить конфиденциальные данные, которые необходимо стереть, потому что это означает, что они навсегда исчезнут из базы данных. (Однако имейте в виду, что могут быть другие копии данных, о которых идет речь, например, в резервной копии, или в журнале транзакций, или в записанной версии в пути, например, сниффер пакетов - только потому, что вы удаляете из своей базы данных, это не гарантия, что он не был сохранен где-то еще.)
Если вы имеете в виду, что, выполняя логическое удаление, ваши данные более безопасны, потому что ты никогда не потеряешь данные, это тоже верно. Это хорошо для сценариев аудита; Я склоняюсь к такому дизайну, потому что он признает основной факт, что после генерации данных В самом деле никогда не исчезнет (особенно, если он когда-либо имел возможность кэшироваться, скажем, поисковой системой в Интернете). Конечно, реальный сценарий аудита требует, чтобы не только удаления были логичными, но и чтобы обновления регистрировались вместе с указанием времени изменения и исполнителя, внесшего изменение.
Если вы имеете в виду, что данные не попадут в руки тех, кто не должен их видеть, то это полностью зависит от вашего приложения и его структуры безопасности. В этом отношении логическое удаление не более и менее безопасно, чем что-либо еще в вашей базе данных.
Это довольно стандартно в случаях, когда вы хотите вести историю чего-либо (например, учетные записи пользователей, как упоминает @Jon Dewees). И это, безусловно, отличная идея, если есть большая вероятность, что пользователи попросят отменить удаление.
Если вас беспокоит, что логика фильтрации удаленных записей из ваших запросов становится беспорядочной и просто усложняет ваши запросы, вы можете просто создать представления, которые выполняют фильтрацию за вас и использовать запросы против этого. Это предотвратит утечку этих записей в решениях для отчетности и тому подобное.
Являются ли логические удаления обычной практикой? Да, я видел это во многих местах. Они в безопасности? Это действительно зависит от того, являются ли они менее безопасными, чем были данные до того, как вы их удалили?
Когда я был техническим руководителем, я требовал, чтобы наша команда хранила все данные, в то время я знал, что мы будем использовать все эти данные для создания различных приложений бизнес-аналитики, хотя в то время мы не знали, какие требования будут быть. Хотя это было хорошо с точки зрения аудита, устранения неполадок и отчетности (это был сайт электронной коммерции / инструментов для транзакций B2B, и если кто-то использовал инструмент, мы хотели записать его, даже если его учетная запись позже была отключена), у него было несколько недостатков.
К недостаткам относятся (не считая уже упомянутых):
Решая использовать логическое, физическое удаление или архивирование, я задавал себе следующие вопросы:
В примере с вашими учетными записями пользователей было бы хорошо хранить активных и неактивных пользователей в отдельных таблицах? Например. Таблица Activated и схема таблицы Deactivated - Строка Id,Name,etc.. в Activated - 1001,Smith007,etc... Когда он деактивирован, мы можем очистить все, кроме столбца идентификатора, для smith в Activated и добавить его в Deactivated.
Какая польза от перемещения всех данных, если вы собираетесь оставить идентификатор и строку? Может быть, если ваш рекорд огромен, но я бы посмотрел на это как на микрооптимизацию.
Удачи с каскадными ограничениями внешнего ключа, если вы перемещаете данные по таблицам.
Они не позволяют базе данных работать должным образом, делая бесполезными такие вещи, как каскадная функциональность.
Для простых вещей, таких как вставки, в случае повторной вставки код, стоящий за ней, удваивается.
Вы не можете просто вставить, вместо этого вы должны проверить наличие и вставить, если он не существует раньше, или обновить флаг удаления, если он есть, одновременно обновляя все другие столбцы до новых значений. Это рассматривается как обновление журнала транзакций базы данных, а не как новая вставка, вызывающая неточные журналы аудита.
Они вызывают проблемы с производительностью, потому что таблицы забиваются избыточными данными. Он играет хаотично с индексацией, особенно с уникальностью.
Я не большой поклонник логических удалений.
Возможно, уже немного поздно, но я предлагаю всем проверить Сообщение в блоге Пинала Дэйва на предмет логического / мягкого удаления:
I just do not like this kind of design [soft delete] at all. I am firm believer of the architecture where only necessary data should be in single table and the useless data should be moved to an archived table. Instead of following the isDeleted column, I suggest the usage of two different tables: one with orders and another with deleted orders. In that case, you will have to maintain both the table, but in reality, it is very easy to maintain. When you write UPDATE statement to the isDeleted column, write INSERT INTO another table and DELETE it from original table. If the situation is of rollback, write another INSERT INTO and DELETE in reverse order. If you are worried about a failed transaction, wrap this code in TRANSACTION.
What are the advantages of the smaller table verses larger table in above described situations?
- A smaller table is easy to maintain
- Index Rebuild operations are much faster
- Moving the archive data to another filegroup will reduce the load of primary filegroup (considering that all filegroups are on different system) – this will also speed up the backup as well.
- Statistics will be frequently updated due to smaller size and this will be less resource intensive.
- Size of the index will be smaller
- Performance of the table will improve with a smaller table size.
как бы вы позаботились о внешних ключах, используя такой метод? Может быть 1, 10 или более других таблиц, которые ссылаются на удаляемую запись и перемещаются в другую таблицу!
@ sam360 - это большая проблема. Честно говоря, мне лично не удалось реализовать вышеприведенную рекомендацию в своих проектах из-за обработки PK и связи между таблицами. К сожалению, в этой статье не было реального примера. Я работаю над решением в одном из своих проектов, если получится хорошая реализация, я поделюсь с вами кодом ...
как это называется ? вместо мягкого удаления?
@eugene - я не знаю конкретного термина для этого решения. Это подход действительно «удаляет» строки и сохраняет удаленные записи в «архивной» таблице, если он вам понятен.
@Tohid: Я реализовал себя с помощью django, вы можете взглянуть на мои работы. stackoverflow.com/a/34447879/433570
Я считаю, что «перемещение архивных данных в другую файловую группу» может быть реализовано как разделы в Oracle, так что можно получить перечисленные выше преимущества ...
ясно, что парень никогда не разрабатывал механизм синхронизации между несколькими устройствами
Я настоятельно рекомендую не согласен с логическим удалением, потому что вы подвержены множеству ошибок.
Прежде всего, каждый запрос должен обрабатывать поле IsDeleted, и вероятность ошибки возрастает при сложных запросах.
Во-вторых, производительность: представьте себе таблицу со 100000 записей и только 3 активными, теперь умножьте это число на таблицы вашей базы данных; Еще одна проблема производительности - это возможный конфликт новых записей со старыми (удаленными записями).
Единственное преимущество, которое я вижу, - это история записей, но есть и другие методы для достижения этого результата, например, вы можете создать таблицу регистрации, в которой вы можете сохранить информацию: TableName,OldValues,NewValues,Date,User,[..], где *Values может быть varchar, и записать детали в этой форме. fieldname : value; [..] или сохраните информацию как xml.
Все это может быть достигнуто с помощью кода или триггеров, но вы всего лишь таблица ОДИН со всей вашей историей. Другой вариант - проверить, поддерживает ли указанный механизм базы данных встроенную поддержку отслеживания изменений, например, в базе данных SQL Server есть изменение данных отслеживания SQL.
Мягкое удаление - это практика программирования, которой придерживаются в большинстве приложений, когда данные более актуальны. Рассмотрим случай финансового приложения, в котором удаление по ошибке конечного пользователя может быть фатальным. Это тот случай, когда становится актуальным мягкое удаление. При мягком удалении пользователь фактически не удаляет данные из записи, вместо этого они помечаются как IsDeleted равными истине (по обычному соглашению).
В EF 6.x или EF 7 и далее Softdelete добавлен в качестве атрибута, но на данный момент мы должны создать настраиваемый атрибут.
Я настоятельно рекомендую SoftDelete в дизайне базы данных, и это хорошее соглашение для практики программирования.
Есть требования, выходящие за рамки системного проектирования, на которые необходимо ответить. Каковы юридические или законодательные требования к хранению записей? В зависимости от того, к чему относятся строки, может существовать юридическое требование, чтобы данные хранились в течение определенного периода времени после их «приостановки».
С другой стороны, требование может заключаться в том, чтобы после «удаления» записи она действительно и безвозвратно удалялась. Прежде чем принять решение, поговорите со своими заинтересованными сторонами.
Я разработчик NoSQL, и на моей последней работе я работал с данными, которые всегда были важны для кого-то, и если они были случайно удалены в тот же день, что и были созданы, я не смог найти их в последней резервной копии со вчерашнего дня! В этой ситуации мягкое удаление всегда спасало положение.
Я выполнил мягкое удаление с использованием временных меток, зарегистрировав дату удаления документа:
IsDeleted = 20150310 //yyyyMMdd
Каждое воскресенье процесс просматривал базу данных и проверял поле IsDeleted. Если разница между текущей датой и отметкой времени была больше N дней, документ был удален без возможности восстановления. Учитывая, что документ все еще доступен в некоторой резервной копии, это было безопасно.
Обновлено: Этот вариант использования NoSQL касается больших документов, создаваемых в базе данных, десятки или сотни из них каждый день, но не тысячи или миллионы. Как правило, это были документы со статусом, данными и вложениями рабочих процессов. Это было причиной того, что пользователь мог удалить важный документ. Этим пользователем может быть кто-то с правами администратора или, возможно, владелец документа, и это лишь некоторые из них.
TL; DR Моим вариантом использования не были большие данные. В этом случае вам потребуется другой подход.
Хорошо! Как все говорили, это зависит от ситуации.
Если у вас есть индекс для столбца, такого как UserName или EmailID, и вы никогда не ожидаете, что то же UserName или EmailID будут использоваться снова; вы можете пойти с мягким удалением.
Тем не менее, всегда проверяйте, использует ли ваша операция SELECT первичный ключ. Если ваш оператор SELECT использует первичный ключ, добавление флага с предложением WHERE не будет иметь большого значения. Возьмем пример (Псевдо):
Таблица Users (UserID [первичный ключ], EmailID, IsDeleted)
SELECT * FROM Users where UserID = 123456 and IsDeleted = 0
Этот запрос не будет иметь никакого значения с точки зрения производительности, поскольку столбец UserID имеет первичный ключ. Сначала он просканирует таблицу на основе PK, а затем выполнит следующее условие.
Случаи, когда мягкое удаление не работает вообще:
Регистрация практически на всех веб-сайтах принимает EmailID в качестве вашего уникального идентификатора. Мы очень хорошо знаем, что если EmailID используется на таких веб-сайтах, как facebook, G +, он не может использоваться кем-либо еще.
Наступает день, когда пользователь хочет удалить свой профиль с сайта. Теперь, если вы сделаете логическое удаление, этот пользователь больше не сможет зарегистрироваться. Кроме того, повторная регистрация с использованием того же адреса электронной почты не означает восстановления всей истории. Всем известно, что удаление означает удаление. В таких сценариях мы должны выполнить физическое удаление. Но для того, чтобы поддерживать всю историю учетной записи, мы всегда должны архивировать такие записи либо в архивных таблицах, либо в удаленных таблицах.
Да, в ситуациях, когда у нас много сторонних таблиц, обработка оказывается довольно громоздкой.
Также имейте в виду, что мягкое / логическое удаление увеличит размер вашей таблицы, поэтому размер индекса.
Мобильные приложения, зависящие от синхронизации, могут требовать использования логического, а не физического удаления: сервер должен иметь возможность указать клиенту, что запись была (помечена как) удалена, а это может быть невозможно, если записи были удалены физически.
Раньше я делал мягкое удаление, просто чтобы сохранить старые записи. Я понял, что пользователи не так часто просматривают старые записи, как я думал. Если пользователи хотят просматривать старые записи, они могут просто просматривать их из архива или таблицы аудита, верно? Итак, в чем преимущество мягкого удаления? Это только приводит к более сложному запросу и т. д.
Ниже приведены вещи, которые я реализовал до того, как решил больше не удалять мягкое удаление:
внедрить аудит, чтобы записывать все действия (добавление, редактирование, удаление). Убедитесь, что нет внешнего ключа, связанного с аудитом, и убедитесь, что эта таблица защищена и никто не может удалить, кроме администраторов.
определить, какие таблицы считаются «транзакционной таблицей», которая, скорее всего, будет храниться в течение длительного времени, и, скорее всего, пользователь может захотеть просмотреть прошлые записи или отчеты. Например; сделка покупки. Эта таблица должна не только содержать идентификатор главной таблицы (например, dept-id), но также содержать дополнительную информацию, такую как имя в качестве ссылки (например, dept-name), или любые другие поля, необходимые для отчетности.
Реализуйте «активный / неактивный» или «включить / выключить» или «скрыть / показать» запись главной таблицы. Таким образом, вместо удаления записи пользователь может отключить / деактивировать основную запись. Так намного безопаснее.
Просто мое мнение за два цента.
Один из шаблонов, которые я использовал, - это создать зеркальную таблицу и прикрепить триггер к основной таблице, чтобы все удаления (и обновления, если необходимо) записывались в зеркальную таблицу.
Это позволяет вам «восстанавливать» удаленные / измененные записи, и вы по-прежнему можете жестко удалить в основной таблице и сохранить ее «чистой» - это также позволяет создавать функцию «отменить», и вы также можете записывать дату и время. , и пользователь, который выполнил действие в зеркальной таблице (бесценно в ситуациях охоты на ведьм).
Другое преимущество заключается в том, что нет возможности случайно включить удаленные записи при запросе с основного сервера, если только вы намеренно не возьмете на себя труд включить записи из зеркальной таблицы (вы можете захотеть показать текущие и удаленные записи).
Еще одно преимущество состоит в том, что зеркальную таблицу можно очищать независимо, поскольку она не должна иметь никаких фактических ссылок на внешние ключи, что делает эту операцию относительно простой по сравнению с очисткой из первичной таблицы, которая использует мягкое удаление, но все же имеет ссылочные соединения с другими таблицами.
Какие еще преимущества? - отлично, если у вас есть группа кодеров, работающих над проектом, читающих базу данных со смешанными навыками и вниманием к уровням детализации, вам не нужно спать по ночам в надежде, что один из них не забыл не включить удаленные записи (смеется, не включать удаленные записи = True), что приводит к таким вещам, как завышение, скажем, доступной денежной позиции клиентов, с которой они затем покупают акции (например, как в торговой системе), когда вы работаете с торговыми системами, вы очень быстро узнаете ценность надежных решений, даже если они могут иметь немного больше начальных «накладных расходов».
Исключения:
- в качестве руководства используйте мягкое удаление для «справочных» данных, таких как пользователь, категория и т. д., и жесткое удаление в зеркальной таблице для данных типа «факт», т. е. истории транзакций.
Чтобы ответить на комментарий Тохида, мы столкнулись с той же проблемой, когда мы хотели сохранить историю записей, а также мы не были уверены, нужна ли нам колонка is_deleted или нет.
Я говорю о нашей реализации на Python и аналогичном сценарии использования, который мы затронули.
Мы столкнулись с https://github.com/kvesteri/sqlalchemy-continuum, который представляет собой простой способ получить таблицу управления версиями для соответствующей таблицы. Минимум строк кода и история захвата для добавления, удаления и обновления.
Это не просто колонка is_deleted. Вы всегда можете обратиться к таблице версий, чтобы проверить, что произошло с этой записью. Была ли запись удалена, обновлена или добавлена.
Таким образом, нам вообще не нужно было иметь столбец is_deleted, а наша функция удаления была довольно тривиальной. Таким образом, нам также не нужно помнить о маркировке is_deleted=False ни в одном из наших API.
В большинстве случаев мягкое удаление используется, потому что вы не хотите раскрывать некоторые данные, но вы должны сохранить их по историческим причинам (продукт может быть прекращен, поэтому вы не хотите никаких новых транзакций с ним, но вам все равно нужно работать с история сделки купли-продажи). Кстати, некоторые копируют значение информации о продукте в данные транзакции продажи вместо того, чтобы делать ссылку на продукт, чтобы справиться с этим.
На самом деле это больше похоже на переформулировку видимой / скрытой или активной / неактивной функции. Потому что это значение слова «удалить» в деловом мире. Я хочу сказать, что Терминаторы могут удалять людей, а босс их просто увольняет.
Эта практика является довольно распространенным шаблоном и используется во многих приложениях по разным причинам. Поскольку это не единственный способ добиться этого, у вас будут тысячи людей, которые будут говорить, что это здорово или чушь, и у обоих есть довольно хорошие аргументы.
С точки зрения безопасности SoftDelete не заменит работу аудита, а также не заменит работу резервного копирования. Если вы опасаетесь «вставки / удаления между двумя вариантами резервного копирования», вам следует прочитать о моделях полного или массового восстановления. Я допускаю, что SoftDelete может сделать процесс восстановления более тривиальным.
До вас знать ваши требования.
В качестве альтернативы у нас есть пользователи, использующие удаленное обновление устройств через MobiLink. Если мы удалим записи в базе данных сервера, эти записи никогда не будут помечены как удаленные в клиентских базах данных.
Итак, мы делаем и то, и другое. Мы работаем с нашими клиентами, чтобы определить, как долго они хотят иметь возможность восстанавливать данные. Например, обычно клиенты и продукты активны до тех пор, пока наш клиент не скажет, что они должны быть удалены, но история продаж сохраняется только в течение 13 месяцев, а затем удаляется автоматически. Клиент может пожелать сохранить удаленных клиентов и продукты в течение двух месяцев, но сохранить историю в течение шести месяцев.
Таким образом, мы запускаем скрипт в течение ночи, который помечает вещи, которые логически удалены в соответствии с этими параметрами, а затем через два / шесть месяцев все, что было отмечено логически удаленным сегодня, будет удалено без возможности восстановления.
Мы не столько заботимся о безопасности данных, сколько о наличии огромных баз данных на клиентском устройстве с ограниченной памятью, таком как смартфон. У клиента, который заказывает 200 товаров дважды в неделю в течение четырех лет, будет более 81 000 строк истории, из которых 75% клиента не волнует, увидит ли он.
Все зависит от варианта использования системы и ее данных.
Например, если вы говорите о регулируемой государством системе (например, система в фармацевтической компании, которая считается частью системы качества и должна следовать рекомендациям FDA в отношении электронных записей), то вам, черт возьми, лучше не выполнять жесткое удаление! Аудитор из FDA может прийти и запросить все записи в системе, относящиеся к номеру продукта ABC-123, и все данные будут лучше доступны. Если владелец бизнес-процесса говорит, что система не должна позволять никому использовать номер продукта ABC-123 для новых записей в будущем, используйте вместо этого метод мягкого удаления, чтобы сделать его «неактивным» в системе, сохраняя при этом исторические данные.
Однако, возможно, ваша система и ее данные имеют такой вариант использования, как «отслеживание погоды на Северном полюсе». Возможно, вы измеряете температуру один раз в час и в конце дня суммируете среднесуточное значение. Возможно, почасовые данные больше не будут использоваться после агрегирования, и вы бы жестко удалили почасовые показания после создания агрегата. (Это выдуманный тривиальный пример.)
Дело в том, что все зависит от варианта использования системы и ее данных, а не от решения, которое следует принимать исключительно с технологической точки зрения.
Я почти всегда мягко удаляю, и вот почему:
isdeleted повсюду не является проблемой, вы все равно должны проверять наличие userid (если база данных содержит данные от нескольких пользователей). Вы можете принудительно выполнить проверку с помощью кода, поместив эти две проверки в отдельную функцию (или используя представления)@Jim сохраняет данные в базе данных, это не незаконно. это незаконно, если вы храните записи даже после того, как клиент сказал вам удалить его собственные данные. Мягкое удаление полностью совместимо с GDPR: по запросу просто замените разумные данные пустыми. Более того, если пользователь удаляет запись, он может захотеть отменить действие в будущем или каким-то образом восстановить данные ... это не означает, что он / она хочет, чтобы данные полностью исчезли из базы данных.
Я уже ответил в другом посте. Однако я думаю, что мой ответ больше подходит для поставленного здесь вопроса.
My practical solution for soft-delete is archiving by creating a new table with following columns:
original_id,table_name,payload, (and an optional primary key `id).Where
original_idis the original id of deleted record,table_nameis the table name of the deleted record ("user"in your case),payloadis JSON-stringified string from all columns of the deleted record.I also suggest making an index on the column
original_idfor latter data retrievement.By this way of archiving data. You will have these advantages
- Keep track of all data in history
- Have only one place to archive records from any table, regardless of the deleted record's table structure
- No worry of unique index in the original table
- No worry of checking foreign index in the original table
- No more
WHEREclause in every query to check for deletionThe is already a discussion here explaining why soft-deletion is not a good idea in practice. Soft-delete introduces some potential troubles in future such as counting records, ...
Я написал сообщение в блоге обо всех способах удаления данных transang.me/database-design-practice-soft-deletion-to
Приключения - это сохранение / увековечение данных. Несоответствие - снижение производительности при запросе или извлечении данных из таблиц со значительным количеством мягких удалений. В нашем случае мы используем комбинацию обоих: как другие упоминали в предыдущих ответах, мы, например, soft-deleteusers/clients/customers и hard-delete в таблицах items/products/merchandise, где есть дублированные записи, которые не нужно хранить.
Это зависит от случая, обратите внимание на следующее:
Обычно не требуется "мягкое удаление" записи. Сделайте это просто и быстро. например Удаление продукта, который больше не доступен, поэтому вам не нужно проверять, не удален ли продукт по всему приложению (счетчик, список продуктов, рекомендуемые продукты и т. д.).
Тем не менее, вы можете рассмотреть возможность «мягкого удаления» в модели хранилища данных. например Вы просматриваете старую квитанцию об удаленном продукте. *
Я просто хотел подробнее остановиться на упомянутой проблеме уникальное ограничение.
Предположим, у меня есть таблица с двумя столбцами: id и my_column.. Для поддержки мягких удалений мне нужно обновить определение таблицы следующим образом:
create table mytable (
id serial primary key,
my_column varchar unique not null,
deleted_at datetime
)
Но если строка мягко удалена, я хочу, чтобы ограничение my_column игнорировалось, потому что удаленные данные не должны мешать не удаленным данным. Моя оригинальная модель не подойдет.
Мне нужно будет обновить определение данных до следующего:
create table mytable (
id serial primary key,
my_column varchar not null,
my_column_repetitions integer not null default 0,
deleted_at datetime,
unique (my_column, my_column_repetitions),
check (deleted_at is not null and my_column_repetitions > 0 or deleted_at is null and my_column_repetitions = 0)
)
И примените эту логику: когда строка является текущей, то есть не удаленной, my_column_repetitions должен содержать значение по умолчанию 0, а когда строка мягко удалена, ее my_column_repetitions необходимо обновить до (max. number of repetitions on soft-deleted rows) + 1..
Последняя логика должна быть реализована программно с помощью триггера или обрабатываться в моем коде приложения, и я не могу установить проверку.
Повторите это для каждого уникального столбца!
Я думаю, что это решение действительно хакерское и предпочло бы отдельную таблицу архив для хранения удаленных строк.
Используйте метки времени удаления, а не флаги.