В чем преимущество выполнения логического / мягкого удаления записи (т. Е. Установки флага, указывающего на то, что запись удалена) по сравнению с фактическим или физическим удалением записи?
Это обычная практика?
Это безопасно?
В чем преимущество выполнения логического / мягкого удаления записи (т. Е. Установки флага, указывающего на то, что запись удалена) по сравнению с фактическим или физическим удалением записи?
Это обычная практика?
Это безопасно?
Ответы:
Преимущества заключаются в том, что вы храните историю (что удобно для аудита), и вам не нужно беспокоиться о каскадном удалении через различные другие таблицы в базе данных, которые ссылаются на строку, которую вы удаляете. Недостатком является то, что вам нужно закодировать любые методы отчетности / отображения, чтобы учитывать флаг.
Что касается обычной практики - я бы сказал, что да, но, как и в случае с чем-либо, то, будете ли вы ее использовать, зависит от потребностей вашего бизнеса.
РЕДАКТИРОВАТЬ: Мысль о другом недостатке - если у вас есть уникальные индексы в таблице, удаленные записи по-прежнему будут занимать «одну» запись, поэтому вам также придется закодировать эту возможность (например, таблица User с уникальным индексом на имя пользователя; удаленная запись все равно будет блокировать имя пользователя удаленных пользователей для новых записей. Обходя это, вы можете привязать GUID к столбцу удаленного имени пользователя, но это очень хакерский обходной путь, который я бы не рекомендовал. Вероятно, в таких обстоятельствах это было бы Лучше просто иметь правило, согласно которому после использования имени пользователя его нельзя будет заменить.)
CREATE UNIQUE INDEX ... WHERE DELETED_AT is null
(в PostgreSQL) и тогда все строки с любой датой удаления не индексируются. (Вместо этого они могут быть включены в неуникальный индекс.)
Являются ли логические удаления обычной практикой? Да, я видел это во многих местах. Они в безопасности? Это действительно зависит от того, являются ли они менее безопасными, чем были данные до того, как вы их удалили?
Когда я был техническим руководителем, я требовал, чтобы наша команда хранила все данные. В то время я знал, что мы будем использовать все эти данные для создания различных приложений бизнес-аналитики, хотя в то время мы не знали, какие требования будут быть. Хотя это было хорошо с точки зрения аудита, устранения неполадок и отчетности (это был сайт электронной коммерции / инструментов для транзакций B2B, и если кто-то использовал инструмент, мы хотели записать его, даже если его учетная запись позже была отключена), у него было несколько недостатков.
К недостаткам относятся (не считая уже упомянутых):
Решая использовать логическое, физическое удаление или архивирование, я задавал себе следующие вопросы:
Activated
таблица и Deactivated
схема таблицы - Id,Name,etc..
Row in Activated
- 1001,Smith007,etc...
Когда он деактивирован, мы можем очистить все столбцы, кроме ID для кузнеца, Activated
и добавить его Deactivated
.
Возможно, уже немного поздно, но я предлагаю всем проверить сообщение в блоге Пиналя Дэйва о логическом / мягком удалении:
Просто мне вообще не нравится такой дизайн [мягкое удаление]. Я твердо верю в архитектуру, в которой только необходимые данные должны быть в одной таблице, а бесполезные данные должны быть перемещены в архивную таблицу. Вместо того, чтобы следовать столбцу isDeleted, я предлагаю использовать две разные таблицы: одну с заказами, а другую с удаленными заказами. В этом случае вам придется обслуживать обе таблицы, но на самом деле поддерживать их очень просто. Когда вы пишете оператор UPDATE в столбец isDeleted, напишите INSERT INTO другую таблицу и УДАЛИТЕ ее из исходной таблицы. Если происходит откат, напишите еще INSERT INTO и DELETE в обратном порядке. Если вас беспокоит неудачная транзакция, оберните этот код в TRANSACTION.
В чем преимущества таблицы меньшего размера по сравнению с таблицей большего размера в описанных выше ситуациях?
- За меньшим столом легко ухаживать
- Операции восстановления индекса выполняются намного быстрее
- Перемещение архивных данных в другую файловую группу снизит нагрузку на основную файловую группу (учитывая, что все файловые группы находятся в другой системе) - это также ускорит резервное копирование.
- Статистика будет часто обновляться из-за меньшего размера, что потребует меньше ресурсов.
- Размер индекса будет меньше
- Производительность стола улучшится при меньшем размере стола.
Я разработчик NoSQL, и на своей последней работе я работал с данными, которые всегда были для кого-то критичными, и если они были случайно удалены в тот же день, что и были созданы, я не смог найти их в последней резервной копии со вчерашнего дня! В этой ситуации мягкое удаление всегда спасало положение.
Я выполнил мягкое удаление с использованием временных меток, зарегистрировав дату удаления документа:
IsDeleted = 20150310 //yyyyMMdd
Каждое воскресенье процесс просматривал базу данных и проверял IsDeleted
поле. Если разница между текущей датой и отметкой времени была больше N дней, документ был удален без возможности восстановления. Учитывая, что документ все еще доступен в некоторой резервной копии, это было безопасно.
РЕДАКТИРОВАТЬ: этот вариант использования NoSQL касается больших документов, создаваемых в базе данных, десятки или сотни из них каждый день, но не тысячи или миллионы. По большому счету, это были документы со статусом, данными и вложениями рабочих процессов. Это было причиной того, что пользователь мог удалить важный документ. Этим пользователем может быть кто-то с правами администратора или, возможно, владелец документа, и это лишь некоторые из них.
TL; DR Моим вариантом использования не были большие данные. В этом случае вам потребуется другой подход.
Один из шаблонов, которые я использовал, - это создание зеркальной таблицы и присоединение триггера к основной таблице, чтобы все удаления (и обновления, если необходимо) записывались в зеркальную таблицу.
Это позволяет вам «восстанавливать» удаленные / измененные записи, и вы по-прежнему можете жестко удалить в основной таблице и сохранить ее «чистой» - это также позволяет создавать функцию «отменить», и вы также можете записывать дату и время. , и пользователь, выполнивший действие в зеркальной таблице (бесценно в ситуациях охоты на ведьм).
Другое преимущество заключается в том, что нет возможности случайно включить удаленные записи при запросе с основного сервера, если только вы не решитесь сознательно включить записи из зеркальной таблицы (вы можете захотеть показать текущие и удаленные записи).
Еще одно преимущество состоит в том, что зеркальную таблицу можно очищать независимо, так как в ней не должно быть реальных ссылок на внешние ключи, что делает эту операцию относительно простой по сравнению с очисткой из первичной таблицы, которая использует мягкое удаление, но все же имеет ссылочные соединения с другими таблицами.
Какие еще преимущества? - отлично, если у вас есть группа кодировщиков, работающих над проектом, которые читают базу данных со смешанными навыками и вниманием к уровням детализации, вам не нужно спать по ночам, надеясь, что один из них не забыл не включить удаленное записей (смеется, не включать удаленные записи = True), что приводит к таким вещам, как завышение, скажем, доступная денежная позиция клиентов, с которой они затем покупают некоторые акции (например, как в торговой системе), когда вы работаете с торговыми системами, вы очень быстро узнает ценность надежных решений, даже если они могут иметь немного больше начальных "накладных расходов".
Исключения:
- в качестве руководства используйте мягкое удаление для «справочных» данных, таких как пользователь, категория и т. Д., И жесткое удаление в зеркальной таблице для данных типа «факт», т. Е. Истории транзакций.
Я обычно использую логические удаления - я считаю, что они хорошо работают, когда вы также периодически архивируете «удаленные» данные в заархивированной таблице (в которой можно выполнять поиск при необходимости), таким образом, не имея возможности повлиять на производительность приложения.
Это хорошо работает, потому что у вас все еще есть данные, если вы когда-либо проходили аудит. Если удалить его физически, его нет !
Я большой поклонник логического удаления, особенно для бизнес-приложений или в контексте учетных записей пользователей. Мои причины просты: часто я не хочу, чтобы пользователь мог больше использовать систему (поэтому учетная запись помечается как удаленная), но если мы удалим пользователя, мы потеряем всю его работу и тому подобное.
Другой распространенный сценарий - пользователи могут быть воссозданы через некоторое время после удаления. Для пользователя гораздо приятнее иметь все свои данные в том виде, в котором они были до удаления, а не создавать их заново.
Я обычно думаю об удалении пользователей как о «приостановке» их на неопределенный срок. Никогда не знаешь, когда им законно нужно будет вернуться.
Я почти всегда мягко удаляю, и вот почему:
isdeleted
повсюду не является проблемой, вы userid
все равно должны проверять (если база данных содержит данные от нескольких пользователей). Вы можете принудительно выполнить проверку с помощью кода, поместив эти две проверки в отдельную функцию (или используя представления)Re: "Это безопасно?" - это зависит от того, что вы имеете в виду.
Если вы имеете в виду, что, выполняя физическое удаление, вы не позволите никому когда-либо найти удаленные данные , тогда да, это более или менее верно; безопаснее физически удалять конфиденциальные данные, которые необходимо стереть, потому что это означает, что они навсегда исчезнут из базы данных. (Однако помните, что могут быть и другие копии данных, о которых идет речь, например, в резервной копии или в журнале транзакций, или в записанной версии в пути, например, сниффер пакетов - просто потому, что вы удаляете из своей базы данных, это не гарантия, что он не был сохранен где-то еще.)
Если вы имеете в виду, что, выполняя логическое удаление, ваши данные будут более безопасными, потому что вы никогда не потеряете их , это тоже правда. Это хорошо для сценариев аудита; Я , как правило , проектировать таким образом , что она допускает основной факт , что когда - то генерируются данные, он никогда не будет действительно уйти (особенно , если он когда - либо имел возможность быть, скажем, кэшируются с помощью поисковой системы Интернет). Конечно, реальный сценарий аудита требует, чтобы не только удаления были логичными, но и чтобы обновления регистрировались вместе с указанием времени изменения и исполнителя, внесшего изменение.
Если вы имеете в виду, что данные не попадут в руки тех, кто не должен их видеть, то это полностью зависит от вашего приложения и его структуры безопасности. В этом отношении логическое удаление не более или менее безопасно, чем что-либо еще в вашей базе данных.
Я категорически не согласен с логическим удалением, потому что вы подвержены множеству ошибок.
Прежде всего, каждый запрос должен обрабатывать поле IsDeleted, и вероятность ошибки возрастает при сложных запросах.
Во-вторых, производительность: представьте себе таблицу со 100000 записей и только 3 активными, теперь умножьте это число на таблицы вашей базы данных; Еще одна проблема производительности - это возможный конфликт новых записей со старыми (удаленными).
Единственное преимущество, которое я вижу, - это история записей, но есть и другие методы для достижения этого результата, например, вы можете создать таблицу регистрации, в которой вы можете сохранять информацию: TableName,OldValues,NewValues,Date,User,[..]
где *Values
может быть, varchar
и записывать детали в эту форму fieldname : value
; [..] или сохраните информацию как xml
.
Все это может быть достигнуто с помощью кода или триггеров, но вы - только ОДНА таблица со всей вашей историей. Другой вариант - проверить, поддерживает ли указанный механизм базы данных встроенную поддержку отслеживания изменений, например, в базе данных SQL Server есть изменение данных отслеживания SQL.
Раньше я делал мягкое удаление, просто чтобы сохранить старые записи. Я понял, что пользователи не так часто просматривают старые записи, как я думал. Если пользователи хотят просматривать старые записи, они могут просто просматривать их из архива или таблицы аудита, верно? Итак, в чем преимущество мягкого удаления? Это только приводит к более сложному запросу и т. Д.
Ниже приведены вещи, которые я реализовал до того, как решил больше не удалять мягкое удаление:
внедрить аудит, чтобы записывать все действия (добавление, редактирование, удаление). Убедитесь, что нет внешнего ключа, связанного с аудитом, и убедитесь, что эта таблица защищена и никто не может удалить, кроме администраторов.
определить, какие таблицы считаются «транзакционной таблицей», которая, скорее всего, будет храниться в течение длительного времени, и, скорее всего, пользователь может захотеть просмотреть прошлые записи или отчеты. Например; сделка покупки. В этой таблице должен храниться не только идентификатор главной таблицы (например, dept-id), но и дополнительная информация, такая как имя в качестве ссылки (например, dept-name), или любые другие поля, необходимые для отчетности.
Реализуйте «активный / неактивный» или «включить / выключить» или «скрыть / показать» запись главной таблицы. Таким образом, вместо удаления записи пользователь может отключить / деактивировать основную запись. Так намного безопаснее.
Просто мое мнение за два цента.
Логические удаления, если это плохо для ссылочной целостности.
Это правильное решение, когда есть временной аспект данных таблицы (действительны FROM_DATE - TO_DATE).
В противном случае переместите данные в таблицу аудита и удалите запись.
С положительной стороны:
Это самый простой способ отката (если это вообще возможно).
Легко увидеть, каково было состояние в определенный момент времени.
Это довольно стандартно в случаях, когда вы хотите сохранить историю чего-либо (например, учетные записи пользователей, как упоминает @Jon Dewees). И это, безусловно, отличная идея, если есть большая вероятность того, что пользователи попросят отменить удаление.
Если вас беспокоит, что логика фильтрации удаленных записей из ваших запросов становится беспорядочной и просто усложняет ваши запросы, вы можете просто создать представления, которые выполняют фильтрацию за вас и использовать запросы против этого. Это предотвратит утечку этих записей в решениях для отчетности и т.п.
Есть требования, выходящие за рамки системного проектирования, на которые необходимо ответить. Каковы юридические или законодательные требования к хранению записей? В зависимости от того, к чему относятся строки, может существовать законное требование, чтобы данные хранились в течение определенного периода времени после их «приостановки».
С другой стороны, требование может заключаться в том, что после «удаления» записи она действительно и безвозвратно удаляется. Прежде чем принять решение, поговорите со своими заинтересованными сторонами.
Они не позволяют базе данных работать должным образом, делая бесполезными такие вещи, как каскадные функции.
Для простых вещей, таких как вставки, в случае повторной вставки код, стоящий за ней, удваивается.
Вы не можете просто вставить, вместо этого вы должны проверить наличие и вставить, если он не существует раньше, или обновить флаг удаления, если он есть, одновременно обновляя все другие столбцы до новых значений. Это рассматривается как обновление журнала транзакций базы данных, а не как новая вставка, вызывающая неточные журналы аудита.
Они вызывают проблемы с производительностью, поскольку таблицы забиваются избыточными данными. Он играет хаотично с индексацией, особенно с уникальностью.
Я не большой поклонник логических удалений.
Чтобы ответить на комментарий Тохида, мы столкнулись с той же проблемой, когда мы хотели сохранить историю записей, а также не были уверены, нужна ли нам is_deleted
колонка или нет.
Я говорю о нашей реализации на Python и аналогичном сценарии использования, который мы затронули.
Мы обнаружили https://github.com/kvesteri/sqlalchemy-continuum, который представляет собой простой способ получить таблицу управления версиями для соответствующей таблицы. Минимум строк кода и история захвата для добавления, удаления и обновления.
Это не просто is_deleted
колонка. Вы всегда можете вернуться к таблице версий, чтобы проверить, что произошло с этой записью. Была ли запись удалена, обновлена или добавлена.
Таким образом, нам вообще не нужно было иметь is_deleted
столбец, а наша функция удаления была довольно тривиальной. Таким образом, нам также не нужно помнить о маркировке is_deleted=False
ни в одном из наших API.
Мягкое удаление - это практика программирования, которой придерживаются в большинстве приложений, когда данные более актуальны. Рассмотрим случай финансового приложения, в котором удаление по ошибке конечного пользователя может быть фатальным. Это тот случай, когда становится актуальным мягкое удаление. При мягком удалении пользователь фактически не удаляет данные из записи, вместо этого они помечаются как IsDeleted равными true (по обычному соглашению).
В EF 6.x или EF 7 и далее Softdelete добавляется в качестве атрибута, но на данный момент мы должны создать настраиваемый атрибут.
Я настоятельно рекомендую SoftDelete в дизайне базы данных и это хорошее соглашение для практики программирования.
В большинстве случаев мягкое удаление используется, потому что вы не хотите раскрывать некоторые данные, но вы должны сохранить их по историческим причинам (продукт может быть прекращен, поэтому вы не хотите никаких новых транзакций с ним, но вам все равно нужно работать с история сделки купли-продажи). Кстати, некоторые копируют значение информации о продукте в данные транзакции продажи вместо того, чтобы делать ссылку на продукт для обработки этого.
На самом деле это больше похоже на переформулировку видимой / скрытой или активной / неактивной функции. Потому что это значение слова «удалить» в деловом мире. Я хочу сказать, что Терминаторы могут удалять людей, а босс просто увольняет их.
Это довольно распространенная практика, которая используется во многих приложениях по разным причинам. Поскольку это не единственный способ добиться этого, у вас будут тысячи людей, которые скажут, что это здорово или чушь, и у обоих есть довольно хорошие аргументы.
С точки зрения безопасности SoftDelete не заменит работу аудита и не заменит задачу резервного копирования. Если вы боитесь «вставки / удаления между двумя вариантами резервного копирования», вам следует прочитать о моделях полного или массового восстановления. Я допускаю, что SoftDelete может сделать процесс восстановления более тривиальным.
До вас знать ваши требования.
В качестве альтернативы у нас есть пользователи, использующие удаленное обновление устройств через MobiLink. Если мы удалим записи в базе данных сервера, эти записи никогда не будут помечены как удаленные в клиентских базах данных.
Итак, мы делаем и то, и другое. Мы работаем с нашими клиентами, чтобы определить, как долго они хотят иметь возможность восстанавливать данные. Например, обычно клиенты и продукты активны до тех пор, пока наш клиент не скажет, что они должны быть удалены, но история продаж сохраняется только в течение 13 месяцев, а затем удаляется автоматически. Клиент может пожелать сохранить удаленных клиентов и продукты в течение двух месяцев, но сохранить историю в течение шести месяцев.
Таким образом, мы запускаем скрипт в течение ночи, который помечает вещи, которые логически удалены в соответствии с этими параметрами, а затем через два / шесть месяцев все, что было помечено как логически удаленное сегодня, будет удалено без возможности восстановления.
Мы не столько заботимся о безопасности данных, сколько о наличии огромных баз данных на клиентском устройстве с ограниченной памятью, таком как смартфон. У клиента, который заказывает 200 продуктов дважды в неделю в течение четырех лет, будет более 81 000 строк истории, из которых 75% клиента не волнует, увидит ли он.
Все зависит от варианта использования системы и ее данных.
Например, если вы говорите о регулируемой государством системе (например, о системе в фармацевтической компании, которая считается частью системы качества и должна следовать рекомендациям FDA в отношении электронных записей), то вам, черт возьми, лучше не выполнять жесткое удаление! Аудитор из FDA может прийти и запросить все записи в системе, относящиеся к номеру продукта ABC-123, и все данные будут лучше доступны. Если владелец бизнес-процесса говорит, что система не должна позволять никому использовать номер продукта ABC-123 для новых записей в будущем, используйте метод мягкого удаления, чтобы сделать его «неактивным» в системе, сохраняя при этом исторические данные.
Однако, возможно, ваша система и ее данные имеют такой вариант использования, как «отслеживание погоды на Северном полюсе». Возможно, вы измеряете температуру один раз в час и в конце дня суммируете среднесуточное значение. Возможно, почасовые данные больше не будут использоваться после агрегирования, и вы бы жестко удалили почасовые показания после создания агрегата. (Это выдуманный тривиальный пример.)
Дело в том, что все зависит от варианта использования системы и ее данных, а не от решения, которое следует принимать исключительно с технологической точки зрения.
Хорошо! Как все говорили, это зависит от ситуации.
Если у вас есть индекс для столбца, такого как 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 +, он не может использоваться кем-либо еще.
Наступает день, когда пользователь хочет удалить свой профиль с сайта. Теперь, если вы сделаете логическое удаление, этот пользователь больше не сможет зарегистрироваться. Кроме того, повторная регистрация с использованием того же идентификатора электронной почты не означает восстановления всей истории. Всем известно, что удаление означает удаление. В таких случаях мы должны выполнить физическое удаление. Но для того, чтобы сохранить всю историю учетной записи, мы всегда должны архивировать такие записи либо в архивных таблицах, либо в удаленных таблицах.
Да, в ситуациях, когда у нас много сторонних таблиц, обработка оказывается довольно громоздкой.
Также имейте в виду, что мягкое / логическое удаление увеличит размер вашей таблицы, поэтому размер индекса.
Я уже ответил в другом посте . Однако я думаю, что мой ответ больше подходит для поставленного здесь вопроса.
Мое практичное решение для мягкого удаления является архивирование путем создания новой таблицы со следующими столбцами:
original_id
,table_name
,payload
, (и дополнительный первичный ключ `идентификатор).Где
original_id
исходный идентификатор удаленной записи,table_name
это имя таблицы удаленной записи ("user"
в вашем случае),payload
это строка в формате JSON из всех столбцов удаленной записи.Я также предлагаю сделать индекс по столбцу
original_id
для последующего извлечения данных.Таким способом архивирования данных. У вас будут эти преимущества
- Следите за всеми данными в истории
- Иметь только одно место для архивирования записей из любой таблицы, независимо от структуры таблицы удаленной записи
- Не беспокойтесь об уникальном индексе в исходной таблице
- Не беспокойтесь о проверке внешнего индекса в исходной таблице
- Больше никаких
WHERE
предложений в каждом запросе для проверки на удалениеУже обсуждение здесь объясняет , почему мягкое удаление не является хорошей идея , на практике. Мягкое удаление вводит некоторые потенциальные проблемы в будущем, такие как подсчет записей, ...
Приключения - это сохранение / увековечение данных. Несоответствие - это снижение производительности при запросе или извлечении данных из таблиц со значительным количеством мягких удалений. В нашем случае мы используем комбинацию обоих: как другие упоминали в предыдущих ответах, soft-delete
users/clients/customers
например, мы , и hard-delete
в items/products/merchandise
таблицах, где есть повторяющиеся записи, которые не нужно хранить.
Это зависит от случая, учтите следующее:
Обычно не требуется «мягкое удаление» записи. Сделайте это просто и быстро. например, удаление продукта, который больше не доступен, поэтому вам не нужно проверять, не удален ли продукт по всему приложению (счетчик, список продуктов, рекомендуемые продукты и т. д.).
Тем не менее, вы можете рассмотреть возможность «мягкого удаления» в модели хранилища данных. Например, вы просматриваете старую квитанцию об удаленном продукте. *