Python 事务内的Django竞争条件
我有一个带有PostgreSQL的Django 1.11应用程序。 请看下面的代码 有可能有比赛条件吗?恐怕我可以在Python 事务内的Django竞争条件,python,django,postgresql,Python,Django,Postgresql,我有一个带有PostgreSQL的Django 1.11应用程序。 请看下面的代码 有可能有比赛条件吗?恐怕我可以在diff=-account.hours上获得比赛条件。transaction.atomic是否从竞争条件中保存 from django.db import transaction def write_off(account_ids): accounts = Account.objects.filter(id__in=account_ids) for account
diff=-account.hours
上获得比赛条件。transaction.atomic
是否从竞争条件中保存
from django.db import transaction
def write_off(account_ids):
accounts = Account.objects.filter(id__in=account_ids)
for account in accounts:
with transaction.atomic():
MyLog.objects.create(
hours=0,
operation_type=LOG_OPERATION_WRITE_OFF,
diff=-account.hours,
)
Account.objects.filter(pk=account.pk).update(hours=0)
atomic()表示您的所有对象都是在单个事务中创建/保存的,或者它们都不是。它不会阻止其他请求修改帐户
你可以看看:
atomic()表示您的所有对象都是在单个事务中创建/保存的,或者它们都不是。它不会阻止其他请求修改帐户
你可以看看:
从我看来,你的代码不应该工作<代码>帐户将是一个
查询集
而不是单个帐户
实例。因此,它将不会有.hours
和.pk
@klauds。我已经编辑了这个问题,谢谢。现在解释一下你在哪里看到了可能的比赛条件。比赛在哪里?@KlausD。在行diff=-account.hours
中。我以account
为例,将account.hours
保存到MyLog
,然后设置account.hours=0
。在我用过时的值创建MyLog
后,account.hours
的值是否可以更改?在我看来,您的代码不应该工作<代码>帐户将是一个查询集
而不是单个帐户
实例。因此,它将不会有.hours
和.pk
@klauds。我已经编辑了这个问题,谢谢。现在解释一下你在哪里看到了可能的比赛条件。比赛在哪里?@KlausD。在行diff=-account.hours
中。我以account
为例,将account.hours
保存到MyLog
,然后设置account.hours=0
。在我用过时的值创建MyLog
后,是否可以更改account.hours
的值?立即更新所有帐户不是一个好主意,因为如果一次更新失败,所有更新都将回滚。您可以重新排列代码以满足您的需要。请注意,select\u for\u update
必须位于原子块内。一次更新所有帐户不是一个好主意,因为如果一次更新失败,所有更新都将回滚。您可以重新排列代码以满足需要。请注意,select\u for\u update
必须位于原子块内。
def write_off(account_ids):
with transaction.atomic():
accounts = Account.objects.select_for_update().filter(id__in=account_ids)
for account in accounts:
MyLog.objects.create(
hours=0,
operation_type=LOG_OPERATION_WRITE_OFF,
diff=-account.hours,
)
accounts.update(hours=0) # use fewer queries by updating all accounts at once