SQLAlchemy: В чем разница между flush () и commit ()? - PullRequest
356 голосов
/ 17 ноября 2010

В чем разница между flush() и commit() в SQLAlchemy?

Я читал документы, но не мудрый - они, кажется, предполагают, что я не понимаюhave.

Меня особенно интересует их влияние на использование памяти.Я загружаю некоторые данные в базу данных из ряда файлов (всего около 5 миллионов строк), и моя сессия иногда падает - это большая база данных и машина с небольшим объемом памяти.

Мне интересно, если я использую слишком много commit() и недостаточно flush() звонков - но без реального понимания, в чем разница, трудно сказать!

Ответы [ 2 ]

434 голосов
/ 17 ноября 2010

Объект Session - это, по сути, текущая транзакция изменений базы данных (обновление, вставка, удаление). Эти операции не сохраняются в базе данных до тех пор, пока они не будут зафиксированы (если ваша программа по какой-то причине прерывается во время транзакции в середине сеанса, все незафиксированные изменения внутри нее теряются).

Объект сеанса регистрирует транзакции с помощью session.add(), но еще не передает их в базу данных, пока не будет вызван session.flush().

session.flush() передает серию операций в базу данных (вставка, обновление, удаление). База данных поддерживает их как ожидающие операции в транзакции. Изменения не сохраняются постоянно на диске или не видны другим транзакциям, пока база данных не получит COMMIT для текущей транзакции (что и делает session.commit()).

session.commit() фиксирует (сохраняет) эти изменения в базе данных.

flush() - это всегда , вызываемый как часть вызова commit() ( 1 ).

Когда вы используете объект Session для запроса к базе данных, запрос будет возвращать результаты как из базы данных, так и из очищенных частей незафиксированной транзакции, которую он содержит. По умолчанию объекты Session autoflush выполняют свои операции, но это можно отключить.

Надеюсь, этот пример прояснит ситуацию:

#---
s = Session()

s.add(Foo('A')) # The Foo('A') object has been added to the session.
                # It has not been committed to the database yet,
                #   but is returned as part of a query.
print 1, s.query(Foo).all()
s.commit()

#---
s2 = Session()
s2.autoflush = False

s2.add(Foo('B'))
print 2, s2.query(Foo).all() # The Foo('B') object is *not* returned
                             #   as part of this query because it hasn't
                             #   been flushed yet.
s2.flush()                   # Now, Foo('B') is in the same state as
                             #   Foo('A') was above.
print 3, s2.query(Foo).all() 
s2.rollback()                # Foo('B') has not been committed, and rolling
                             #   back the session's transaction removes it
                             #   from the session.
print 4, s2.query(Foo).all()

#---
Output:
1 [<Foo('A')>]
2 [<Foo('A')>]
3 [<Foo('A')>, <Foo('B')>]
4 [<Foo('A')>]
15 голосов
/ 16 октября 2016

Как говорит @snapshoe

flush() отправляет ваши операторы SQL в базу данных

commit() фиксирует транзакцию.

Когда session.autocommit == False:

commit () вызовет flush (), если ваш autoflush == True.

Когда session.autocommit == True:

Вы не можете вызвать commit (), если вы еще не начали транзакцию (чего вы, вероятно, не сделали, поскольку вы, вероятно, будете использовать только эторежим, чтобы избежать ручного управления транзакциями).

В этом режиме вы должны вызвать flush (), чтобы сохранить изменения ORM.Сброс также эффективно фиксирует ваши данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...