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

kdt*_*kdt 13 python mysql django

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

我编写了一个函数,我认为应该以原子方式递增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
Run Code Online (Sandbox Code Playgroud)

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

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

Rem*_*emi 1

一般的经验法则是任何类型的自定义查询或自定义查询行为都应该进入管理器方法。 这对于您的情况来说是有意义的,因为您可以在非常低的级别上增加、保存和返回版本号:在实际查询期间。

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

另请参阅经理