使用PostgreSQL获得Django的下一个工作项目



想象一下您有一个带有工作项目的简单表:

|ID |OWNER|...
+---+-----+---
|123|     |...
|456|     |...
|789|     |...

我们想提供HTTP API,以获取尚未拥有所有者的下一个工作项目。

我们使用postgresql。

我们使用django-orm访问表。

我想如果许多用户同时获得API,则有几个种族条件。

我如何确保给定工具(PostgreSQL,django(都解决了所有种族条件(如果给出两个矿石的用户,这是一个主要错误(。

带有django 1.11,select_for_update开始支持 skip_locked。这意味着您可以保存save()调用,因为您不必立即将其分配给所有者。

例如,在 @user73657的答案上构建:

with transaction.atomic():
    work_item = WorkItem.objects.select_for_update().filter(owner__isnull=True).first()
    work_item.owner = request.user
    work_item.save(update_fields=['owner'])
# process work_item

您可以做:

with transaction.atomic():
    work_item = WorkItem.objects.select_for_update(skip_locked=True).filter(owner__isnull=True).first()
    work_item.owner = request.user
    # process work_item, edit other fields
    work_item.save()

使用skip_locked=True,交易跳过了锁定的行,因此是非障碍物。作为奖励,您只需要保存到db

with select_for_update

with transaction.atomic():
    work_item = WorkItem.objects.select_for_update().filter(owner__isnull=True).first()
    work_item.owner = request.user
    work_item.save(update_fields=['owner'])
# process work_item

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#select-for-pordate

select_for_update将确保只有一个连接可以更新匹配行,直到交易结束为止。

最新更新