Python 事务内的Django竞争条件

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

我有一个带有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 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