【问题标题】:Django select_for_update with nowait=True not raising DatabaseError for conflicting transctions带有 nowait=True 的 Django select_for_update 不会为冲突事务引发数据库错误
【发布时间】:2018-08-03 09:01:52
【问题描述】:

根据 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 并并行调用相同的函数。但是由于nowait=True,第二次调用并没有抛出DatabaseError,而是阻塞了10秒。

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

【问题讨论】:

  • 我建议您找出哪些语句被发送到数据库,如有必要,通过设置log_statement = all

标签: python django database postgresql


【解决方案1】:

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")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2014-10-16
    • 2017-07-13
    • 1970-01-01
    相关资源
    最近更新 更多