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


Какая разница между flush() и commit() в SQLAlchemy?

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

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

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



Answers


Объект 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')>]



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

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

commit() совершает транзакцию.

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

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

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

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

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