Django比赛条件

时间:2014-01-24 10:00:07

标签: django postgresql race-condition

使用Django ORM避免竞争条件的最佳方法是什么?我正在使用Postgres数据库。以下是易受竞争条件影响的代码的简化版本(很少但可能发生):

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()

如果两个单独的处理同时执行上面的代码怎么办?

假设使用account_id 123的数据库中的最后一个条目的余额为100。

第一个进程将插入一个平衡增加100的新条目,即200。

第二个流程将插入一个新的条目,余额增加100,即200。

但它应该从200增加到300,因为另一个进程在此期间插入了一个新行。

1 个答案:

答案 0 :(得分:0)

我不认为你所描述的是一个很好的方法来解决你的问题。我要做的是,我要创建一个Deposit模型,该模型对帐户有ForeignKey并保存存款的日期和存入的金额(可能还需要其他信息) )。

现在,我只需添加一个新的Deposit,然后每次只需将所有相关的Deposit相加(并类似地减去Withdrawal,我就可以获得该帐户的余额或多个)。

当然可能有其他用例实际上需要表锁定以确保表中的行不会在SQL语句之间发生更改,但这些是特定于数据库的并且与django无关。为了完整起见,我在这里找到了对postgresql表锁定的一个非常好的介绍http://www.postgresql.org/docs/9.1/static/explicit-locking.html - ACCESS EXCLUSIVE表级锁定似乎解决了你的问题(不过我想到了在使用可能导致死锁的事情之前进行设计。)