为啥 Django 模型级联删除在现实世界中会失败?
Posted
技术标签:
【中文标题】为啥 Django 模型级联删除在现实世界中会失败?【英文标题】:Why would a Django model cascade delete fail in the real world?为什么 Django 模型级联删除在现实世界中会失败? 【发布时间】:2011-10-17 21:47:27 【问题描述】:鉴于 Django 模型:
类 ContainerOwner(模型。模型): id = models.IntegerField() 类容器(模型。模型): 所有者 = 模型.ForeignKey(ContainerOwner)如果您对“ContainerOwner”对象调用 .delete(),它将级联删除该“ContainerOwner”拥有的所有“Container”对象。
但我发现在我的现实生活中的 django 项目中,有时这种级联删除似乎失败了。它似乎偶尔发生,当系统处于高容量时。因此,在“ContainerOwner”被删除后,您最终会得到没有有效“ContainerOwner”的“Container”对象(这应该是不可能的,“Containers”总是有一个“ContainerOwner”。)
以前有没有人见过这种类型的故障并能解释它是如何发生的?应用程序或数据库服务器在进行级联删除的过程中,级联删除会被中途杀死吗?
根据回答反馈更新问题:
1) 我们在 mysql 中使用 myisam
2) 我们正在使用查询集删除来删除“ContainerOwner”对象的查询集
3) MySQL 后端
4) 我们有一个非常常见的操作,即一次性删除所有“ContainerOwner”对象的 Django 查询集,并且也应该删除它们的所有“Container”对象。这种情况每天会发生几十次,我们只是注意到这些孤立的“容器”对象会导致应用程序错误。看起来只有很小比例的删除失败了,比如 0.01% 的删除会导致一些孤儿。
【问题讨论】:
【参考方案1】:如果不了解有关您的应用程序的更多详细信息,实际上不可能回答您的实际问题,例如:
ContainerOwner.delete()
或 Container.delete()
中有自定义逻辑吗?
您是否在 ContainerOwner 上的任何地方使用查询集的 delete?
您使用的是什么数据库??
创建/更新/删除ContainerOwner
/Container
对象的一般使用模式
但最重要的是:
"Container" objects that have no valid "ContainerOwner" after the "ContainerOwner" has been deleted
这首先在数据库级别上是不可能的,除非您缺少外键约束或者您使用的数据库不支持 FK 约束(如 MySQL + MISAM)。如果是前者,你应该先解决这个问题。如果是后者,请考虑切换,具体取决于这对您的应用的实际重要性。
【讨论】:
感谢您提供指导性问题的帮助,我已将原始问题更新为底部的答案。【参考方案2】:如果其他人在此期间添加了一个具有相同 ContainerOwner 的容器,而您在事务之外,它将无法删除。在这些情况下,您应该得到一个 IntegrityError。
此外,如果您有任何 django 之外的代码,并且还有其他冲突的数据库约束,那么这些将阻止级联删除。
尝试检查您的数据库日志,看看删除失败的原因。
【讨论】:
以上是关于为啥 Django 模型级联删除在现实世界中会失败?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用不会将删除级联到其子级的 ForeignKeys 创建 Django 模型?