Ответ вслух Senior Django ORM и N+1 спрашивают часто обновлено

Гонки данных в Django и как их предотвращать

Вопрос

Какие гонки данных возникают в Django-приложении и какими средствами вы с ними боретесь?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Образцовый ответ: «Самая частая гонка это потерянное обновление: два запроса читают объект, меняют поле и сохраняют, и одно изменение пропадает. Для счётчиков и балансов использую атомарные обновления на стороне БД: update(balance=F("balance") - x) с условием balancegte=x и проверкой, что обновилась одна строка.

Что должно прозвучать в ответе

  • Lost update: прочитал, изменил, записал

  • Атомарные обновления через F-выражения и условные update

  • `select_for_update` в `transaction.atomic`, порядок блокировок, `nowait` и `skip_locked`

  • Ограничения в БД: unique, check, как последняя линия защиты

  • Идемпотентность и уникальные ключи для повторных запросов

  • Побочные эффекты через `on_commit`

Что могут спросить следом

  • Чем select_for_update(skip_locked=True) полезен для очередей?
  • Как избежать дедлока при блокировке нескольких строк?

Разбор

Образцовый ответ: «Самая частая гонка это потерянное обновление: два запроса читают объект, меняют поле и сохраняют, и одно изменение пропадает. Для счётчиков и балансов использую атомарные обновления на стороне БД: update(balance=F("balance") - x) с условием balance__gte=x и проверкой, что обновилась одна строка. Когда нужна сложная логика с чтением, беру transaction.atomic и select_for_update, тогда параллельный запрос ждёт блокировку. При блокировке нескольких строк фиксирую порядок, например по id, чтобы не было дедлоков, а для обработки очереди задач в таблице использую skip_locked=True, чтобы воркеры не ждали друг друга. Последняя линия защиты это ограничения в самой БД: уникальные индексы, CheckConstraint, тогда даже при ошибке в коде данные не станут неконсистентными. От повторных запросов клиента спасают ключи идемпотентности. И все побочные эффекты, письма и задачи, отправляю через transaction.on_commit».

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.