django - 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)
甚至,您可以将所有代码重构为:
obj, created = model.objects.update_or_create(
id=id,
defaults={'id': x, 'user': y, 'completed': True}
)