helado
helado

Reputation: 895

Django concurrent get-and-increment

Lets say I have a model A which has an account_number field and when a new instance of A is created a counter field in my model B increments it's value by one. This value will be the same that my account_number field will receive.

I want to protect the operation from concurrent modifications so that my account_number is always the correct one.

I want to do something like the following:

instance.account_number = F('modelB_table.counter') + 1

also updating the counter value in B

How can I achieve this in Django 1.9?

Could transactions be helpful in this case?

Upvotes: 2

Views: 694

Answers (1)

Kevin Christopher Henry
Kevin Christopher Henry

Reputation: 49092

Yes, you can achieve this in Django using transactions. You'd do something like:

with transaction.atomic():
    ModelB.objects.update(counter=F('counter') + 1)
    new_counter = ModelB.objects.get().counter
    a_instance.account_number = new_counter
    a_instance.save()

This needs to be done at a transaction isolation level of READ_COMMITTED or above. (In PostgreSQL the default isolation level is READ_COMMITTED, I'm not sure about other databases.)

It works because that isolation level makes dirty reads impossible, so there's no way for a concurrent transaction to update the counter until the other commits.

Upvotes: 3

Related Questions