Development #81133
wcs et transactions PG
0%
Description
On en a parlé tout à l'heure, j'ai creusé et voilà ce que j'ai trouvé...
https://www.psycopg.org/docs/connection.html#connection.autocommit
Ce paramètre est terriblement mal nommé.
Quand autocommit = False, par défaut, psycopg2 va automatiquement ouvrir une transaction à la première requête (donc en quelque sorte un autobegin), et si aucun .close(), .rollback() ou .commit() n'est réalisé, la session restera côté PG en idle in transaction.
Quand autocommit = True, psycopg2 ne fait plus rien, il se contente d'envoyer au PG les requêtes qu'on lui donne. Si on fait cursor.execute("begin"), alors on est dans une transaction.
Mais en dehors d'une transaction explicite, c'est PG qui ne fait que son fonctionnement par défaut où on peut, effectivement, considérer que chaque requête vit dans une transaction isolée automatique.
Le code de wcs/sql.py est couvert de commit() sur la plupart des chemins de code. Mais il en subsiste qui n'ont pas cet appel, comme SqlMixin::get, get_ids_from_query. À l'inverse, certaines fonctions enchaînent les .execute/.commit (par exemple SqlUser::get_reference_ids), ce qui est contre-productif puisque cela multiplie sans raison les fermetures de transaction alors que la ligne de code suivante va devoir en rouvrir une.
Pour ma part, je préfèrerais qu'on soit directement en autocommit = True, et qu'on protège par une transaction le code qui en a besoin. autocommit = False fait faire trop de magie à psycopg à mes yeux, et PG est bien assez grand pour clôturer la transaction dès que possible.
À défaut, il faut relire attentivement ce code pour s'assurer que tout soit bien fermé, et éventuellement chasser les ouvertures/fermetures successives inutiles.
Pour aussi voir les conséquences que ça a sur le pgbouncer, bien que non critiques : en autocommit = True, pgbouncer aura moins de messages à traiter certes, mais surtout les transactions seront plus courtes. Sur un strace cette nuit en recette, j'ai mesuré :
1694555871.298653 recvfrom(11, "Q\0\0\0\nBEGIN\0", 4096, 0, NULL, NULL) 1694555871.299041 sendto(11, "C\0\0\0\nBEGIN\0Z\0\0\0\5T", 17, 0, NULL, 0) 1694555871.299170 recvfrom(11, "Q\0\0\0\263SELECT id, title, s... ... 1694555871.302228 sendto(11, "9c9-8299-... 1694555871.302437 recvfrom(11, "Q\0\0\0\vCOMMIT\0", 4096, 0, NULL, NULL) 1694555871.302809 sendto(11, "C\0\0\0\vCOMMIT\0Z\0\0\0\5I", 18, 0, NULL, 0)
En autocommit = True, la transaction aurait duré environ 3ms, elle en a duré 4. L'écart est faible en absolu, mais c'est tout de même 30% de temps supplémentaire, et la majorité des requêtes sont au moins aussi rapides que celle-ci. Dès qu'un BEGIN arrive, pgbouncer associe une session PostgreSQL au client qui la demande, et ne la libère qu'au COMMIT ou ROLLBACK suivant.
Demandes liées
Révisions associées
sql: get rid of guard_postgres (#81133)
this was no longer needed
tests: add test for sql.atomic() (#81133)
sql: introduce Atomic.partial_commit() (#81133)
Historique
Mis à jour par Benjamin Dauvergne il y a 8 mois
J'ai fait une analyse équivalente mais pas dans le contexte de l'utilisation d'un proxy mais pour l'utilisation des curseurs nommés ça aboutissait à la même conclusion (#57623-24).
Mis à jour par Robot Gitea il y a 8 mois
- Statut changé de Nouveau à En cours
- Assigné à mis à Pierre Ducroquet
Pierre Ducroquet (pducroquet) a ouvert une pull request sur Gitea concernant cette demande :
- URL : https://git.entrouvert.org/entrouvert/wcs/pulls/667
- Titre : WIP: sql: switch to autocommit (#81133)
- Modifications : https://git.entrouvert.org/entrouvert/wcs/pulls/667/files
Mis à jour par Frédéric Péters il y a 7 mois
- Lié à Development #81534: ajouter quelques conn.commit() ajouté
Mis à jour par Robot Gitea il y a 7 mois
- Statut changé de Solution proposée à En cours
Frédéric Péters (fpeters) a relu et demandé des modifications sur une pull request sur Gitea concernant cette demande :
Mis à jour par Robot Gitea il y a 6 mois
Frédéric Péters (fpeters) a relu et demandé des modifications sur une pull request sur Gitea concernant cette demande :
Mis à jour par Robot Gitea il y a 5 mois
- Statut changé de Solution proposée à Solution validée
Frédéric Péters (fpeters) a approuvé une pull request sur Gitea concernant cette demande :
Mis à jour par Robot Gitea il y a 5 mois
- Statut changé de Solution validée à Résolu (à déployer)
Frédéric Péters (fpeters) a mergé une pull request sur Gitea concernant cette demande :
- URL : https://git.entrouvert.org/entrouvert/wcs/pulls/667
- Titre : sql: switch to autocommit (#81133)
- Modifications : https://git.entrouvert.org/entrouvert/wcs/pulls/667/files
Mis à jour par Transition automatique il y a 5 mois
- Statut changé de Résolu (à déployer) à Solution déployée
sql: switch the postgresql connection to autocommit (#81133)
As explained in #81133, the autocommit=False behaviour of psycopg2 is not
something we really want. It will automatically open transactions on the
server, closing them only when we commit, thus changing most of the
queries from a single roundtrip to three roundtrips. It also creates
longer transactions, thus reducing the opportunities for pgbouncer to
multiplex them. Last but not least, it makes forgetting a single
commit() call far more dangerous since it would possible leave an idle in
transaction session.
This changes to autocommit=True, ie. psycopg doesn't try anything and let
PostgreSQL do one transaction per statement, except when we explicitely
ask for one, with the new @atomic decorator.