重复的请求线程在Django模型中创建重复的数据库条目

时间:2011-03-11 22:04:58

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

问题:信号接收器检查某些条件是否存在模型条目,如果不存在,则会创建一个新条目。在一些罕见的情况下,该条目正在重复。

在接收函数中:

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。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

也许this answer可能会有所帮助。显然,交易与get_or_create正确使用,但我没有证实这一点。 mod_wsgi是多进程和多线程(都是可配置的),这意味着肯定会出现竞争条件。我猜你的应用程序中发生了两个单独的请求,这些请求将为field1生成相同的值,并且它恰好在恰当的时间执行以添加“重复”条目。

如果MyModel(field1=value1, field2=sender)的组合必须是唯一的,那么请在模型上定义unique_together约束,以进一步提升完整性。