Je reçois le message d'erreur suivant lors de l'exécution d'une requête sur une base de données PostgreSQL en mode veille. La requête à l'origine de l'erreur fonctionne correctement pendant un mois, mais une erreur est générée lorsque vous effectuez une requête pendant plus d'un mois.
ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
Des suggestions sur la façon de résoudre? Merci
Exécuter des requêtes sur un serveur de secours est un peu délicat - il peut échouer car lors de la requête, certaines lignes nécessaires peuvent être mises à jour ou supprimées sur le serveur principal. Comme le principal ne sait pas qu'une requête est lancée sur le secondaire, il pense pouvoir nettoyer (vider) les anciennes versions de ses lignes. Ensuite, secondaire doit rejouer ce nettoyage et annuler de force toutes les requêtes pouvant utiliser ces lignes.
Les requêtes plus longues seront annulées plus souvent.
Vous pouvez contourner ce problème en démarrant une transaction de lecture répétable sur le principal qui effectue une requête fictive, puis reste inactive pendant qu'une vraie requête est exécutée sur le secondaire. Sa présence empêchera l’aspiration des anciennes versions de la rangée sur le primaire.
Pour plus d'informations sur ce sujet et sur d'autres solutions, reportez-vous à la section Hot Standby - Traitement des conflits de requêtes de la documentation.
Il n'est pas nécessaire de démarrer des transactions inactives sur le maître. Dans postgresql-9.1, le moyen le plus direct de résoudre ce problème consiste à définir
hot_standby_feedback = on
Cela mettra le maître au courant des requêtes de longue durée. De la docs :
La première option consiste à définir le paramètre hot_standby_feedback, ce qui empêche VACUUM de supprimer les lignes récemment inactives, ce qui évite les conflits de nettoyage.
Pourquoi n'est-ce pas le cas par défaut? Ce paramètre a été ajouté après la mise en œuvre initiale et constitue l'unique moyen par lequel une veille peut affecter un maître.
Pas besoin de toucher hot_standby_feedback
. Comme d'autres l'ont mentionné, le paramétrage sur on
peut faire grimper le maître. Imaginez ouvrir une transaction sur un esclave et non le fermer.
Au lieu de cela, définissez max_standby_archive_delay
et max_standby_streaming_delay
à une valeur raisonnable:
# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s
De cette façon, les requêtes sur les esclaves d'une durée inférieure à 900 secondes ne seront pas annulées. Si votre charge de travail nécessite des requêtes plus longues, définissez simplement ces options sur une valeur plus élevée.
Comme indiqué ici à propos de hot_standby_feedback = on
:
Eh bien, l’inconvénient, c’est que la mise en veille peut fatiguer le maître, ce qui peut surprendre aussi certaines personnes.
Et ici :
Avec quel réglage de max_standby_streaming_delay? Je préférerais que -1 soit la valeur par défaut plutôt que hot_standby_feedback par défaut. De cette façon, ce que vous faites en veille n’affecte que la veille
Alors j'ai ajouté
max_standby_streaming_delay = -1
Et pas plus pg_dump
erreur pour nous, ni maître gonfler :)
Pour l'instance AWS RDS, vérifiez http://docs.aws.Amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html
Les données de la table sur le serveur esclave de secours automatique sont modifiées lors de l'exécution d'une requête longue. Une solution (PostgreSQL 9.1+) pour vous assurer que les données de la table ne sont pas modifiées consiste à suspendre la réplication et à la reprendre après la requête:
select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume