为什么Django模型级联删除会在现实世界中失败?

时间:2011-08-02 02:11:18

标签: database django model

鉴于Django模型:


class ContainerOwner(models.Model):
  id = models.IntegerField()

class Container(models.Model):
  owner = models.ForeignKey(ContainerOwner)

如果在“ContainerOwner”对象上调用.delete(),它将级联删除该“ContainerOwner”所拥有的所有“Container”对象。

但是我发现在我现实生活中的django项目中,有时这个级联删除似乎失败了。它似乎偶尔发生,当系统处于高容量时。因此,在“ContainerOwner”被删除后,你最终得到的“Container”对象没有有效的“ContainerOwner”(这应该是不可能的,'容器'总是有'ContainerOwner'。)

之前有没有人见过这种类型的失败,可以解释它是如何发生的?在应用程序或数据库服务器执行级联删除的过程中,级联删除是否会被中途杀死?


根据答案反馈更新问题:

1)我们正在使用myisam和MySQL

2)我们使用queryset delete删除“ContainerOwner”对象的查询集

3)MySQL后端

4)我们有一个非常常见的操作,其中一次删除“ContainerOwner”对象的Django查询集,并且还应删除它们的所有“Container”对象。这种情况每天发生几十次,我们只是注意到有这些孤立的“容器”对象导致应用程序错误。看起来很少有一部分删除失败,例如0.01%的删除会导致一些孤儿失踪。

2 个答案:

答案 0 :(得分:2)

如果不了解有关您的应用程序的更多详细信息,则无法回答您的实际问题:

  1. 您在ContainerOwner.delete()Container.delete()
  2. 中是否有自定义逻辑?
  3. 您是否在ContainerOwner上的任何位置使用queryset的delete
  4. 您使用的数据库是什么?
  5. 创建/更新/删除ContainerOwner / Container个对象
  6. 的一般使用模式

    但最重要的是:

    "Container" objects that have no valid "ContainerOwner" after the "ContainerOwner" has been deleted

    除非您缺少外键约束或者您使用的是不支持FK约束的数据库(如MySQL + MYISAM),否则首先不应该在数据库级上执行此操作。如果是前者,你应该先解决这个问题。如果是后者,请考虑切换,具体取决于实际对您的应用程序的重要程度。

答案 1 :(得分:0)

如果其他人在此期间添加了一个容器,它具有相同的ContainerOwner,并且您处于事务之外,则无法删除。在这种情况下,您应该得到IntegrityError。

此外,如果你有任何代码在django之外,并且存在其他相互冲突的数据库约束,那么这些将阻止级联删除。

尝试检查数据库日志,看看删除失败的原因。