Django使用transaction.atomic“死锁”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django使用transaction.atomic“死锁”相关的知识,希望对你有一定的参考价值。

我有一个更新模型的函数或创建一个新条目,如果它不存在:

try:            
  obj=model.objects.get(id=id)
  setattr(obj, 'completed', True)
  obj.save()
except:
  model.objects.create(id=x, user=y, completed=True)

在特定情况下,这个函数被调用两次以至于它在数据库上创建了两个条目,因此,我包含了一个唯一的约束来确保它不会发生。

但后来我开始收到此错误:

Duplicate entry '1-13' for key 'x_y_z_uniq'

所以我尝试使用锁定:

with transaction.atomic():
  try:            
    obj=model.objects.select_for_update().get(id=id)
    setattr(obj, 'completed', True)
    obj.save()
  except:
    model.objects.create(id=x, user=y, completed=True)

但现在提出这个错误:

(Deadlock found when trying to get lock; try restarting transaction)

我想要一种方法,即函数的第一次调用将创建一个新条目,第二次调用将更新该条目,但第二次调用由于死锁而完全失败,我怎样才能使第二次调用等待第一次调用一个完成?

答案

在我看来你可以使用这里简单的.update()方法: obj=model.objects.filter(id=id).update(completed=True) 更重要的是,您可以将所有代码重构为this

obj, created = model.objects.update_or_create(
    id=id,
    defaults={'id': x, 'user': y, 'completed': True}
)

以上是关于Django使用transaction.atomic“死锁”的主要内容,如果未能解决你的问题,请参考以下文章

django使用已有的数据库表怎么建立model

Django web 开发 - Django的使用

Django-下载安装-配置-创建django项目-三板斧简单使用

使用Django返回helloworld

使用Django返回helloworld

使用Django返回helloworld