web-dev-qa-db-ja.com

SQLAlchemy:flush()とcommit()の違いは何ですか?

SQLAlchemyのflush()commit()の違いは何ですか?

私はドキュメントを読みましたが、賢明ではありません-彼らは私が持っていないことを事前に理解しているようです。

特にメモリ使用量への影響に興味があります。一連のファイル(合計約500万行)からデータベースにデータを読み込んでいますが、セッションが時々失敗することがあります-それは大きなデータベースであり、メモリの少ないマシンです。

使用しているcommit()の数が多すぎてflush()の呼び出しが十分ではないのではないかと思っています-しかし、実際に違いが何であるかを理解しないと、わかりにくいです!

351
AP257

Sessionオブジェクトは、基本的に、データベースに対する変更(更新、挿入、削除)の進行中のトランザクションです。これらの操作は、コミットされるまでデータベースに保持されません(セッション中のトランザクションで何らかの理由でプログラムが中止されると、コミットされていない変更は失われます)。

セッションオブジェクトは、session.add()を使用してトランザクション操作を登録しますが、session.flush()が呼び出されるまで、データベースとの通信をまだ行いません。

session.flush()は、一連の操作をデータベースに通知します(挿入、更新、削除)。データベースは、それらをトランザクションの保留中の操作として保持します。データベースに現在のトランザクションのCOMMITを受信するまで、変更は永続的にディスクに永続化されず、他のトランザクションからも見えません(これはsession.commit()が行うことです)。

session.commit()は、これらの変更をデータベースにコミット(永続化)します。

flush()は、alwayscommit()の呼び出しの一部として呼び出されます( 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')>]
429
snapshoe

@snapshoeが言うように

flush()はSQLステートメントをデータベースに送信します

commit()はトランザクションをコミットします。

session.autocommit == Falseの場合:

autoflush == Trueの場合、commit()はflush()を呼び出します。

session.autocommit == True:の場合

トランザクションを開始していない場合、commit()を呼び出すことはできません(おそらく、手動でトランザクションを管理するのを避けるためにこのモードのみを使用するため、おそらく開始していません)。

このモードでは、flush()を呼び出してORMの変更を保存する必要があります。フラッシュはデータを効果的にコミットします。

15
Jacob