我有一个简单的数据库关系:一个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。
答案 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, ...)