В чем преимущество выполнения логического/мягкого удаления записи (т.е. установка флага, указывающего, что запись удалена), в отличие от фактического или физического удаления записи?
Это обычная практика?
Это безопасно?
В чем преимущество выполнения логического/мягкого удаления записи (т.е. установка флага, указывающего, что запись удалена), в отличие от фактического или физического удаления записи?
Это обычная практика?
Это безопасно?
Преимущества в том, что вы сохраняете историю (хорошо для аудита), и вам не нужно беспокоиться о каскадировании удаления через различные другие таблицы в базе данных, которые ссылаются на строку, которую вы удаляете. Недостатком является то, что вы должны закодировать любые методы отчетности/отображения, чтобы принять флаг.
Насколько это обычная практика - я бы сказал "да", но, как и все, что вы используете, зависит от потребностей вашего бизнеса.
EDIT: Мысль о другом неудобстве. Если у вас есть уникальные индексы в таблице, удаленные записи по-прежнему будут занимать "одну" запись, поэтому вам также придется кодировать эту возможность (например, таблицу пользователя, которая имеет уникальный индекс на имени пользователя, удаленная запись по-прежнему блокирует имя пользователя удаленных пользователей для новых записей. Работая вокруг этого, вы можете привязать GUID к столбцу удаленных пользователей, но это очень хакерское обходное решение, которое я бы не рекомендовал. было бы лучше иметь правило, что после использования имени пользователя он никогда не может быть заменен.)
Является ли логическое удаление обычной практикой? Да, я видел это во многих местах. Безопасны ли они? Это действительно зависит от того, насколько они менее безопасны, чем данные перед удалением?
Когда я был техническим руководителем, я потребовал, чтобы наша команда хранила каждую часть данных, я знал, что в то время мы будем использовать все эти данные для создания различных приложений BI, хотя в то время мы не знали, что требования были бы. Хотя это было хорошо с точки зрения аудита, устранения неполадок и отчетности (это был сайт электронной коммерции/инструментов для транзакций B2B, и если кто-то использовал инструмент, мы хотели записать его, даже если их учетная запись была впоследствии отключена), у него было несколько недостатков.
Недостатки включают (не считая других уже упомянутых):
При принятии решения об использовании логических, физических удалений или архивирования я задавал себе следующие вопросы:
Возможно, немного поздно, но я предлагаю всем проверить сообщение в блоге Pinal Dave о логическом/мягком удалении:
Мне совсем не нравится этот дизайн [soft delete]. Я твердо верю в архитектуру, где только необходимые данные должны быть в одной таблице, а бесполезные данные должны быть перемещены в архивированную таблицу. Вместо того, чтобы следовать столбцу isDeleted, я предлагаю использовать две разные таблицы: одну с заказами и другую с удаленными заказами. В этом случае вам придется поддерживать обе таблицы, но на самом деле ее очень легко поддерживать. Когда вы пишете инструкцию UPDATE в столбец isDeleted, напишите INSERT INTO в другую таблицу и DELETE из исходной таблицы. Если ситуация отката, напишите еще один INSERT INTO и DELETE в обратном порядке. Если вас беспокоит неудачная транзакция, оберните этот код в транзакцию.
В чем преимущества таблиц меньших таблиц в таблице выше в приведенных выше ситуациях?
- Маленькую таблицу легко поддерживать
- Операции перестройки индекса намного быстрее
- Перемещение архивных данных в другую файловую группу уменьшит нагрузку первичной файловой группы (учитывая, что все файловые группы находятся в другой системе) - это также ускорит резервное копирование.
- Статистика будет часто обновляться из-за меньшего размера, и это будет менее ресурсоемким.
- Размер индекса будет меньше
- Производительность таблицы улучшится с меньшим размером таблицы.
Я разработчик NoSQL, и на моей последней работе я работал с данными, которые всегда были важны для кого-то, и если он был удален случайно в тот же день, который был создан, я не смог его найти последняя резервная копия со вчерашнего дня! В этой ситуации мягкое удаление всегда сохраняло день.
Я сделал мягкое удаление с использованием временных меток, зарегистрировав дату удаления документа:
IsDeleted = 20150310 //yyyyMMdd
Каждое воскресенье процесс проходил по базе данных и проверял поле IsDeleted
. Если разница между текущей датой и временной меткой была больше, чем N дней, документ был удален. Учитывая, что документ по-прежнему доступен для некоторых резервных копий, было бы безопасно это сделать.
РЕДАКТИРОВАТЬ: Этот случай использования NoSQL - это большие документы, созданные в базе данных, десятки или сотни из них каждый день, но не тысячи или миллионы. По общему мнению, это были документы со статусом, данными и вложениями процессов документооборота. Именно поэтому была причина, по которой пользователь удаляет важный документ. Этот пользователь может быть кем-то с правами администратора или, возможно, владельцем документа, просто чтобы назвать несколько.
TL; DR Мой вариант использования не был большим. В этом случае вам понадобится другой подход.
Один из шаблонов, который я использовал, - это создание зеркальной таблицы и присоединение триггера к основной таблице, поэтому все удаления (и обновления при желании) записываются в зеркальную таблицу.
Это позволяет вам "восстанавливать" удаленные/измененные записи, и вы все еще можете жестко удалять в основной таблице и сохранять ее "чистой" - это также позволяет создавать функцию "отмены", а также вы можете записывать дату и время и пользователь, который сделал действие в зеркальной таблице (неоценим в ситуациях охоты на ведьм).
Другое преимущество заключается в том, что нет возможности случайно включить удаленные записи при запросе к первичному, если вы сознательно не решите включить записи из зеркальной таблицы (возможно, вы захотите показать живые и удаленные записи).
Другое преимущество состоит в том, что зеркальная таблица может быть очищена независимо, поскольку она не должна иметь каких-либо фактических ссылок на внешние ключи, что делает эту операцию относительно простой по сравнению с очисткой из первичной таблицы, которая использует мягкое удаление, но все еще имеет ссылочные соединения с другими таблицами.
Какие еще преимущества? - замечательно, если у вас есть куча кодеров, работающих над проектом, выполняющих операции чтения базы данных со смешанным умением и вниманием к уровням детализации, вам не нужно не спать по ночам в надежде, что один из них не забыл не включать удаленные записи ( lol, Not Include Deleted Records = True), что приводит к таким вещам, как завышение, скажем, доступная денежная позиция клиентов, с которой они затем покупают некоторые акции (то есть, как в торговой системе), когда вы работаете с торговыми системами, вы найдете очень быстро выявляют ценность надежных решений, хотя они могут иметь немного больше первоначальных "накладных расходов".
Исключения:
- в качестве руководства используйте мягкое удаление для "справочных" данных, таких как пользователь, категория и т.д., и жесткое удаление в зеркальную таблицу для данных "фактического" типа, то есть истории транзакций.
Я обычно использую логические удаления - я нахожу, что они хорошо работают, когда вы также периодически архивируете "удаленные" данные в архивированную таблицу (которая может быть найдена в случае необходимости), поэтому не имеет шанса повлиять на производительность приложения.
Это хорошо работает, потому что у вас все еще есть данные, если вы когда-либо проверялись. Если вы удалите его физически, оно исчезло!
Я большой поклонник логического удаления, особенно для приложения Business of Business или в контексте учетных записей пользователей. Мои причины просты: часто я не хочу, чтобы пользователь мог больше использовать систему (поэтому учетная запись получает помеченную как удаленную), но если мы удалили пользователя, мы потеряли бы все их работу и т.д.
Другим распространенным сценарием является то, что пользователи могут быть повторно созданы некоторое время после удаления. Для пользователя гораздо приятнее использовать все свои данные, как было до их удаления, вместо того, чтобы повторно создавать его.
Я обычно думаю об удалении пользователей более как "приостановку" их на неопределенный срок. Вы никогда не знаете, когда они законно должны вернуться.
Я почти всегда мягко удаляю и вот почему:
isdeleted
везде не является проблемой, вы все равно должны проверить на userid
(если база данных содержит данные от нескольких пользователей). Вы можете применить проверку по коду, поместив эти две проверки в отдельную функцию (или использовать представления)Re: "Это безопасно?" - это зависит от того, что вы имеете в виду.
Если вы имеете в виду, что, выполнив физическое удаление, вы помешаете кому-либо найти удаленные данные, тогда да, это более или менее верно; вы безопаснее физически удалять конфиденциальные данные, которые необходимо удалить, потому что это означает, что он постоянно удаляется из базы данных. (Однако, понимайте, что могут быть другие копии данных, о которых идет речь, например, в резервной копии или журнале транзакций, или записанная версия из транзита, например, сниффер пакетов - только потому, что вы удаляете из своей базы данных, гарантировать, что он не был сохранен где-то в другом месте.)
Если вы имеете в виду, что, делая логическое удаление, ваши данные более безопасны, потому что вы никогда не потеряете никаких данных, что также верно. Это хорошо для сценариев аудита; Я имею тенденцию разрабатывать этот путь, потому что он признает тот факт, что, как только данные генерируются, он никогда не исчезнет (особенно если у него когда-либо была возможность быть, скажем, кэширована поисковой системой Интернета). Конечно, реальный сценарий аудита требует, чтобы не только удалялись логические, но также регистрировались обновления, а также время изменения и актер, внесший изменения.
Если вы имеете в виду, что данные не попадут в руки тех, кто не должен их видеть, то это полностью зависит от вашего приложения и его структуры безопасности. В этом отношении логическое удаление не более или менее безопасно, чем что-либо еще в вашей базе данных.
Логические удаления, если они жестко связаны с ссылочной целостностью.
Правильно думать, когда есть временный аспект данных таблицы (действительны FROM_DATE - TO_DATE).
В противном случае переместите данные в таблицу аудита и удалите запись.
С положительной стороны:
Это более простой способ откат (если вообще возможно).
Легко понять, каково было состояние в определенный момент времени.
Это довольно стандартно в тех случаях, когда вы хотите сохранить историю чего-то (например, учетные записи пользователей, как упоминаются @Jon Dewees). И это, безусловно, отличная идея, если у пользователей есть сильные шансы на удаление.
Если вы обеспокоены логикой фильтрации удаленных записей из ваших запросов, которые становятся беспорядочными и просто усложняют ваши запросы, вы можете просто создавать представления, которые выполняют фильтрацию для вас, и использовать запросы против этого. Это предотвратит утечку этих записей в решениях для отчетности и т.д.
Я сильно не согласен с логическим удалением, потому что вы подвергаетесь многочисленным ошибкам.
Прежде всего, каждый запрос должен заботиться о поле IsDeleted, а вероятность ошибки становится выше при сложных запросах.
Во-вторых, производительность: представьте таблицу с 100000 реком с только 3 активными, теперь умножьте это число на таблицы вашей базы данных; другой проблемой производительности является возможный конфликт с новыми записями со старыми (удаленные записи).
Единственное преимущество, которое я вижу, это история записей, но есть и другие способы достижения этого результата, например, вы можете создать таблицу протоколирования, в которой вы можете сохранить информацию: TableName,OldValues,NewValues,Date,User,[..]
где *Values
может быть varchar
и напишите подробности в этой форме fieldname : value
; [..] или сохранить информацию как xml
.
Все это может быть достигнуто с помощью кода или триггеров, но вы всего лишь ОДНА таблица со всей вашей историей. Еще один вариант заключается в том, чтобы определить, является ли указанный механизм базы данных встроенной поддержкой отслеживания изменений, например, в базе данных SQL Server есть изменение данных SQL Track.
Существуют требования, выходящие за рамки системы, на которые необходимо ответить. Какое юридическое или законодательное требование в отношении сохранения записей? В зависимости от того, с чем связаны строки, может существовать юридическое требование о том, чтобы данные сохранялись в течение определенного периода времени после его "приостановления".
С другой стороны, требование может заключаться в том, что после того, как запись "удалена", она действительно и безвозвратно удалена. Прежде чем принимать решение, поговорите со своими заинтересованными сторонами.
Мобильные приложения, зависящие от синхронизации, могут налагать использование логического, а не физического удаления: сервер должен иметь возможность указать клиенту, что запись была (отмечена как) удалена, и это может быть невозможно, если записи были физически удален.
Я делал soft-delete, просто чтобы сохранить старые записи. Я понял, что пользователи не утруждают себя просмотром старых записей так часто, как я думал. Если пользователи хотят просматривать старые записи, они могут просто просматривать из таблицы архива или аудита, правильно? Итак, какое преимущество soft-delete? Это приводит только к более сложному запросу запроса и т.д.
Ниже перечислены все, что я реализовал, прежде чем я решил не-soft-delete больше:
выполнить аудит, записать все действия (добавить, отредактировать, удалить). Убедитесь, что нет внешнего ключа, связанного с аудитом, и убедитесь, что эта таблица защищена, и никто не может удалять кроме администраторов.
определить, какие таблицы считаются "транзакционной таблицей", что очень вероятно, что она будет храниться в течение длительного времени, и, скорее всего, пользователь может захотеть просмотреть прошлые записи или отчеты. Например; покупка сделка. В этой таблице не следует просто хранить идентификатор главной таблицы (например, депт-id), но также сохранять дополнительную информацию, такую как имя в качестве ссылки (например, имя-имя), или любые другие необходимые поля для отчетности.
Внедрить запись "активная/неактивная" или "включить/отключить" или "скрыть/показать" главной таблицы. Таким образом, вместо удаления записи пользователь может отключить/неактиву основную запись. Это намного безопаснее.
Только мое мнение двух центов.
Они не позволяют базе данных работать так, как если бы они отображали такие вещи, как бесполезная каскадная функциональность.
Для простых вещей, таких как вставки, в случае повторной установки, код, стоящий за ним, удваивается.
Вы не можете просто вставить, вместо этого вы должны проверить наличие и вставить, если он не существует до или обновить флаг удаления, если он выполняется, одновременно обновляя все остальные столбцы до новых значений. Это рассматривается как обновление журнала транзакций базы данных, а не свежая вставка, вызывающая неточные журналы аудита.
Они вызывают проблемы с производительностью, потому что таблицы забиваются избыточными данными. Он играет havock с индексированием особенно с уникальностью.
Я не большой поклонник логических удалений.
Чтобы ответить на комментарий Tohid, мы столкнулись с такой же проблемой, когда хотели сохранить историю записей, а также не были уверены, хотим ли мы столбец is_deleted
или нет.
Я говорю о нашей реализации python и аналогичном случае использования.
Мы столкнулись с https://github.com/kvesteri/sqlalchemy-continuum, который является простым способом получить таблицу управления версиями для вашей соответствующей таблицы. Минимальные строки кода и фиксирует историю для добавления, удаления и обновления.
Это больше, чем просто столбец is_deleted
. Вы всегда можете использовать таблицу версий backref, чтобы проверить, что произошло с этой записью. Будет ли запись удалена, обновлена или добавлена.
Таким образом, нам не нужно иметь столбец is_deleted
, и наша функция удаления была довольно тривиальной. Таким образом, нам также не нужно забывать отмечать is_deleted=False
в любом из наших api.
Это 2018 год, и одним большим недостатком мягкого удаления является:
Ваша заявка, вероятно, не соответствует требованиям GDPR, если вы выполняете мягкое удаление всего, что считается персональными данными. [ 1 ] [ 2 ]
Также имейте в виду, что, даже если ваша компания не находится в пределах ЕС, если вы имеете дело с данными о предприятиях, жителях или гражданах ЕС, вам придется соблюдать GDPR. [ 3 ]
Soft Delete - это практика программирования, которая соблюдается в большинстве приложений, когда данные более актуальны. Рассмотрим случай финансового приложения, в котором удаление по ошибке конечного пользователя может быть фатальным. Это тот случай, когда мягкое удаление становится актуальным. При мягком удалении пользователь фактически не удаляет данные из записи, а указывает на значение IsDeleted на true (по нормальному соглашению).
В EF 6.x или EF 7 далее Softdelete добавляется как атрибут, но мы должны создать пользовательский атрибут на данный момент.
Я настоятельно рекомендую SoftDelete В дизайне базы данных и ее хорошем соглашении для практики программирования.
Что ж! Как все говорили, это зависит от ситуации.
Если у вас есть индекс для столбца, такого как UserName или EmailID, - и вы никогда не ожидаете, что это же имя пользователя или EmailID будет использоваться снова; Вы можете пойти с мягким удалением.
Тем не менее, всегда проверяйте, использует ли ваша операция SELECT первичный ключ. Если ваш оператор SELECT использует первичный ключ, добавление флага с предложением WHERE не будет иметь большого значения. Давайте возьмем пример (псевдо):
Пользователи таблицы (UserID [первичный ключ], EmailID, IsDeleted)
SELECT * FROM Users where UserID = 123456 and IsDeleted = 0
Этот запрос не будет иметь никакого значения с точки зрения производительности, поскольку столбец UserID имеет первичный ключ. Сначала он будет сканировать таблицу на основе PK, а затем выполнит следующее условие.
Случаи, когда мягкое удаление не может работать вообще:
Регистрация на большинстве веб-сайтов использует EmailID в качестве уникального идентификатора. Мы очень хорошо знаем, как только EmailID используется на веб-сайте, таком как Facebook, G+, он не может быть использован кем-либо еще.
Наступает день, когда пользователь хочет удалить свой профиль с сайта. Теперь, если вы сделаете логическое удаление, этот пользователь больше не сможет зарегистрироваться. Кроме того, повторная регистрация с использованием того же EmailID не будет означать восстановление всей истории. Все знают, удаление означает удаление. В таких сценариях мы должны сделать физическое удаление. Но чтобы сохранить всю историю учетной записи, мы всегда должны архивировать такие записи либо в архивных таблицах, либо в удаленных таблицах.
Да, в ситуациях, когда у нас много сторонних таблиц, обработка довольно громоздка.
Также имейте в виду, что мягкое/логическое удаление увеличит размер таблицы, поэтому размер индекса.
В большинстве случаев используется softdeleting, потому что вы не хотите раскрывать некоторые данные, но вы должны хранить их по историческим причинам (продукт может быть прекращен, поэтому вам не нужна новая транзакция с ним, но вам все еще нужно для работы с историей транзакции продажи). Кстати, некоторые из них копируют значение информации о продукте в данных транзакции продажи, а не ссылаются на продукт, чтобы справиться с этим.
На самом деле это больше похоже на переписку для видимой/скрытой или активной/неактивной функции. Потому что смысл "удалить" в деловом мире. Я хотел бы сказать, что Терминаторы могут удалять людей, но босс просто стреляет в них.
Эта практика довольно распространена и используется многими приложениями по многим причинам. Поскольку это не единственный способ достичь этого, так что у вас будет тысяча людей, говорящих, что великий или дерьмо, и оба имеют довольно хорошие аргументы.
С точки зрения безопасности SoftDelete не заменит работу аудита и не заменит работу резервного копирования. Если вы боитесь "вставить/удалить из двух резервных копий", вы должны прочитать о моделях полного или массового восстановления. Я признаю, что SoftDelete может сделать процесс восстановления более тривиальным.
До вашего сведения, чтобы узнать ваше требование.
Чтобы дать альтернативу, у нас есть пользователи, использующие удаленные устройства, обновляющиеся через MobiLink. Если мы удаляем записи в базе данных сервера, эти записи никогда не помечаются как удаленные в базах данных клиента.
Итак, мы делаем оба. Мы работаем с нашими клиентами, чтобы определить, как долго они хотят иметь возможность восстанавливать данные. Например, обычно клиенты и продукты активны, пока наш клиент не скажет, что их следует удалить, но история продаж сохраняется только в течение 13 месяцев, а затем удаляется автоматически. Клиент может хотеть хранить удаленных клиентов и продукты в течение двух месяцев, но сохранять историю в течение шести месяцев.
Поэтому мы запускаем скрипт на ночь, который помечает логически удаленные объекты в соответствии с этими параметрами, а затем через два/шесть месяцев все помеченные сегодня логически удаленные будут жестко удалены.
Мы не столько о безопасности данных, сколько о наличии огромных баз данных на клиентском устройстве с ограниченной памятью, например на смартфоне. У клиента, который заказывает 200 продуктов два раза в неделю в течение четырех лет, будет более 81 000 строк истории, из которых 75% клиенту все равно, увидит ли он.
Все зависит от варианта использования системы и ее данных.
Например, если вы говорите о регулируемой государством системе (например, о системе в фармацевтической компании, которая считается частью системы качества и должна следовать рекомендациям FDA для электронных записей), то вы, черт побери, лучше не делать жестких удалений! Аудитор из FDA может прийти и запросить все записи в системе, относящиеся к номеру продукта ABC-123, и все данные лучше будут доступны. Если владелец вашего бизнес-процесса говорит, что система не должна позволять кому-либо использовать номер продукта ABC-123 при поступлении новых записей, используйте метод мягкого удаления, чтобы сделать его "неактивным" в системе, сохраняя при этом исторические данные.
Однако, возможно, у вашей системы и ее данных есть вариант использования, такой как "отслеживание погоды на Северном полюсе". Может быть, вы снимаете показания температуры один раз в час, а в конце дня суммируете среднесуточное значение. Возможно, почасовые данные больше не будут использоваться после агрегации, и вам будет сложно удалить почасовые показания после создания агрегата. (Это вымышленный, тривиальный пример.)
Дело в том, что все зависит от варианта использования системы и ее данных, а не от решения, которое будет принято исключительно с технологической точки зрения.
Я уже ответил в другом сообщении. Тем не менее, я думаю, что мой ответ больше подходит для вопроса здесь.
Моим практическим решением для soft-delete является архивация путем создания нового таблица со следующими столбцами:
original_id
,table_name
,payload
, (и необязательный первичный ключ 'id).Где
original_id
является исходным идентификатором удаленной записи,table_name
является именем таблицы удаленной записи ("user"
в вашем случае),payload
- строка в формате JSON из всех столбцов удаленного запись.Я также предлагаю сделать индекс по столбцу
original_id
для последнего извлечение данных.Таким способом архивирования данных. У вас будут эти преимущества
- Следите за всеми данными в истории
- Имеется только одно место для архивирования записей из любой таблицы, независимо от структуры таблицы удаленных записей
- Не беспокойтесь об уникальном индексе в исходной таблице
- Не беспокойтесь о проверке внешнего индекса в исходной таблице
- В каждом запросе больше нет пункта
WHERE
для проверки на удалениеЭто уже обсуждение здесь объясняя почему Софт-удаление не очень хорошая идея на практике. Soft-delete представляет некоторые потенциальные проблемы в будущем, такие как подсчет записей,...