Django select_for_update(nowait=False) в transaction.atomic() работает не так, как ожидалось

У меня есть приложение django, которому нужно получить уникальный ID. Одновременно работает много потоков, которым нужен один. Я бы хотел, чтобы идентификаторы были последовательными. Когда мне нужен уникальный ID, я делаю следующее:

with transaction.atomic():
    max_batch_id = JobStatus.objects.select_for_update(nowait=False).aggregate(Max('batch_id'))
    json_dict['batch_id'] = max_batch_id['batch_id__max'] + 1
    status_row = JobStatus(**json_dict)
    status_row.save()

Но несколько заданий получают один и тот же ID. Почему код работает не так, как я ожидаю? Какой способ лучше для достижения того, что мне нужно? Я не могу использовать идентификатор строки, так как есть много строк, имеющих одинаковый batch_id.

Как говорится в документации Django в Docs, вы можете использовать F() для предотвращения состояния гонки:

Этот процесс можно сделать надежным, избегая состояния гонки, а также немного ускорить, если выразить обновление относительно исходного значения поля, а не как явное присвоение нового значения. Django предоставляет F-выражения для выполнения такого рода относительного обновления.

Так что вы, вероятно, хотите чего-нибудь вроде этого:

...
max_batch_id = JobStatus.objects.select_for_update(nowait=False).aggregate(Max(F('batch_id')))
...
Вернуться на верх