在重写表的各个部分时如何实现数据库一致性?

时间:2014-08-25 18:13:25

标签: django postgresql django-orm database-locking

我有一个简单的数据库关系:一个Item涉及许多ItemDetails。 ItemDetails一次更新:一条消息通过HTTP POST传入,其中包含完整的ItemDetails集合以替换任何旧的ItemDetails。我使用的逻辑是:

with transaction.atomic():
    ...
    ItemDetails.objects.filter(item_id=item_id).all().delete()
    for item in new_item_list:
        ItemDetails.objects.create(title=item.title, ...)

但是如果两个发件人同时发送更新,这似乎有竞争条件。我有时会看到重复的列表,因为(我认为)delete()在或多或少并行的两个线程上运行,然后创建发生。

我可以使用什么锁定策略来避免此问题?我正在使用Django和PostgreSQL。

1 个答案:

答案 0 :(得分:0)

正如问题评论中所指出的,一个Django / Postgres解决方案是在正确的select_for_update()行上使用Item,然后再与孩子们交谈。这导致Django阻止等待锁定。因此,将逻辑更改为以下内容可以修复竞争条件:

with transaction.atomic():
    # Just add this and Django will block here until other threads let go.
    item = Item.objects.select_for_update().get(pk=item_id)
    ...
    ItemDetails.objects.filter(item_id=item_id).all().delete()
    for item in new_item_list:
        ItemDetails.objects.create(title=item.title, ...)