我将 MySQL 与 InnoDB 引擎和 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 后给我值。我对吗?
(这不是一般的“我如何进行原子增量?”问题,已经有一个。这是关于这种特定方式是否有效。)
最佳答案
一般的经验法则是 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
关于python - 这是在 Django 中递增和获取计数器值的安全方法吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7148859/