web-dev-qa-db-fra.com

SQLAlchemy: Quelle est la différence entre flush () et commit ()?

Quelle est la différence entre flush() et commit() dans SQLAlchemy?

J'ai lu les documents, mais je ne suis pas plus sage - ils semblent présumer que je ne les ai pas compris.

Je suis particulièrement intéressé par leur impact sur l'utilisation de la mémoire. Je charge des données dans une base de données à partir d'une série de fichiers (environ 5 millions de lignes au total) et ma session est parfois en train de basculer. Il s'agit d'une base de données volumineuse et d'une machine ne disposant pas de beaucoup de mémoire.

Je me demande si j'utilise trop d'appels commit() et pas assez flush() - mais sans vraiment comprendre la différence, c'est difficile à dire!

361
AP257

Un objet de session est essentiellement une transaction en cours de modification d'une base de données (mise à jour, insertion, suppression). Ces opérations ne sont pas conservées dans la base de données jusqu'à ce qu'elles soient validées (si votre programme abandonne pour une raison quelconque dans une transaction en milieu de session, toutes les modifications non validées sont perdues).

L'objet de session enregistre les opérations de transaction avec session.add(), mais ne les communique pas encore à la base de données jusqu'à ce que session.flush() soit appelé.

session.flush() communique une série d'opérations à la base de données (insertion, mise à jour, suppression). La base de données les maintient en tant qu'opérations en attente dans une transaction. Les modifications ne sont pas conservées de manière permanente sur le disque ou visibles pour d'autres transactions jusqu'à ce que la base de données reçoive un COMMIT pour la transaction en cours (ce que fait session.commit().).

session.commit() valide ces modifications dans la base de données.

flush() est toujours appelé dans le cadre d'un appel à commit() ( 1 ).

Lorsque vous utilisez un objet Session pour interroger la base de données, celle-ci renverra les résultats de la base de données et des parties vidées de la transaction non validée qu'elle contient. Par défaut, les objets Session autoflush leurs opérations, mais cela peut être désactivé.

Espérons que cet exemple rendra ceci plus clair:

#---
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')>]
445
snapshoe

Comme @snapshoe dit

flush() envoie vos instructions SQL à la base de données

commit() valide la transaction.

When session.autocommit == False:

commit () appellera flush () si votre autoflush == True.

Lorsque session.autocommit == True:

Vous ne pouvez pas appeler commit () si vous n'avez pas démarré de transaction (ce qui n'est probablement pas le cas puisque vous n'utiliseriez probablement que ce mode pour éviter de gérer manuellement les transactions).

Dans ce mode, vous devez appeler flush () pour enregistrer vos modifications ORM. Le flush valide également vos données.

16
Jacob