Что делают Rails с обоими: depend =>: destroy и cascade delete/nullify/restrict
Я пытаюсь решить, как лучше всего настроить (если вообще) внешние ограничения ключа для моего приложения rails. У меня есть модель Response
, которая belongs_to
a Prompt
. Я хотел бы использовать :dependent => :destroy
для вызова destroy на каждый Response
, который принадлежит удаленному Prompt
, и я пытаюсь решить, какое ограничение на удаление я должен разместить на моем внешнем ключе.
Короче говоря, мне нужен совет о том, как я могу лучше всего использовать как метод destroy для зависимых объектов, так и ограничения внешнего ключа, чтобы гарантировать, что крут не накапливается и не отражает логическую структуру хранящихся данных. Несколько предыдущих вопросов, таких как Должен ли я использовать ON DELETE CASCADE,: dependent = > : уничтожить или оба? и Rails: удалить каскад против зависимого уничтожения спросил, что было лучше, но они не очень много говорят о том, как два варианта взаимодействуют и в каком порядке они срабатывают или кажутся расплывчатыми в этом вопросе.
Как я вижу, соображения, похоже, разбиваются на несколько частей:
- Вызывает ли вызов
:dependent => :destroy
сначала на зависимые объекты перед удалением родителя из базы данных, поэтому уничтожение будет вызываться на этих объектах, даже если я использую каскадное удаление?
-
Удаляет ли :dependent => :destroy
зависимые объекты из базы данных до (или в транзакции) с удалением родителя из базы данных? Другими словами, если я устанавливаю каскад для аннулирования, база данных в конечном итоге опустошает ссылки на дочерние объекты до их удаления?
-
Удаляются ли в результате исходных вариантов уничтожения и привязки :dependent => :destroy
, завернутых в транзакцию, или, к сожалению, при кратковременных сбоях в базе данных, если я не устанавливаю каскадное удаление?
/li > - Наконец, будет
:dependent => :destroy
гарантировать, что родительский объект будет удален из базы данных, если я использую ограничение как параметр внешнего ключа on_delete?
Ответы
Ответ 1
При dependent: :destroy
в транзакции rails сначала уничтожает все зависимости, а только потом удаляет саму запись.
Может быть условие гонки: если зависимая запись была добавлена сразу после того, как рельсы прочитали коллекцию для уничтожения, но еще не удалили родителя - она может быть оставлена. Позвольте назвать эти "записи о состоянии гонки" ниже.
-
да, вы можете использовать dependent: :destroy
и on delete cascade
, таким образом, некоторые дочерние элементы (состояния гонки) могут быть удалены без обратных вызовов. Если обратные вызовы являются обязательными - on delete restrict
вместе с некоторыми блокировками и явное дочернее удаление может быть лучше. Это похоже на validates :some_field, uniqueness: true
который лучше поддерживать уникальным индексом, только база данных может обеспечить согласованность данных.
-
поскольку родитель удаляется последним, on delete nullify
не будет мешать (вы получите аннулированные записи о состоянии гонки)
-
там транзакция, оборачивающая все удаляемые, могут быть оставлены только записи о состоянии гонки
-
on delete restrict
по dependent: :destroy
будет срабатывать только для записей условий гонки (и откатывать всю транзакцию), но если условий гонки не было - рельсы удачно удалят все.