Django,如何使视图成为原子?
我有一个简单的Django应用程序,用来模拟股票市场,用户可以进来买卖股票。当他们选择进行交易时,
- 首先会读取市场价格,
- 然后根据买入或卖出的订单来调整市场价格,可能会增加或减少。
我不太确定在Django中这个是怎么运作的,但我想知道有没有办法让这个视图是原子的?也就是说,我担心用户A的操作可能会读取到价格,但在他的订单更新之前,用户B的操作也读取了这个价格。
我在网上找不到简单明了的解决方案。谢谢。
3 个回答
把读取数据库和更新数据库的操作放在一个事务里。具体的写法要看你使用的是什么ORM工具。
这个问题虽然比较老,但自从 1.6 版本开始,你可以把 transaction.atomic()
当作一个装饰器来使用。
views.py
@transaction.atomic()
def stock_action(request):
#trade here
这是关于数据库事务的一些说明,主要针对Postgresql。所有数据库都有锁定机制,但具体细节各不相同。
很多数据库在默认情况下并不会进行这么严格的锁定,即使你在一个事务中。你需要对数据进行明确的锁定。
在Postgresql中,你可能需要使用SELECT ... FOR UPDATE,这样可以锁定返回的行。每次想要阻止其他用户更新这些行的SELECT语句都需要加上FOR UPDATE。
不幸的是,在Django的ORM中没有直接的方法可以使用FOR UPDATE。你可能需要稍微修改一下ORM,或者使用原始SQL,按照我所知道的。如果你的代码性能要求不高,并且可以接受对整个表的访问进行串行处理,你可以使用表级的LOCK IN EXCLUSIVE MODE,这样会对整个表进行锁定。
http://www.postgresql.org/docs/current/static/explicit-locking.html
http://www.postgresql.org/docs/current/static/sql-lock.html
http://www.postgresql.org/docs/current/static/sql-select.html