Pourquoi tirer la chasse si vous pouvez vous engager ?
En tant que novice dans le domaine des bases de données et de sqlalchemy, je trouve les réponses précédentes - que flush()
envoie des instructions SQL à la base de données et commit()
les persiste - n'étaient pas claires pour moi. Les définitions ont un sens, mais il n'est pas immédiatement clair, à partir de ces définitions, pourquoi vous utilisez un flush au lieu de simplement commiter.
Étant donné qu'un commit vide toujours la mémoire ( https://docs.sqlalchemy.org/en/13/orm/session_basics.html#committing ), elles se ressemblent beaucoup. Je pense que le gros problème à souligner est qu'un flush n'est pas permanent et peut être annulé, alors qu'un commit est permanent, dans le sens où vous ne pouvez pas demander à la base de données d'annuler le dernier commit (je pense).
@snapshoe souligne que si vous voulez interroger la base de données et obtenir des résultats qui incluent les objets nouvellement ajoutés, vous devez d'abord effectuer un flush (ou un commit, qui effectuera le flush pour vous). Cela peut être utile pour certaines personnes, bien que je ne sois pas sûr de la raison pour laquelle vous voudriez faire un flush plutôt qu'un commit (à part la réponse triviale que cela peut être annulé).
Dans un autre exemple, je synchronisais des documents entre une base de données locale et un serveur distant, et si l'utilisateur décidait d'annuler, tous les ajouts/mises à jour/suppressions devaient être annulés (c'est-à-dire qu'il n'y avait pas de synchronisation partielle, seulement une synchronisation complète). Lors de la mise à jour d'un seul document, j'ai décidé de supprimer simplement l'ancienne ligne et d'ajouter la version mise à jour à partir du serveur distant. Il s'avère qu'en raison de la façon dont sqlalchemy est écrit, l'ordre des opérations lors de la validation n'est pas garanti. Cela a entraîné l'ajout d'une version en double (avant de tenter de supprimer l'ancienne), ce qui a fait échouer une contrainte unique dans la base de données. Pour contourner ce problème, j'ai utilisé flush()
afin que l'ordre soit maintenu, mais je pouvais toujours annuler si le processus de synchronisation échouait plus tard.
Voir mon billet à ce sujet à l'adresse suivante Y a-t-il un ordre pour l'ajout ou la suppression lors de la validation dans sqlalchemy ?
De même, quelqu'un voulait savoir si l'ordre d'ajout est maintenu lors de la validation, c'est-à-dire que si j'ajoute object1
puis ajoutez object2
, fait object1
sont ajoutés à la base de données avant object2
Est-ce que SQLAlchemy sauvegarde l'ordre lors de l'ajout d'objets à la session ?
Là encore, l'utilisation d'un flush() permettrait d'obtenir le comportement souhaité. Donc, en résumé, une utilisation de flush est de fournir des garanties d'ordre (je pense), encore une fois tout en vous permettant une option "undo" que commit ne fournit pas.
Autoflush et Autocommit
Notez que l'autoflush peut être utilisé pour s'assurer que les requêtes agissent sur une base de données mise à jour, car sqlalchemy fera un flush avant d'exécuter la requête. https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.params.autoflush
Autocommit est une autre chose que je ne comprends pas complètement, mais il semble que son utilisation soit déconseillée : https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.params.autocommit
Utilisation de la mémoire
La question originale voulait en fait connaître l'impact du flush par rapport au commit pour les besoins de la mémoire. Comme la possibilité de persister ou non est quelque chose que la base de données offre (je pense), un simple flush devrait être suffisant pour décharger vers la base de données - bien que le commit ne devrait pas faire de mal (en fait, il aide probablement - voir ci-dessous) si vous ne vous souciez pas d'annuler.
sqlalchemy utilise le référencement faible pour les objets qui ont été vidés : https://docs.sqlalchemy.org/en/13/orm/session_state_management.html#session-referencing-behavior
Cela signifie que si vous n'avez pas un objet explicitement maintenu quelque part, comme dans une liste ou un dict, sqlalchemy ne le gardera pas en mémoire.
Cependant, il faut alors se préoccuper de l'aspect base de données. On peut supposer que le fait de vider les données sans les valider entraîne une pénalité mémoire pour maintenir la transaction. Encore une fois, je suis novice en la matière, mais voici un lien qui semble suggérer exactement cela : https://stackoverflow.com/a/15305650/764365
En d'autres termes, les commits devraient réduire l'utilisation de la mémoire, bien que l'on puisse supposer qu'il existe un compromis entre la mémoire et les performances. En d'autres termes, vous ne souhaitez probablement pas valider chaque modification de la base de données, une par une (pour des raisons de performances), mais attendre trop longtemps augmentera l'utilisation de la mémoire.