Уровень изоляции по умолчанию не позволяет работать следующему коду; отдельные процессы могут считывать одно и то же значение, устанавливать одно и то же значение и вызывать ошибочный подсчет.
def next_id():
with transaction.atomic():
db_counter = Counter.objects.filter(name=name).first()
if not db_counter:
# Create count if not exists
db_counter = Counter.objects.create(name=name, count=0)
count = db_counter.count
db_counter.count = count + 1
db_counter.save()
return count
Некоторые вещи, на которые я смотрел:
- Установка уровня изоляции на
serializable
работает, но я боюсь, что это слишком ограничительно. Остальная часть приложения работает нормально с repeatable read
. - . select_for_update может работать, но я не знаю, как применять его в случае, если счетчик отсутствует, и запись должна быть добавлена.
- Я проследил через код Django / MySQL с помощью отладчика: я не уверен, что
transaction.atomic()
что-то делает, я не вижу, чтобы он испускал START TRANSACTION
.
Как попросить Django начать транзакцию? Спасибо.