【问题标题】:Is this a safe way to increment and get the value of a counter in Django?这是在 Django 中递增和获取计数器值的安全方法吗?
【发布时间】:2011-11-01 04:59:49
【问题描述】:

我正在使用带有 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

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

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

【问题讨论】:

标签: python mysql django


【解决方案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

【讨论】:

  • 好的,但问题中给出的代码是正确的还是错误的?
  • 我认为它更危险,因为 .update() 的实际实现可以独立于 Django 版本。此外,您正在进行双重甚至可能是三重查找。老实说,我不知道它(目前)是否正确。
猜你喜欢
  • 2017-03-03
  • 2013-09-08
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多