Rails用两者做什么:dependent =>:destroy和cascade delete/nullify/restrict

Pet*_*des 13 cascade ruby-on-rails foreign-keys dependent-destroy

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

简而言之,我想要了解如何最好地利用依赖对象的destroy方法和外键约束,以确保cruft不会累积并反映存储数据的逻辑结构.几个早期的问题,比如我应该使用ON DELETE CASCADE,:dependent =>:destroy,还是两者都有?Rails:删除cascade vs dependent destroy询问哪个更好但是他们并没有真正说明两个选择如何相互作用以及它们被触发的顺序或者看起来模糊不清.

正如我所看到的那样,考虑因素似乎分为几个方面:

  1. :dependent => :destroy在从数据库中删除父对象之前,调用是否首先在依赖对象上进行销毁,因此即使我使用级联删除,仍会在这些对象上调用destroy?
  2. 是否:dependent => :destroy从数据库中移除父项之前(或在事务中)从数据库中删除依赖对象?换句话说,如果我将cascade设置为nullify,数据库最终会在删除子对象之前浪费地取消它们的引用吗?

  3. 是否由于原始销毁和链接:dependent => :destroy选项包含在事务中而发出删除,或者遗憾的是,如果我没有设置级联删除,则会在数据库中暂时崩溃?

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

Vas*_*fed 9

随着dependent: :destroy在轨交易第一销毁所有依赖关系,然后才删除记录本身。

可能存在竞争条件:如果在 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 会很乐意删除所有内容。

  • @PeterGerdes大多数数据库的默认事务隔离级别为“已提交读”(出于性能原因),因此允许“不可重复读”。Rails 逻辑也位于数据库之外。示例:事务 _A_ 添加了依赖记录 _R_,但未提交。事务 B 是父销毁事务,在依赖记录中,它不会读取 R,因为 A 未提交。然后A最终提交,外键没有违反,因为父记录仍然存在(B没有提交,也可能还没有删除它),所以R被写入。B 可以重新读取项目并将 R 放入集合中,但为时已晚 (2认同)