Django:在字段中维护计数器(竞赛条件)

时间:2018-07-25 10:39:23

标签: django transactions race-condition

我有一个与此示例相似的模型

a

这个想法是,对于每个Foo,将有一系列@transaction.atomic从1开始编号,然后依次编号。

问题在于,即使我们有A -> Get max -> 42 B -> Get max -> 42 A -> Set max + 1 A -> save B -> Set max + 1 B -> save Both will be 43 ,也存在竞争条件,因为Django期望的事务隔离级别将允许事务同时运行,即

{{1}}

那么我该如何解决呢?有没有办法自动设置计数器,以便在获取当前最大值和插入新值之间没有竞争条件?

这个问题是similar to this one,但又相差甚远,以至于这个问题并没有提供我具体示例的答案

1 个答案:

答案 0 :(得分:2)

签出select_for_update。如文档所述:

  

返回一个查询集,该查询集将锁定行直到事务结束,从而在支持的数据库上生成SELECT ... FOR UPDATE SQL语句。

或者,哈基·贝纳塔(Haki Benata)在https://web.archive.org/web/20170707121253/https://medium.com/@hakibenita/how-to-manage-concurrency-in-django-models-b240fed4ee2定义了两种方法,可能会很有趣

最后,如果您需要锁定整个表,则有一个method描述可以使您做到这一点。有效地,您可以创建一个锁定上下文管理器,该管理器获取一个完整的表锁并在退出时将其释放