Domanda

What is the best way to avoid race conditions with Django ORM? I am using Postgres database. Here is a simplified version of the code which is vulnerable to race conditions (rare but can happen):

last_account_balance = AccountBalance.objects.filter(
    account_id=account_id
).last()

new_account_balance = AccountBalance(
    account_id=account_id,
    balance= last_account_balance.balance + 100
)

new_account_balance.save()

What if two separate processed execute the code above at the same time?

Let's say the last entry in the database with account_id 123 has balance of 100.

First process will insert a new entry with balance increased by 100, that is 200.

Second process will insert a new entry with balance increased by 100, that is 200 as well.

But it should increase from 200 to 300 as another process inserted a new row in the meantime.

È stato utile?

Soluzione

I don't think that what you are describing is a very good approach to your problem. What I'd do instead is that I'd create a Deposit Model which would have a ForeignKey to the account and save the date of the deposit and the amount that was deposited (and probably other information needed).

Now, I'd just add a new Deposit and then I could get the Balance of the account each time just by summing all the related Deposits (and similarly subtracting Withdrawals).

Of course there could be other usage cases that would actually need table locking to be sure that rows in a table do not change between SQL statements, however these are database specific and not really related to django. For completeness, I've found a very nice introduction to postgresql table locking here http://www.postgresql.org/docs/9.1/static/explicit-locking.html -- the ACCESS EXCLUSIVE table-level lock seems to be what'd solve your problem (however I'd double think my design before using things that could lead to deadlocks).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top