Безопасны ли последовательные вызовы сохранения моделей в django?
У меня проблемы с полем, которое иногда не обновляется. Просто хочу знать, является ли следующее небезопасным для экземпляра модели Django.
obj.field1 = True
obj.save()
obj.field2 = True
obj.save()
Поскольку я не вызываю obj.update_from_db(), есть ли риск, что второе сохранение сбросит/отменит field1
?
Здесь нет хуков post_save, окружающий код синхронный, а бэкенд БД - PostgreSQL.
Кроме того, является ли функция save() синхронной (в том смысле, что обновление БД произойдет до возвращения функции)?
Если вы используете PyCharm, вы всегда можете зайти ctrl+b
и проверить функцию.
Из того, что я вижу, нет ни await, ни async, так что это должно быть синхронно.
В любом случае. Это может стать небольшой проблемой, когда вы развернете его, например, на Apache
и сделаете 2 или более экземпляров. Если эти несколько экземпляров используют одну и ту же базу данных, то могут возникнуть некоторые проблемы. Но обычно эта проблема решается на стороне db (если вы используете только «известные»).
Ответ: должно быть безопасно для использования.
.save()
вообще говоря, строго синхронна. Это означает, что при вызове .save()
фиксация будет успешной до того, как метод вернется (или она будет неудачной, и метод выбросит исключение).
Есть несколько ситуаций, когда это необязательно (но они больше относятся к продвинутым вариантам использования):
with transaction.atomic()
контекст -.save()
может быть успешным (и вернуться!), но персистентность не будет пытаться до конца транзакции .
- Аналогично вышеизложенному, если вы работаете с таблицей, имеющей ограничение
DEFERRABLE INITIALLY DEFERRED
, Postgres сохранит изменения в этом столбце только в конце транзакции .
- В зависимости от логической структуры вашего приложения, уровни изоляции, к сожалению, могут иметь значение. Это означает, что для всех уровней изоляции, кроме самого строгого, вы можете создать ситуацию, когда
.save()
возвращается синхронно, но при извлечении данных постфактум вы можете увидеть «неправильные» данные (разные уровни изоляции будут иметь разные паттерны для создания такого сценария). Все они связаны с тем, что чтение происходит одновременно с записью, поэтому такую проблему можно ожидать только при больших объемах и низкой частоте. Это не проблема самого.save()
, а скорее замечание о том, что гипотетически возможно, что.save()
работает именно так, как ожидалось, но с неожиданными чтениями данных во время/после этого.
Команда model.save() сохраняет всю информацию о полях текущей модели в db.
Если вы хотите сохранить только определенные поля, добавьте информацию update_fields.
model.save(update_fields=['aaa'])
По рекомендации django.seolpyo.com
я обнаружил, что проблема решается, если ограничить update_fields
только полями, которые я изменяю. Это позволило устранить некоторые условия гонки, когда разные процессы работали с одной и той же моделью, но с разными полями. Просто вызов save()
без ограничения полей часто приводил к тому, что устаревшие данные записывались поверх недавно обновленных.
Если ваша программа однопоточная, это обычно не является проблемой, но в моем случае 2 разных процесса работали над одной моделью.