Это безопасный способ увеличить и получить значение счетчика в Django? - PullRequest
13 голосов
/ 22 августа 2011

Я использую 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

Я думаю, что при двух одновременных вызовах ОБНОВЛЕНИЯ взаимно исключают одиндругой из-за блокировки записи, а затем REPEATABLE-READ должен гарантировать, что мой последующий .get даст мне значение после ОБНОВЛЕНИЯ.Я прав?

(Это не общий вопрос «как сделать атомный прирост?», Уже один из них. Это вопрос о том, действителен ли этот конкретный способ.)

1 Ответ

1 голос
/ 29 августа 2011

Общее эмпирическое правило заключается в том, что любые настраиваемые запросы или настраиваемое поведение запросов должны переходить в методы менеджера. Это имеет смысл в вашем случае, поскольку вы можете увеличивать, сохранять и возвращать версиючисло на очень низком уровне: во время самого запроса.

Таким образом, используйте менеджер (object = MyManager()) и напишите SQL-запрос, который увеличивает номер версии (UPDATE mytable SET version=(version+1) WHERE pk=pk, см. здесь ), и немедленно верните увеличенную версию модели.Например, перед выполнением любого другого вызова.

См. также Менеджеры

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...