使用nowait = True的Django select_for_update不会因冲突的转换而引发DatabaseError

时间:2018-02-23 10:19:32

标签: python django database postgresql

根据Django文档:

  

通常,如果另一个事务已经对其中一个选定行获取了锁定,则查询将一直阻塞,直到锁定被释放。如果这不是您想要的行为,请调用select_for_update(nowait = True)。这将使呼叫无阻塞。如果另一个事务已经获取了冲突的锁,则在评估查询集时将引发DatabaseError。

我正在尝试这个,但发现了一个奇怪的行为。同时运行下面的代码并不会引发错误,但会以阻塞方式工作。

def test4():
with transaction.atomic():
    WorkflowCallContact.objects.select_for_update(nowait=True).filter(id__in=[1,2,3,4]).update(number="22222")
    time.sleep(10)
    list(WorkflowCallContact.objects.filter(id__in=[1,2,3,4]))

为了测试,我只是打开shell并且并行调用相同的函数。但是,由于DatabaseError而不是在第二次通话中抛出nowait=True,呼叫将被阻止10秒。

数据库我正在使用:postgres Django版本:1.9

1 个答案:

答案 0 :(得分:0)

select_for_update()update() 不能链接。您必须强制对 QuerySet 进行评估,例如将其转换为 list():

with transaction.atomic():
list(WorkflowCallContact.objects.select_for_update(nowait=True).filter(id__in=[1,2,3,4]))
WorkflowCallContact.objects.filter(id__in=[1,2,3,4]).update(number="22222")