Documentation PostgreSQL 14.22 » Administration du serveur » Haute disponibilité, répartition de charge et réplication » Hot Standby

Précédent | Niveau supérieur | Suivant
27.3. Bascule (Failover) | Sommaire | Chapitre 28. Superviser l'activité de la base de données

## 27.4. Hot Standby

Hot Standby est le terme utilisé pour décrire la possibilité de se connecter et d'exécuter des requêtes en lecture seule alors que le serveur est en récupération d'archive ou mode standby. C'est utile à la fois pour la réplication et pour restaurer une sauvegarde à un état désiré avec une grande précision. Le terme Hot Standby fait aussi référence à la capacité du serveur à passer de la récupération au fonctionnement normal tandis-que les utilisateurs continuent à exécuter des requêtes et/ou gardent leurs connexions ouvertes.

Exécuter des requêtes en mode hot standby est similaire au fonctionnement normal des requêtes, bien qu'il y ait quelques différences d'utilisation et d'administration notées ci-dessous.

### 27.4.1. Aperçu pour l'utilisateur

Quand le paramètre hot_standby est configuré à true sur un serveur en attente, le serveur commencera à accepter les connexions une fois que la restauration est parvenue à un état cohérent. Toutes les connexions qui suivront seront des connexions en lecture seule ; même les tables temporaires ne pourront pas être utilisées.

Les données sur le secondaire mettent un certain temps pour arriver du serveur primaire, il y aura donc un délai mesurable entre primaire et secondaire. La même requête exécutée presque simultanément sur le primaire et le secondaire pourrait par conséquent retourner des résultats différents. On dit que la donnée est cohérente à terme avec le primaire. Une fois que l'enregistrement de validation (COMMIT) d'une transaction est rejoué sur le serveur en attente, les modifications réalisées par cette transaction seront visibles par toutes les images de bases obtenues par les transactions en cours sur le serveur en attente. Ces images peuvent être prises au début de chaque requête ou de chaque transaction, suivant le niveau d'isolation des transactions utilisé à ce moment. Pour plus de détails, voir Section 13.2.

Les transactions exécutées pendant la période de restauration sur un serveur en mode hot standby peuvent inclure les commandes suivantes :

- Accès par requête : `SELECT`, `COPY TO`

- Commandes de curseur : `DECLARE`, `FETCH`, `CLOSE`

- Paramètres : `SHOW`, `SET`, `RESET`

- Commandes de gestion de transaction :

  - `BEGIN`, `END`, `ABORT`, `START TRANSACTION`

  - `SAVEPOINT`, `RELEASE`, `ROLLBACK TO SAVEPOINT`

  - Blocs d'`EXCEPTION` et autres sous-transactions internes

- `LOCK TABLE`, mais seulement quand explicitement dans un de ces modes: `ACCESS SHARE`, `ROW SHARE` ou `ROW EXCLUSIVE`.

- Plans et ressources : `PREPARE`, `EXECUTE`, `DEALLOCATE`, `DISCARD`

- Plugins et extensions : `LOAD`

- `UNLISTEN`

Les transactions lancées pendant la restauration d'un serveur en hot standby ne se verront jamais affectées un identifiant de transactions et ne peuvent pas être écrites dans les journaux de transactions. Du coup, les actions suivantes produiront des messages d'erreur :

- Langage de Manipulation de Données (LMD ou DML) : `INSERT`, `UPDATE`, `DELETE`, `COPY FROM`, `TRUNCATE`. Notez qu'il n'y a pas d'action autorisée qui entraînerait l'exécution d'un trigger pendant la récupération. Cette restriction s'applique même pour les tables temporaires car les lignes de ces tables ne peuvent être lues et écrites s'il n'est pas possible d'affecter un identifiant de transactions, ce qui n'est actuellement pas possible dans un environnement Hot Standby.

- Langage de Définition de Données (LDD ou DDL) : `CREATE`, `DROP`, `ALTER`, `COMMENT`. Cette restriction s'applique aussi aux tables temporaires car, pour mener à bien ces opérations, cela nécessiterait de mettre à jour les catalogues systèmes.

- `SELECT ... FOR SHARE | UPDATE`, car les verrous de lignes ne peuvent pas être pris sans mettre à jour les fichiers de données.

- Règles sur des ordres `SELECT` qui génèrent des commandes LMD.

- `LOCK` qui demandent explicitement un mode supérieur à `ROW EXCLUSIVE MODE`.

- `LOCK` dans sa forme courte par défaut, puisqu'il demande `ACCESS EXCLUSIVE MODE`.

- Commandes de gestion de transaction qui positionnent explicitement un état n'étant pas en lecture-seule :

  - `BEGIN READ WRITE`, `START TRANSACTION READ WRITE`

  - `SET TRANSACTION READ WRITE`, `SET SESSION CHARACTERISTICS AS TRANSACTION READ WRITE`

  - `SET transaction_read_only = off`

- Commandes de two-phase commit : `PREPARE TRANSACTION`, `COMMIT PREPARED`, `ROLLBACK PREPARED` parce que même les transactions en lecture seule ont besoin d'écrire dans le WAL durant la phase de préparation (la première des deux phases du two-phase commit).

- Mise à jour de séquence : `nextval()`, `setval()`

- `LISTEN`, `NOTIFY`

Dans le cadre normal, les transactions « en lecture seule » permettent l'utilisation des instructions `LISTEN` et `NOTIFY`, donc les sessions Hot Standby ont des restrictions légèrement inférieures à celles de sessions en lecture seule ordinaires. Il est possible que certaines des restrictions soient encore moins importantes dans une prochaine version.

Lors du fonctionnement en serveur hot standby, le paramètre `transaction_read_only` est toujours à true et ne peut pas être modifié. Tant qu'il n'y a pas de tentative de modification sur la base de données, les connexions sur un serveur en hot standby se comportent de façon pratiquement identiques à celles sur un serveur normal. Quand une bascule (failover ou switchover) survient, la base de données bascule dans le mode de traitement normal. Les sessions resteront connectées pendant le changement de mode. Quand le mode hot standby est terminé, il sera possible de lancer des transactions en lecture/écriture, y compris pour les sessions connectées avant la bascule.

Les utilisateurs peuvent déterminer si le Hot Standby est actuellement actif pour leur session en exécutant `SHOW in_hot_standby`. (Le paramètre `in_hot_standby` n'existant pas avant la version 14, `SHOW transaction_read_only` est donc à utiliser sur les serveurs en version plus ancienne.) De plus, un jeu de fonctions (Tableau 9.88) permettent aux utilisateurs d'accéder à des informations à propos du serveur secondaire. Ceci vous permet d'écrire des programmes qui sont conscients de l'état actuel de la base. Vous pouvez vous en servir pour superviser l'avancement de la récupération, ou pour écrire des programmes complexes qui restaurent la base dans des états particuliers.

### 27.4.2. Gestion des conflits avec les requêtes

Les nœuds primaire et secondaire sont faiblement couplés à bien des égards. Des actions sur le primaire auront un effet sur le secondaire. Par conséquent, il y a un risque d'interactions négatives ou de conflits entre eux. Le conflit le plus simple à comprendre est la performance : si un gros chargement de données a lieu sur le primaire, il générera un flux similaire d'enregistrements WAL sur le secondaire, et les requêtes du secondaire pourrait entrer en compétition pour les ressources systèmes, comme les entrées-sorties.

Il y a aussi d'autres types de conflits qui peuvent se produire avec le Hot Standby. Ces conflits sont des conflits durs dans le sens où des requêtes pourraient devoir être annulées et, dans certains cas, des sessions déconnectées, pour les résoudre. L'utilisateur dispose de plusieurs moyens pour gérer ces conflits. Voici les différents cas de conflits possibles :

- Des verrous en accès exclusif pris sur le serveur primaire, incluant à la fois les commandes `LOCK` exclusives et quelques actions de type DDL, entrent en conflit avec les accès de table des requêtes en lecture seule.

- La suppression d'un tablespace sur le serveur primaire entre en conflit avec les requêtes sur le serveur secondaire qui utilisent ce tablespace pour les fichiers temporaires.

- La suppression d'une base de données sur le serveur primaire entre en conflit avec les sessions connectées sur cette base de données sur le serveur en attente.

- La copie d'un enregistrement nettoyé par un VACUUM entre en conflit avec les transactions sur le serveur en attente qui peuvent toujours « voir » au moins une des lignes à supprimer.

- La copie d'un enregistrement nettoyé par un VACUUM entre en conflit avec les requêtes accédant à la page cible sur le serveur en attente, qu'elles voient ou non les données à supprimer.

Sur le serveur primaire, ces cas résultent en une attente supplémentaire ; l'utilisateur peut choisir d'annuler une des actions en conflit. Néanmoins, sur le serveur en attente, il n'y a pas de choix possibles : l'action enregistrée dans les journaux de transactions est déjà survenue sur le serveur primaire et le serveur secondaire doit absolument réussir à l'appliquer. De plus, permettre que l'enregistrement de l'action attende indéfiniment pourrait avoir des effets fortement non désirables car le serveur en attente sera de plus en plus en retard par rapport au primaire. Du coup, un mécanisme est fourni pour forcer l'annulation des requêtes sur le serveur en attente qui entreraient en conflit avec des enregistrements des journaux de transactions en attente.

Voici un exemple de problème type : un administrateur exécute un `DROP TABLE` sur une table du serveur primaire qui est actuellement utilisé dans des requêtes du serveur en attente. Il est clair que la requête ne peut pas continuer à s'exécuter si l'enregistrement dans les journaux de transactions, correspondant au `DROP TABLE` est appliqué sur le serveur en attente. Si cette situation survient sur le serveur primaire, l'instruction `DROP TABLE` attendra jusqu'à ce que l'autre requête se termine. Par contre, quand le `DROP TABLE` est exécuté sur le serveur primaire, ce dernier ne sait pas les requêtes en cours d'exécution sur le serveur en attente, donc il n'attendra pas la fin de l'exécution des requêtes sur le serveur en attente. L'enregistrement de cette modification dans les journaux de transactions arrivera au serveur en attente alors que la requête sur le serveur en attente est toujours en cours d'exécution, causant un conflit. Le serveur en attente doit soit retarder l'application des enregistrements des journaux de transactions (et tous ceux qui sont après aussi) soit annuler la requête en conflit, pour appliquer l'instruction `DROP TABLE`.

Quand une requête en conflit est courte, il est généralement préférable d'attendre un peu pour l'application du journal de transactions. Mais un délai plus long n'est généralement pas souhaitable. Donc, le mécanisme d'annulation dans l'application des enregistrements de journaux de transactions dispose de deux paramètres, max_standby_archive_delay et max_standby_streaming_delay, qui définissent le délai maximum autorisé pour appliquer les enregistrements. Les requêtes en conflit seront annulées si l'application des enregistrements prend plus de temps que celui défini. Il existe deux paramètres pour que des délais différents puissent être observés suivant le cas : lecture des enregistrements à partir d'un journal archivé (par exemple lors de la restauration initiale à partir d'une sauvegarde ou lors d'un « rattrapage » si le serveur en attente accumulait du retard par rapport au primaire) et lecture des enregistrements à partir de la réplication en flux.

Pour un serveur en attente dont le but principal est la haute-disponibilité, il est préférable de configurer des valeurs assez basses pour les paramètres de délai, de façon à ce que le serveur en attente ne soit pas trop en retard par rapport au serveur primaire à cause des délais suivis à cause des requêtes exécutées sur le serveur en attente. Par contre, si le serveur en attente doit exécuter des requêtes longues, alors une valeur haute, voire infinie, du délai pourrait être préférable. Néanmoins, gardez en tête qu'une requête mettant du temps à s'exécuter pourrait empêcher les autres requêtes de voir les modifications récentes sur le serveur primaire si elle retarde l'application des enregistrements de journaux de transactions.

Une fois que le délai spécifié par `max_standby_archive_delay` ou `max_standby_streaming_delay` a été dépassé, toutes les requêtes en conflit seront annulées. Ceci résulte habituellement en une erreur d'annulation, bien que certains cas, comme un `DROP DATABASE`, peuvent occasionner l'arrêt complet de la connexion. De plus, si le conflit intervient sur un verrou détenu par une transaction en attente, la session en conflit sera terminée (ce comportement pourrait changer dans le futur).

Les requêtes annulées peuvent être ré-exécutées immédiatement (après avoir commencé une nouvelle transaction, bien sûr). Comme l'annulation des requêtes dépend de la nature des enregistrements dans le journal de transactions, une requête annulée pourrait très bien réussir si elle est de nouveau exécutée.

Gardez en tête que les paramètres de délai sont comparés au temps passé depuis que la donnée du journal de transactions a été reçue par le serveur en attente. Du coup, la période de grâce accordée aux requêtes n'est jamais supérieure au paramètre de délai, et peut être considérablement inférieure si le serveur en attente est déjà en retard suite à l'attente de la fin de l'exécution de requêtes précédentes ou suite à son impossibilité de conserver le rythme d'une grosse mise à jour.

La raison la plus fréquente des conflits entre les requêtes en lecture seule et le rejeu des journaux de transactions est le « nettoyage avancé ». Habituellement, PostgreSQL permet le nettoyage des anciennes versions de lignes quand aucune transaction ne peut les voir pour s'assurer du respect des règles de MVCC. Néanmoins, cette règle peut seulement s'appliquer sur les transactions exécutées sur le serveur primaire. Donc il est possible que le nettoyage effectué sur le primaire supprime des versions de lignes toujours visibles sur une transaction exécutée sur le serveur en attente.

Les utilisateurs expérimentés peuvent noter que le nettoyage des versions de ligne ainsi que le gel des versions de ligne peuvent potentiellement avoir un conflit avec les requêtes exécutées sur le serveur en attente. L'exécution d'un `VACUUM FREEZE` manuel a de grandes chances de causer des conflits, y compris sur les tables sans lignes mises à jour ou supprimées.

Les utilisateurs doivent s'attendre à ce que les tables fréquemment mises à jour sur le serveur primaire seront aussi fréquemment la cause de requêtes annulées sur le serveur en attente. Dans un tel cas, le paramétrage d'une valeur finie pour `max_standby_archive_delay` ou `max_standby_streaming_delay` peut être considéré comme similaire à la configuration de `statement_timeout`.

Si le nombre d'annulations de requêtes sur le serveur en attente est jugé inadmissible, quelques solutions existent. La première option est de définir la variable `hot_standby_feedback` qui permet d'empêcher les conflits liés au nettoyage opéré par la commande `VACUUM` en lui interdisant de nettoyer les lignes récemment supprimées. Si vous le faites, vous devez noter que cela retardera le nettoyage des versions de lignes mortes sur le serveur primaire, ce qui pourrait résulter en une fragmentation non désirée de la table. Néanmoins, cette situation ne sera pas meilleure si les requêtes du serveur en attente s'exécutaient directement sur le serveur primaire. Vous avez toujours le bénéfice de l'exécution sur un serveur distant. Si des serveurs secondaires se connectent et se déconnectent fréquemment, vous pourriez vouloir faire des ajustements pour gérer la période durant laquelle `hot_standby_feedback` n'est pas renvoyé. Par exemple, vous pouvez considérer l'augmentation de `max_standby_archive_delay` pour que les requêtes ne soient pas annulées rapidement par des conflits avec le journal de transactions d'archive durant les périodes de déconnexion. Vous pouvez également considérer l'augmentation de `max_standby_streaming_delay` pour éviter des annulations rapides par les nouvelles données de flux de transaction après la reconnexion.

Une autre option revient à augmenter vacuum_defer_cleanup_age sur le serveur primaire, pour que les lignes mortes ne soient pas nettoyées aussi rapidement que d'habitude. Cela donnera plus de temps aux requêtes pour s'exécuter avant d'être annulées sur le serveur en attente, sans voir à configurer une valeur importante de `max_standby_streaming_delay`. Néanmoins, il est difficile de garantir une fenêtre spécifique de temps d'exécution avec cette approche car `vacuum_defer_cleanup_age` est mesuré en nombre de transactions sur le serveur primaire.

Le nombre de requêtes annulées et le motif de cette annulation peut être visualisé avec la vue système `pg_stat_database_conflicts` sur le serveur secondaire. La vue système `pg_stat_database` contient aussi des informations synthétiques sur ce sujet.

Les utilisateurs peuvent contrôler si un message doit être écrit dans les traces du serveur lorsque le rejeu des journaux de transactions est en conflit depuis plus longtemps que `deadlock_timeout`. Ce comportement est contrôlé par le paramètre log_recovery_conflict_waits.

### 27.4.3. Aperçu pour l'administrateur

Si `hot_standby` est positionné à `on` dans `postgresql.conf` (valeur par défaut) et qu'un fichier `standby.signal` est présent, le serveur fonctionnera en mode Hot Standby. Toutefois, il pourrait s'écouler du temps avant que les connections en Hot Standby soient autorisées, parce que le serveur n'acceptera pas de connexions tant que la récupération n'aura pas atteint un point garantissant un état cohérent permettant aux requêtes de s'exécuter. Pendant cette période, les clients qui tentent de se connecter seront rejetés avec un message d'erreur. Pour confirmer que le serveur a démarré, vous pouvez soit tenter de vous connecter en boucle, ou rechercher ces messages dans les journaux du serveur:

    LOG:  entering standby mode

    ... puis, plus loin ...

    LOG:  consistent recovery state reached
    LOG:  database system is ready to accept read-only connections

L'information sur la cohérence est enregistrée une fois par checkpoint sur le primaire. Il n'est pas possible d'activer le mode Hot Standby si on lit des WAL générés durant une période pendant laquelle `wal_level` n'était pas positionné à `replica` ou `logical` sur le primaire. L'arrivée à un état cohérent peut aussi être retardée si ces deux conditions se présentent:

- Une transaction en écriture a plus de 64 sous-transactions

- Des transactions en écriture ont une durée très importante

Si vous effectuez du log shipping par fichier (warm standby), vous pourriez devoir attendre jusqu'à l'arrivée du prochain fichier de WAL, ce qui pourrait être aussi long que le paramètre `archive_timeout` du primaire.

Certains paramètres déterminent la taille de la mémoire partagée pour le suivi des identifiants de transaction, des verrous, et des transactions préparées. Ces structures mémoires partagées ne peuvent pas être plus petites sur le secondaire que sur le primaire pour s'assurer que le secondaire ne tombera pas à court de mémoire partagée pendant la récupération. Par exemple, si le primaire avait utilisé des transactions préparées mais que le secondaire n'avait pas alloué de mémoire partagée pour suivre ces transactions préparées, alors la récupération ne pourrait reprendre avant que la configuration du secondaire ne soit adaptée. Les paramètres concernés sont:

- `max_connections`

- `max_prepared_transactions`

- `max_locks_per_transaction`

- `max_wal_senders`

- `max_worker_processes`

La façon la plus simple pour éviter que cela ne devienne un problème est d'avoir tous ces paramètres définis sur les serveurs secondaires à des valeurs égales ou supérieures que celles du primaire. C'est pourquoi, si vous voulez augmenter ces valeurs, vous devez le faire d'abord sur tous les serveurs secondaires avant de le faire sur le serveur primaire. De la même façon, si vous voulez diminuer ces valeurs, vous devez d'abord le faire sur le serveur primaire, puis sur tous les serveurs secondaires. Gardez également à l'esprit que lorsqu'un secondaire est promu, il devient alors la nouvelle référence des valeurs de ces paramètres pour les secondaires qui s'y raccrochent. De ce fait, pour éviter que cela ne devienne un problème lors d'une bascule (switchover ou failover), il est recommandé de conserver ces paramètres identiques sur tous les serveurs secondaires.

Les journaux de transactions tracent le changement de ces paramètres sur le serveur primaire. Si un serveur hot standby rejoue un journal de transactions qui indique que la valeur actuelle sur le primaire est plus élevée que la sienne, un message d'avertissement sera écrit dans les traces du serveur et le rejeu mis en pause. Par exemple :

    WARNING:  hot standby is not possible because of insufficient parameter settings
    DETAIL:  max_connections = 80 is a lower setting than on the primary server, where its value was 100.
    LOG:  recovery has paused
    DETAIL:  If recovery is unpaused, the server will shut down.
    HINT:  You can then restart the server after making the necessary configuration changes.

A ce stade, les paramètres du secondaire doivent être ajustés et l'instance redémarrée avant que le rejeu ne puisse reprendre. Si le secondaire n'est pas en mode hot standby alors, lorsqu'il rencontrera un changement de paramètre incompatible, il s'éteindra immédiatement sans pause, puisqu'il serait inutile de rester actif.

Il est important que l'administrateur sélectionne le paramétrage approprié pour max_standby_archive_delay et max_standby_streaming_delay. Le meilleur choix varie les priorités. Par exemple, si le serveur a comme tâche principale d'être un serveur de haute-disponibilité, alors il est préférable d'avoir une configuration assez basse, voire à zéro, de ces paramètres. Si le serveur en attente est utilisé comme serveur supplémentaire pour des requêtes du type décisionnel, il sera acceptable de mettre les paramètres de délai à des valeurs allant jusqu'à plusieurs heures, voire même -1 (cette valeur signifiant qu'il est possible d'attendre que les requêtes se terminent d'elles-même).

Les "hint bits" (bits d'indices) écrits sur le primaire ne sont pas journalisés en WAL, il est donc probable que les hint bits soient réécrits sur le secondaire. Ainsi, le serveur secondaire fera toujours des écritures disques même si tous les utilisateurs sont en lecture seule ; aucun changement ne se produira sur les données elles mêmes. Les utilisateurs écriront toujours les fichiers temporaires pour les gros tris et re-génèreront les fichiers d'information relcache, il n'y a donc pas de morceau de la base qui soit réellement en lecture seule en mode hot standby. Notez aussi que les écritures dans des bases distantes en utilisant le module dblink, et d'autres opérations en dehors de la base s'appuyant sur des fonctions PL seront toujours possibles, même si la transaction est en lecture seule localement.

Les types suivants de commandes administratives ne sont pas acceptées durant le mode de récupération:

- Langage de Définition de Données (LDD ou DDL) : comme `CREATE INDEX`

- Droits et propriété : `GRANT`, `REVOKE`, `REASSIGN`

- Commandes de maintenance : `ANALYZE`, `VACUUM`, `CLUSTER`, `REINDEX`

Notez encore une fois que certaines de ces commandes sont en fait autorisées durant les transactions en "lecture seule" sur le primaire.

Par conséquent, vous ne pouvez pas créer d'index supplémentaires qui existeraient uniquement sur le secondaire, ni des statistiques qui n'existeraient que sur le secondaire. Si ces commandes administratives sont nécessaires, elles doivent être exécutées sur le primaire, et ces modifications se propageront à terme au secondaire.

`pg_cancel_backend()` et `pg_terminate_backend()` fonctionneront sur les processus utilisateurs, mais pas sur les processus de démarrage, qui effectuent la récupération. `pg_stat_activity` ne montre pas les transactions de récupération comme actives. Ainsi, `pg_prepared_xacts` est toujours vide durant la récupération. Si vous voulez traiter des transactions préparées douteuses, interrogez `pg_prepared_xacts` sur le primaire, et exécutez les commandes pour résoudre le problème à cet endroit ou résolvez-les après la fin de la restauration.

`pg_locks` affichera les verrous posés par les processus, comme en temps normal. `pg_locks` affiche aussi une transaction virtuelle gérée par le processus de démarrage qui possède tous les `AccessExclusiveLocks` posés par les transactions rejouées par la récupération. Notez que le processus de démarrage n'acquiert pas de verrou pour effectuer les modifications à la base, et que par conséquent les verrous autre que `AccessExclusiveLocks` ne sont pas visibles dans `pg_locks` pour le processus de démarrage; ils sont simplement censés exister.

Le plugin Nagios check_pgsql fonctionnera, parce que les informations simples qu'il vérifie existent. Le script de supervision check_postgres fonctionnera aussi, même si certaines valeurs retournées pourraient être différentes ou sujettes à confusion. Par exemple, la date de dernier vacuum ne sera pas mise à jour, puisqu’aucun vacuum ne se déclenche sur le secondaire. Les vacuums s'exécutant sur le primaire envoient toujours leurs modifications au secondaire.

Les options de contrôle des fichiers de WAL ne fonctionneront pas durant la récupération, comme `pg_start_backup`, `pg_switch_wal`, etc...

Les modules à chargement dynamique fonctionnent, comme `pg_stat_statements`.

Les verrous consultatifs fonctionnent normalement durant la récupération, y compris en ce qui concerne la détection des verrous mortels (deadlocks). Notez que les verrous consultatifs ne sont jamais tracés dans les WAL, il est donc impossible pour un verrou consultatif sur le primaire ou le secondaire d'être en conflit avec la ré-application des WAL. Pas plus qu'il n'est possible d'acquérir un verrou consultatif sur le primaire et que celui-ci initie un verrou consultatif similaire sur le secondaire. Les verrous consultatifs n'ont de sens que sur le serveur sur lequel ils sont acquis.

Les systèmes de réplications à base de triggers tels que Slony, Londiste et Bucardo ne fonctionneront pas sur le secondaire du tout, même s'ils fonctionneront sans problème sur le serveur primaire tant que les modifications ne sont pas envoyées sur le serveur secondaire pour y être appliquées. Le rejeu de WAL n'est pas à base de triggers, vous ne pouvez donc pas utiliser le secondaire comme relais vers un système qui aurait besoin d'écritures supplémentaires ou utilise des triggers.

Il n'est pas possible d'assigner de nouveaux OID, bien que des générateurs d'UUID puissent tout de même fonctionner, tant qu'ils n'ont pas besoin d'écrire un nouveau statut dans la base.

À l'heure actuelle, la création de table temporaire n'est pas autorisée durant les transactions en lecture seule, certains scripts existants pourraient donc ne pas fonctionner correctement. Cette restriction pourrait être levée dans une version ultérieure. Il s'agit à la fois d'un problème de respect des standards et d'un problème technique.

`DROP TABLESPACE` ne peut réussir que si le tablespace est vide. Certains utilisateurs pourraient utiliser de façon active le tablespace via leur paramètre `temp_tablespaces`. S'il y a des fichiers temporaires dans le tablespace, toutes les requêtes actives sont annulées pour s'assurer que les fichiers temporaires sont supprimés, afin de supprimer le tablespace et de continuer l'application des WAL.

Exécuter `DROP DATABASE` ou `ALTER DATABASE ... SET TABLESPACE` sur le serveur primaire générera un enregistrement dans les journaux de transactions qui causera la déconnexion de tous les utilisateurs actuellement connectés à cette base de données. Cette action survient immédiatement, quelque soit la valeur du paramètre `max_standby_streaming_delay`. Notez que `ALTER DATABASE ... RENAME` ne déconnecte pas les utilisateurs qui, dans la plupart des cas, ne s'en apercevront pas. Cela peut néanmoins semer de la confusion pour un programme qui dépendrait du nom de la base.

En fonctionnement normal (pas en restauration), si vous exécutez `DROP USER` ou `DROP ROLE` pour un rôle ayant l'attribut LOGIN alors que cet utilisateur est toujours connecté alors rien ne se produit pour cet utilisateur connecté -- il reste connecté. L'utilisateur ne peut toutefois pas se reconnecter. Ce comportement est le même en récupération, un `DROP USER` sur le primaire ne déconnecte donc pas cet utilisateur sur le secondaire.

Le collecteur de statistiques est actif durant la récupération. Tous les parcours, lectures, utilisations de blocs et d'index, etc... seront enregistrés normalement sur le secondaire. Les actions rejouées ne dupliqueront pas leur effets sur le primaire, l'application d'insertions n'incrémentera pas la colonne Inserts de pg_stat_user_tables. Le fichier de statistiques est effacé au démarrage de la récupération, les statistiques du primaire et du secondaire différeront donc; c'est vu comme une fonctionnalité, pas un bug.

Autovacuum n'est pas actif durant la récupération, il démarrera normalement à la fin de la récupération.

Les processus d'écriture en arrière plan (checkpointer et background writer) sont actifs durant la restauration. Le processus checkpointer process effectuera les restartpoints (similaires aux checkpoints sur le primaire) et le processus background writer réalisera les activités normales de nettoyage de blocs. Ceci peut inclure la mise à jour des information de hint bit des données du serveur secondaire. La commande `CHECKPOINT` est acceptée pendant la récupération, bien qu'elle déclenche un restartpoint et non un checkpoint.

### 27.4.4. Référence des paramètres de Hot Standby

De nombreux paramètres ont été mentionnés ci-dessus dans Section 27.4.2 et Section 27.4.3.

Sur le primaire, les paramètres wal_level et vacuum_defer_cleanup_age peuvent être utilisés. max_standby_archive_delay et max_standby_streaming_delay n'ont aucun effet sur le primaire.

Sur le serveur en attente, les paramètres hot_standby, max_standby_archive_delay et max_standby_streaming_delay peuvent être utilisés. vacuum_defer_cleanup_age n'a pas d'effet tant que le serveur reste dans le mode standby, mais deviendra important quand le serveur en attente deviendra un serveur primaire.

### 27.4.5. Avertissements

Il y a plusieurs limitations au Hot Standby. Elles peuvent et seront probablement résolues dans des versions ultérieures:

- Une connaissance complète des transactions en cours d'exécution est nécessaire avant de pouvoir déclencher des instantanés. Des transactions utilisant un grand nombre de sous-transactions (à l'heure actuelle plus de 64) retarderont le démarrage des connexions en lecture seule jusqu'à complétion de la plus longue transaction en écriture. Si cette situation se produit, des messages explicatifs seront envoyés dans la trace du serveur.

- Des points de démarrage valides pour les requêtes du secondaire sont générés à chaque checkpoint sur le primaire. Si le secondaire est éteint alors que le primaire est déjà éteint, il est tout à fait possible ne pas pouvoir repasser en Hot Standby tant que le primaire n'aura pas été redémarré, afin qu'il génère de nouveaux points de démarrage dans les journaux WAL. Cette situation n'est pas un problème dans la plupart des situations où cela pourrait se produire. Généralement, si le primaire est éteint et plus disponible, c'est probablement en raison d'un problème sérieux qui va de toutes façons forcer la conversion du secondaire en primaire. Et dans des situations où le primaire est éteint intentionnellement, la procédure standard est également de promouvoir le secondaire.

- À la fin de la récupération, les `AccessExclusiveLocks` possédés par des transactions préparées nécessiteront deux fois le nombre d'entrées normal dans la table de verrous. Si vous pensez soit exécuter un grand nombre de transactions préparées prenant des `AccessExclusiveLocks`, ou une grosse transaction prenant beaucoup de `AccessExclusiveLocks`, il est conseillé d'augmenter la valeur de `max_locks_per_transaction`, peut-être jusqu'à une valeur double de celle du serveur primaire. Vous n'avez pas besoin de prendre ceci en compte si votre paramètre `max_prepared_transactions` est 0.

- Il n'est pas encore possible de passer une transaction en mode d'isolation sérialisable tout en supportant le hot standby (voir Section 13.2.3 et Section 13.4.1 pour plus de détails). Une tentative de modification du niveau d'isolation d'une transaction à sérialisable en hot standby générera une erreur.