v18o
v18o

Reputation: 1297

Django race condition inside a transaction

I have Django 1.11 app with PostgreSQL. Take a look at code below.

Is it possible to have race condition there? I am afraid I could get race condition on diff=-account.hours. Does transaction.atomic save from race condition?

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)

Upvotes: 0

Views: 1907

Answers (1)

Alasdair
Alasdair

Reputation: 308839

The transaction.atomic() means that all your objects are created/saved in a single transaction, or none of them are. It does not prevent the accounts being modified by another request.

You could look at select_for_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

Upvotes: 5

Related Questions