Никогда не удаляете записи? Отличная идея? Обычный? - PullRequest
18 голосов
/ 04 мая 2009

Я проектирую систему, и я не думаю, что это хорошая идея - дать возможность конечному пользователю удалять записи в базе данных. Я думаю, что так, потому что часто конечный пользователь, получив права администратора, может в конечном итоге создать беспорядок в базе данных, а затем обратиться ко мне, чтобы это исправить.

Конечно, им нужно будет иметь возможность удалять записи или, по крайней мере, думать, что они это сделали, если они установлены в качестве администратора.

Итак, я думал, что все записи в базе данных должны иметь "активное" поле. Если они попытаются удалить запись, она просто установит флаг на «ложь» или что-то подобное. Тогда будет какой-то супер администратор, который будет командой моей компании, которая может изменить это поле.

Я уже видел это в другой компании, на которую работал, но мне было интересно, хорошая ли это идея. Я мог бы просто делать регулярные резервные копии базы данных, а затем откатываться, если они допустили ошибку, и добавление этого поля добавило бы сложности всем запросам.

Что вы думаете? Должен ли я сделать это таким образом? Используете ли вы этот трюк в своих приложениях?

Ответы [ 10 ]

15 голосов
/ 04 мая 2009

В одной из наших баз данных мы различали записи transactional и dictionary.

В двух словах transactional записи - это вещи, которые вы не можете откатить в реальной жизни, например, звонок от клиента. Вы можете изменить имя вызывающего абонента, его статус и т. Д., Но вы не можете отклонить сам вызов.

Dictionary записи - это вещи, которые вы можете изменить, например, присвоение city клиенту.

Transactional записи и все, что к ним приводит , никогда не удалялись, тогда как dictionary записи можно было удалить полностью.

Под «вещами, которые к ним ведут» я подразумеваю, что как только запись появляется в бизнес-правилах, которые могут привести к записи transactional, эта запись также становится transactional.

Например, city можно удалить из базы данных. Но когда появилось правило, которое гласило: «отправить SMS всем клиентам в Москве », города также стали рекордными transactional, иначе мы не смогли бы ответить на вопрос «почему это произошло? SMS отправить ".

Практическое правило различения было таким: это только дело моей компании?

Если один из моих сотрудников принял решение на основе данных из базы данных (например, он сделал отчет, на основании которого было принято какое-то управленческое решение, а затем отчет о данных был основан на исчезнувших), было сочтено возможным удалить «ОК». эти данные.

Но если решение повлияло на некоторые немедленные действия с клиентами (например, вызов, изменение баланса клиента и т. Д.), Все, что привело к этим решениям, было сохранено навсегда.

Может варьироваться от одной бизнес-модели к другой: иногда может потребоваться запись даже внутренних данных, иногда можно удалить данные, влияющие на внешний мир.

Но для нашей бизнес-модели правило сверху работало нормально.

10 голосов
/ 04 мая 2009

Несколько причин, по которым люди делают подобные вещи, - аудит и автоматический откат. Если строка полностью удалена, то нет способа автоматически откатить это удаление, если оно было ошибочным. Кроме того, для аудита важно сохранить ряд и его предыдущее состояние - суперпользователь должен иметь возможность видеть, кто что удалил и когда, а также кто что изменил и т. Д.

Конечно, все зависит от бизнес-логики вашего текущего приложения. Некоторые приложения не нуждаются в аудите, и может быть целесообразно полностью удалить строку.

6 голосов
/ 04 мая 2009

Недостатком простой установки флага, такого как IsActive или DeletedDate, является то, что все ваши запросы должны учитывать этот флаг при извлечении данных. Это повышает вероятность того, что другой программист случайно забудет этот флаг при написании отчетов ...

Немного лучшей альтернативой является архивирование этой записи в другой базе данных. Таким образом, он был физически перемещен в местоположение, которое обычно не ищется. Вы можете добавить пару полей, чтобы захватить, кто удалил это и когда; но дело в том, что она не будет загрязнять вашу основную базу данных.

Кроме того, вы можете предоставить функцию отмены, чтобы вернуть ее довольно быстро; и сделать постоянное удаление через 30 дней или что-то в этом роде.

ОБНОВЛЕНИЕ, касающееся просмотров:

С представлениями данные по-прежнему участвуют в вашей схеме индексации. Если количество потенциально удаленных данных невелико, представления могут быть просто нормальными, поскольку они проще с точки зрения кодирования.

3 голосов
/ 05 мая 2009

Я предлагаю иметь вторую базу данных, такую ​​как DB_Archives, куда вы добавляете каждую строку, удаленную из БД. Поле is_active отрицает саму цель ограничений внешнего ключа, и ВЫ должны убедиться, что эта строка не помечена как удаленная, когда на нее ссылаются в другом месте. Это становится слишком сложным, когда ваша структура БД массивна.

3 голосов
/ 04 мая 2009

Я использую комбинацию методов, чтобы обойти эту проблему. Для некоторых вещей добавление дополнительного «активного» поля имеет смысл. Затем у пользователя создается впечатление, что элемент был удален, поскольку он больше не отображается на экране приложения. Сценарии, в которых я бы это реализовал, включали бы элементы, необходимые для ведения истории ... скажем, счет и оплата. Я бы не хотел, чтобы такие вещи были удалены по какой-либо причине.

Тем не менее, есть некоторые элементы в базе данных, которые не настолько чувствительны, скажем, список категорий, которые я хочу быть динамическими ... У меня могут быть пользователи с правами администратора, которые могут добавлять и удалять категории и удаление может быть постоянным. Однако в рамках логики приложения я проверю, используется ли категория где-либо, прежде чем разрешить удаление.

3 голосов
/ 04 мая 2009

Я предпочитаю метод, который вы описываете. Приятно иметь возможность исправить ошибку. Чаще всего нет простого способа вернуться к запросу DELETE. У меня никогда не было проблем с этим методом, и если вы не заполняете свою базу данных «удаленными» записями, проблем быть не должно.

2 голосов
/ 04 мая 2009

Существует приемлемая практика, которая существует во многих приложениях (система управления версиями drupal и др.). Поскольку MySQL очень быстро и легко масштабируется, с вами все будет в порядке.

1 голос
/ 04 мая 2009

Я согласен со всеми респондентами, что если вы можете позволить себе хранить старые данные всегда, это хорошая идея; для производительности и простоты я согласен с предложением перемещать «логически удаленные» записи в таблицы «старых материалов» вместо добавления флагов «is_deleted» (переход на совершенно другую базу данных выглядит как перебор, но вы можете легко изменить это более радикальный подход позже, если в конечном итоге объем накопленных данных окажется проблемой для одного БД с таблицами обычной и «старой вещи»).

1 голос
/ 04 мая 2009

Да и нет.

Это будет усложнять ваше приложение намного больше, чем вы ожидаете, так как каждая таблица, которая не позволяет удалять, будет находиться за дополнительной проверкой (IsDeleted = false) и т. Д. Это не звучит много, но тогда, когда вы строите больше Приложение и в запросе 11 таблиц 9 требуют проверки без удаления .. это утомительно и подвержено ошибкам. (Ну да, тогда есть удаленные / не удаленные представления ... когда вы не забываете делать / использовать их)

Некоторые обновления схемы станут PITA, так как вам придется расслабиться и придумать «подходящие» данные для очень и очень старых данных.

Я не пробовал, но немного подумал о решении, где бы вы заархивировали данные строки в xml и сохранили их в какой-то «исторической» таблице. Тогда, в случае «восстанови сейчас ОМГ, мир умирает! Одиннадцать», можно выкопать.

1 голос
/ 04 мая 2009

В последнее время я работал над проектом, в котором все данные также хранились в БД. Статус каждой отдельной строки сохранялся в целочисленном поле (данные могут быть активными, удалены, in_need_for_manual_correction, history).

Вам следует рассмотреть возможность использования представлений для доступа только к активным / историческим / ... данным в каждой таблице. Таким образом, ваши запросы не станут более сложными.

Еще одной вещью, которая упростила задачу, стало использование триггеров UPDATE / INSERT / DELETE, которые обрабатывали все изменения флага внутри БД и, таким образом, сохраняли сложные вещи вне приложения (по большей части).

Я должен упомянуть, что БД была сервером MSSQL 2005, но я думаю, что тот же подход должен работать и с mysql.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...