#mysql #sql #rdbms #data-integrity
#mysql #sql #rdbms #целостность данных
Вопрос:
Это не конкретный вопрос, а скорее общее удивление.
Когда вам нужно выполнить удаление нескольких таблиц в соотношении 1: M, лучше ли создать ограничение FK с каскадным удалением или объединить таблицы в операторе delete.
У меня был старый проект, в котором были отдельные инструкции delete для связанных таблиц, и несколько раз некоторые инструкции не выполнялись, и целостность данных была нарушена. Мне пришлось принять решение между ними, поэтому я немного подумал, что было бы лучшим решением.
Существует также возможность создать хранимую процедуру или транзакцию.
Итак, я ищу мнение или совет …?
Ответ №1:
Я бы сказал, что безопаснее использовать каскадное удаление. Если вы решите использовать объединения, вы должны помнить, что их нужно использовать каждый раз, когда вы удаляете что-либо из родительской таблицы; и даже если вы достаточно дисциплинированы, чтобы сделать это, вы не можете быть уверены в своих коллегах или людях, которые будут поддерживать ваше программное обеспечение в будущем. Кроме того, кодирование таких знаний об отношениях таблиц более одного раза нарушает принцип DRY.
Однако, если вы используете каскадное удаление, никому не нужно ничего запоминать, и дочерние строки всегда будут удаляться по мере необходимости.
Комментарии:
1. Полностью. Отличный ответ и хорошо сформулированный. Целостности данных всегда уделялось слишком мало внимания, и обычно они начинают появляться через несколько лет «в будущем» и часто заканчиваются удушением многих компаний — они больше не могут внедрять инновации и меняться из-за давно принятых неверных решений о сборе данных.
2. Похоже, что с каскадным удалением связана некоторая стигма из-за возможных несчастных случаев при удалении данных вручную. Лично у меня было несколько неудачных опытов с этим, но я все же согласен, что это более безопасный способ поддержания строгой целостности данных. С другой стороны, я все еще стараюсь избегать использования cascade.
Ответ №2:
Если для вашей базы данных определен правильный RI, то не должно быть никаких случаев нарушения целостности данных. Все ваши связанные таблицы должны иметь декларативный RI, что означает, что вы не можете удалить родительский элемент, пока у него все еще есть дочерние элементы.
Кроме того, если у вас есть код, который время от времени удаляет только некоторые строки, то это плохое кодирование и плохое тестирование. Такого рода действия должны быть одной транзакцией. Ваше предложение использовать хранимую процедуру — отличный подход для решения этой проблемы и довольно стандартный.
Как уже упоминалось, каскадные триггеры имеют опасность удаления строк, которые кто-то не собирался удалять. Учтите, что иногда люди могут получать доступ к вашим данным откуда-то за пределами вашего приложения, особенно при устранении проблем с данными. Когда кто-то случайно пытается удалить не того родителя и получает ошибку RI, это хорошо. Когда они случайно пытаются удалить неправильного родителя, и это удаляет не только этого родителя, но и 20 дочерних элементов в 5 других таблицах, это плохо.
Кроме того, каскадные удаления очень скрыты. Если разработчик кодирует удаление для родительского элемента, он должен знать, что он должен использовать хранимую процедуру удаления для обработки дочерних элементов. Гораздо предпочтительнее, чтобы разработчик не кодировал против этого, получал ошибку и исправлял свой код (или понимал, что он на самом деле не хочет выполнять все это удаление), чем чтобы разработчик добавлял удаление и никто не понимал, что это убивает детей, покакод запущен.
ИМО, я предпочитаю, чтобы мои разработчики были осведомлены о приложении, а не облегчали им оставаться в неведении об этом.
Ответ №3:
Каскадное удаление вызывает множество проблем и, следовательно, чрезвычайно опасно. Я бы не рекомендовал его использовать. Во-первых, предположим, мне нужно удалить запись, содержащую миллионы дочерних записей. Вы можете заблокировать базу данных и сделать ее непригодной для использования в течение нескольких часов. Я знаю очень немногих администраторов баз данных, которые разрешают использовать cascade delete в своих базах данных.
Далее, это не поможет с целостностью данных, если вы определили FKs. Удаление с все еще существующими дочерними записями завершится неудачей, и это хорошо. Я хочу, чтобы удаление клиента завершилось неудачно, например, если у него есть существующие заказы. Каскадное удаление, используемое бездумно (как это обычно бывает по моему опыту), может привести к удалению вещей, которые вы действительно не хотите удалять.
Ответ №4:
Используйте оба!
«Объединенные» ручные удаления обычно лучше для предотвращения взаимоблокировок и других проблем с конфликтом, поскольку вы можете разбить удаления на более мелкие единицы работы. Если у вас действительно есть разногласия, вам определенно легче найти причину конфликта.
Как указано, «каскадное удаление» абсолютно гарантирует ссылочную целостность.
Поэтому используйте оба варианта — выполняйте явное удаление «дочерних элементов» в объединенных sqll, чтобы избежать взаимоблокировок и проблем с производительностью. Но оставьте «КАСКАДНОЕ УДАЛЕНИЕ» включенным, чтобы перехватить все, что вы пропустили. Поскольку не должно быть дочерних элементов, когда вы приступаете к удалению родительского элемента, это ничего вам не будет стоить, если только вы не допустили ошибку при удалении, и в этом случае затраты на поддержание вашей ссылочной целостности того стоят.
Комментарии:
1. Любой внешний ключ гарантирует ссылочную целостность