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.
Related issues
Associated revisions
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)
History
Updated by Benjamin Dauvergne about 1 year ago
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).
Updated by Robot Gitea about 1 year ago
- Status changed from Nouveau to En cours
- Assignee set to 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
Updated by Frédéric Péters 12 months ago
- Related to Development #81534: ajouter quelques conn.commit() added
Updated by Robot Gitea 12 months ago
- Status changed from Solution proposée to En cours
Frédéric Péters (fpeters) a relu et demandé des modifications sur une pull request sur Gitea concernant cette demande :
Updated by Robot Gitea 11 months ago
Frédéric Péters (fpeters) a relu et demandé des modifications sur une pull request sur Gitea concernant cette demande :
Updated by Robot Gitea 10 months ago
- Status changed from Solution proposée to Solution validée
Frédéric Péters (fpeters) a approuvé une pull request sur Gitea concernant cette demande :
Updated by Robot Gitea 10 months ago
- Status changed from Solution validée to 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
Updated by Transition automatique 10 months ago
- Status changed from Résolu (à déployer) to 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.