这是一种在Django中增加和获取计数器值的安全方法吗?

时间:2011-08-22 14:17:23

标签: python mysql django

我正在使用带有InnoDB引擎的MySQL和REPEATABLE-READ隔离级别。

我编写了一个函数,我认为应该以原子方式递增IntegerField,并在增量后给出值。我希望看看我的代码是否能够抵御并发问题。

我的代码如下所示:

class MyModel(models.Model):
  version = models.IntegerField()

  @staticmethod
  @transaction.commit_on_success
  def acquire_version(pk):
    MyModel.objects.filter(pk = pk).update(version = F('version') + 1)
    return MyModel.objects.get(pk = pk).version

我的想法是,在两个并发调用中,由于写入锁定,UPDATE将相互排斥,然后REPEATABLE-READ应保证我的后续.get将在UPDATE之后给出值。我是对的吗?

(这不是一般性的“我如何进行原子增量?”问题,已经存在其中之一。这是关于这种特定方式是否有效。)

1 个答案:

答案 0 :(得分:1)

一般的经验法则是any sort of custom queries or customized query behavior should go into manager methods. 这在您的情况下是有意义的,因为您可以在非常低的级别增加,保存和返回版本号:在实际查询期间。

因此,使用管理器(object = MyManager())并编写一个SQL查询,增加版本号(UPDATE mytable SET version=(version+1) WHERE pk=pk,参见here),并立即返回模型实例的递增版本,在任何其他电话可以执行之前。

另见Managers