Зачем сбрасывать, если вы можете зафиксировать?
Как новичок в работе с базами данных и sqlalchemy, предыдущие ответы - что flush()
отправляет операторы SQL в БД, а commit()
сохраняет их - были мне непонятны. Определения имеют смысл, но из определений не сразу понятно, почему вы должны использовать сброс, а не просто фиксацию.
Поскольку коммит всегда сбрасывается (https://docs.sqlalchemy.org/en/13/orm/session_basics.html#committing), это звучит очень похоже. Я думаю, что большая проблема, которую следует выделить, заключается в том, что сброс не является постоянным и может быть отменен, тогда как фиксация является постоянной в том смысле, что вы не можете попросить базу данных отменить последнюю фиксацию (я думаю)
@snapshoe подчеркивает, что если вы хотите запросить базу данных и получить результаты, включающие недавно добавленные объекты, вам необходимо сначала выполнить очистку (или выполнить фиксацию, которая очистится для вас). Возможно, это полезно для некоторых людей, хотя я не уверен, почему вы хотите сбросить, а не зафиксировать (кроме тривиального ответа, что это можно отменить).
В другом примере я синхронизировал документы между локальной базой данных и удаленным сервером, и если пользователь решил отменить, все добавления / обновления / удаления должны быть отменены (т.е. не частичная синхронизация, только полная синхронизация). При обновлении одного документа я решил просто удалить старую строку и добавить обновленную версию с удаленного сервера. Оказывается, из-за того, как написана sqlalchemy, порядок операций при фиксации не гарантируется. Это привело к добавлению дублирующей версии (перед попыткой удаления старой), что привело к сбоям в БД уникального ограничения. Чтобы обойти это, я использовал flush()
, чтобы этот порядок поддерживался, но я все равно мог отменить, если позже процесс синхронизации не удался.
См. Мой пост по этому поводу: Есть ли какой-либо порядок добавления или удаления при фиксации в sqlalchemy
Точно так же кто-то хотел знать, сохраняется ли порядок добавления при фиксации, т.е. если я добавляю object1
, а затем добавляю object2
, object1
добавляется в базу данных до object2
Сохраняет ли SQLAlchemy порядок при добавлении объектов в сеанс?
Опять же, здесь, по-видимому, использование flush () обеспечит желаемое поведение. Таким образом, одним из способов использования промывки является обеспечение гарантии порядка (я думаю), опять же, позволяя себе возможность «отменить», которую коммит не предоставляет.
Автозапуск и автоматическая фиксация
Обратите внимание: автозапуск можно использовать для обеспечения того, чтобы запросы действовали в обновленной базе данных, поскольку sqlalchemy будет сбрасывать данные перед выполнением запроса. https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush
Autocommit - это кое-что еще, что я не совсем понимаю, но похоже, что его использование не рекомендуется:
https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.params.autocommit
Использование памяти
Теперь исходный вопрос действительно хотел знать о влиянии сброса и фиксации на память. Поскольку способность сохраняться или нет - это то, что предлагает база данных (я думаю), простой промывки должно быть достаточно для разгрузки в базу данных - хотя фиксация не должна повредить (на самом деле, вероятно, помогает - см. Ниже), если вы не заботитесь об отмене .
sqlalchemy использует слабые ссылки для объектов, которые были сброшены: https://docs.sqlalchemy.org/en/13/orm/session_state_management.html#session-referencing-behavior <4> <354>
Это означает, что если у вас нет объекта, явно закрепленного где-то, например, в списке или dict, sqlalchemy не будет хранить его в памяти.
Однако тогда у вас есть проблемы с базой данных. Предположительно, сброс без фиксации приводит к некоторой потере памяти для поддержки транзакции. Опять же, я новичок в этом, но вот ссылка, которая, кажется, предлагает именно это: https://coderhelper.com/a/15305650/764365
Другими словами, коммиты должны уменьшить использование памяти, хотя, по-видимому, здесь есть компромисс между памятью и производительностью. Другими словами, вы, вероятно, не захотите фиксировать каждое изменение базы данных по одному (из соображений производительности), но слишком долгое ожидание приведет к увеличению использования памяти.
И еще кое-что: знаете ли вы, увеличивает ли использование памяти при вызове commit () или уменьшает ее?
Это также неверно для движков db, которые не поддерживают транзакции, такие как myisam. Поскольку текущая транзакция отсутствует, flush еще меньше отличается от фиксации.
@underrun Итак, если я сделаю
session.query()
послеsession.flush()
, увижу ли я свои изменения? Учитывая, что я использую MyISAM.Хорошо или плохо использовать
flush()
иcommit()
, или я должен оставить это на усмотрение Алхимии. В некоторых случаях я использовалflush()
, потому что последующие запросы требовали получения новых данных.@FrozenFlame да, поскольку данные видны вам внутри транзакции. Просто еще нет в других сделках.
@Jens Используйте
autoflush
(по умолчаниюTrue
). Он автоматически сбрасывается перед всеми запросами, поэтому вам не нужно каждый раз запоминать.Вот хорошее объяснение. michaelcho.me/article/…