F() выполняет изменение относительно текущего значения прямо в SQL: update(counter=F('counter') + 1). Это устраняет потерю инкрементов из-за схемы «прочитать в Python, увеличить, записать».
Как в Django ORM использовать F()-выражения для предотвращения состояния гонки (Race Condition) при обновлении счётчиков?
F() выполняет изменение относительно текущего значения прямо в SQL: update(counter=F('counter') + 1). Это устраняет потерю инкрементов из-за схемы «прочитать в Python, увеличить, записать».
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
F() выполняет изменение относительно текущего значения прямо в SQL: update(counter=F('counter') + 1). Это устраняет потерю инкрементов из-за схемы «прочитать в Python, увеличить, записать».
Пример:
from django.db.models import F
Counter.objects.filter(pk=counter_id).update(value=F('value') + 1)
Два конкурентных инкремента не записывают одно и то же старое значение. Объект, ранее загруженный в память, нужно обновить из БД для чтения результата. Но F() не делает атомарной произвольную последовательность действий: проверка остатка должна входить в условие UPDATE, а многострочный бизнес-инвариант требует транзакционной защиты.