17

我正在尝试决定如何最好地为我的 rails 应用程序设置(如果有的话)外键约束。我有Response一个belongs_to模型Prompt。我想使用:dependent => :destroydestroy 调用Response属于已删除的每个,Prompt并且我正在尝试确定应该在外键上放置什么删除约束。

简而言之,我想得到关于如何最好地利用依赖对象的销毁方法和外键约束的建议,以确保 cruft 不会累积并反映所存储数据的逻辑结构。几个较早的问题,例如我应该使用 ON DELETE CASCADE、:dependent => :destroy 还是两者都使用?Rails: delete cascade vsdependent destroy问哪个更好,但他们并没有真正说明这两个选择如何相互作用以及它们以什么顺序被触发或在这一点上似乎含糊不清。

在我看来,考虑因素似乎分为几部分:

  1. 在从数据库中删除父对象之前是否:dependent => :destroy首先在依赖对象上调用destroy,所以即使我使用级联删除,仍然会在这些对象上调用destroy?
  2. 在从数据库中删除父对象之前(或在事务中)是否:dependent => :destroy从数据库中删除依赖对象?换句话说,如果我将级联设置为无效,那么数据库最终会在子对象被删除之前浪费地无效化对子对象的引用吗?

  3. 删除是由于包含在事务中的原始销毁和链接:dependent => :destroy选项而发出的,还是如果我不设置级联删除,不幸的是定时崩溃会在数据库中留下垃圾?

  4. 如果我使用限制作为外键 on_delete 选项,最后将:dependent => :destroy确保从数据库中删除父对象?
4

1 回答 1

11

dependent: :destroy事务中,rails 首先销毁所有依赖项,然后才删除记录本身。

可能存在竞争条件:如果在 Rails 读取集合之后添加了依赖记录以进行销毁,但尚未删除父记录 - 它可能会被遗留下来。让我们在下面称这些“竞争条件记录”。

  1. 是的,你可以使用dependent: :destroyand on delete cascade,这样一些孩子(竞争条件的孩子)可以在没有回调的情况下被删除。如果回调是强制性的 -on delete restrict加上一些锁定和显式删除子项可能会更好。这有点像validates :some_field, uniqueness: true最好有唯一索引支持,只有数据库本身才能保证数据的一致性。

  2. 由于父母最后被删除,on delete nullify不会妨碍(你会得到无效的比赛条件记录)

  3. 有包含所有删除的事务,只能留下竞争条件记录

  4. on delete restrictoverdependent: :destroy只会触发竞争条件记录(并回滚整个事务),但如果没有竞争条件 - rails 会很高兴地删除所有内容。

于 2019-05-03T15:49:15.960 回答