【问题标题】:Duplicate request threads create duplicate database entries in Django model重复的请求线程在 Django 模型中创建重复的数据库条目
【发布时间】:2011-07-13 19:53:18
【问题描述】:

问题:信号接收器检查特定条件下是否存在模型条目,如果不存在,则创建一个新条目。在极少数情况下,条目被重复。

在接收函数内:

try:
    my_instance = MyModel.objects.get(field1=value1, field2=sender)
except:
    my_instance = MyModel(field1=value1, field2=sender)
    my_instance.save()

这是get_or_create 的明显候选者,但除了清理该代码之外,使用get_or_create 是否有助于防止此问题?

信号是在用户操作后发送的,但我不认为原始请求被重复,因为这会触发其他操作。

在数千个实例中重复发生了几次。这是否一定是由多个请求引起的,还是可以通过某种方式创建重复线程?有没有办法——也许是细粒度的事务管理——来防止重复?

在 Apache2 上使用 Django 1.1、Python 2.4、PostgreSQL 8.1 和 mod_wsgi。

【问题讨论】:

  • 删除我的答案,因为我没有解决线程安全问题。只是指出,在您的设置中,如果 MyModel 曾经通过任何方式创建了重复项,那么当 get 返回 MultipleObjectsReturned 异常时,它将不断产生重复项。

标签: django transactions thread-safety django-signals django-database


【解决方案1】:

为防止信号重复,将“dispatch_uid”参数添加到信号附件代码中,如described in the docs

确保您打开了一个事务 - 否则可能会发生在检查表的 (objects.get()) 和 cration (save()) 状态之间发生变化。

【讨论】:

  • 太棒了 - 不知道为什么,但它不在 Django 1.1 文档中,尽管它肯定在 Django 1.1 调度模块中。打算试试这个。
【解决方案2】:

也许this answer 可能会有所帮助。显然,get_or_create 可以正确使用事务,但我还没有确认这一点。 mod_wsgi 是多进程和多线程的(都是可配置的),这意味着竞争条件肯定会发生。我猜您的应用程序中发生的情况是,两个单独的请求被启动,它们将为field1 生成相同的值,并且恰好它们在正确的时间执行以添加“重复”条目。

如果MyModel(field1=value1, field2=sender) 的组合必须是唯一的,则在您的模型上定义一个unique_together 约束以进一步帮助完整性。

【讨论】:

  • 感谢您的提醒。是的,约束将解决最终问题,并且是一般数据完整性的好主意,但如果可以避免,当然希望避免更改生产数据库。
  • @benny,可以理解,但如果约束在数据级别有效,则应该应用它。应尽快纠正数据模型中的错误。但是,get_or_create 应该同时使用事务来满足您的目的。
猜你喜欢
  • 1970-01-01
  • 2019-02-01
  • 2018-08-15
  • 2012-10-16
  • 2021-09-08
  • 2017-05-08
  • 2018-10-09
  • 2013-03-16
  • 2021-12-23
相关资源
最近更新 更多