L'archivage en continu peut être utilisé pour créer une configuration de cluster en haute disponibilité (HA) avec un ou plusieurs serveurs de standby prêts à prendre la main sur les opérations si le serveur primaire fait défaut. Cette fonctionnalité est généralement appelée warm standby ou log shipping.
Les serveurs primaire et de standby travaillent de concert pour fournir cette fonctionnalité, bien que les serveurs ne soient que faiblement couplés. Le serveur primaire opère en mode d'archivage en continu, tandis que le serveur de standby opère en mode de récupération en continu, en lisant les fichiers WAL provenant du primaire. Aucune modification des tables de la base ne sont requises pour activer cette fonctionnalité, elle entraîne donc moins de travail d'administration par rapport à d'autres solutions de réplication. Cette configuration a aussi un impact relativement faible sur les performances du serveur primaire.
Déplacer directement des enregistrements de WAL d'un serveur de bases de données à un autre est habituellement appelé log shipping. PostgreSQL implémente le log shipping par fichier, ce qui signifie que les enregistrements de WAL sont transférés un fichier (segment de WAL) à la fois. Les fichiers de WAL (16Mo) peuvent être transférés facilement et de façon peu coûteuse sur n'importe quelle distance, que ce soit sur un système adjacent, un autre système sur le même site, ou un autre système à l'autre bout du globe. La bande passante requise pour cette technique varie en fonction du débit de transactions du serveur primaire. La technique de streaming replication permet d'optimiser cette bande passante en utilisant une granularité plus fine que le log shipping par fichier. Pour cela, les modifications apportées au journal de transactions sont traitées sous forme de flux au travers d'une connexion réseau (voir Section 26.2.5).
Il convient de noter que le log shipping est asynchrone, c'est à dire que les
enregistrements de WAL sont transférés après que la transaction ait été validée. Par conséquent, il y a
un laps de temps pendant lequel une perte de données pourrait se produire si le serveur primaire
subissait un incident majeur; les transactions pas encore transférées seront perdues. La taille de la fenêtre
de temps de perte de données peut être réduite par l'utilisation du paramètre
archive_timeout
, qui peut être abaissé à des valeurs
de quelques secondes. Toutefois, un paramètre si bas augmentera de façon
considérable la bande passante nécessaire pour le transfert de fichiers.
L'utilisation de la technique de streaming replication (voir Section 26.2.5)
permet de diminuer la taille de la fenêtre de temps de perte de données.
La performance de la récupération est suffisamment bonne pour que le standby ne soit en général qu'à quelques instants de la pleine disponibilité à partir du moment où il aura été activé. C'est pour cette raison que cette configuration de haute disponibilité est appelée warm standby. Restaurer un serveur d'une base de sauvegarde archivée, puis appliquer tous les journaux prendra largement plus de temps, ce qui fait que cette technique est une solution de 'disaster recovery' (reprise après sinistre), pas de haute disponibilité. Un serveur de standby peut aussi être utilisé pour des requêtes en lecture seule, dans quel cas il est appelé un serveur de Hot Standby. Voir Section 26.5 pour plus d'information.
Il est habituellement préférable de créer les serveurs primaire et de standby de façon à ce qu'ils soient aussi similaires que possible, au moins du point de vue du serveur de bases de données. En particulier, les chemins associés avec les tablespaces seront passés d'un noeud à l'autre sans conversion, ce qui implique que les serveurs primaire et de standby doivent avoir les mêmes chemins de montage pour les tablespaces si cette fonctionnalité est utilisée. Gardez en tête que si CREATE TABLESPACE est exécuté sur le primaire, tout nouveau point de montage nécessaire pour cela doit être créé sur le primaire et tous les standby avant que la commande ne soit exécutée. Le matériel n'a pas besoin d'être exactement le même, mais l'expérience monte que maintenir deux systèmes identiques est plus facile que maintenir deux différents sur la durée de l'application et du système. Quoi qu'il en soit, l'architecture hardware doit être la même -- répliquer par exemple d'un serveur 32 bits vers un 64 bits ne fonctionnera pas.
De manière générale, le log shipping entre serveurs exécutant des versions majeures différentes de PostgreSQL est impossible. La politique du PostgreSQL Global Development Group est de ne pas réaliser de changement sur les formats disques lors des mises à jour mineures, il est par conséquent probable que l'exécution de versions mineures différentes sur le primaire et le standby fonctionne correctement. Toutefois, il n'y a aucune garantie formelle de cela et il est fortement conseillé de garder le serveur primaire et celui de standby au même niveau de version autant que faire se peut. Lors d'une mise à jour vers une nouvelle version mineure, la politique la plus sûre est de mettre à jour les serveurs de standby d'abord -- une nouvelle version mineure est davantage susceptible de lire les enregistrements WAL d'une ancienne version mineure que l'inverse.
En mode de standby, le serveur applique continuellement les WAL reçus du
serveur primaire. Le serveur de standby peut lire les WAL d'une archive WAL
(voir restore_command) ou directement du primaire via une
connexion TCP (streaming replication). Le serveur de standby essaiera aussi de
restaurer tout WAL trouvé dans le répertoire pg_wal
du
cluster de standby. Cela se produit habituellement après un redémarrage de
serveur, quand le standby rejoue à nouveau les WAL qui ont été reçu du primaire
avant le redémarrage, mais vous pouvez aussi copier manuellement des fichiers dans
pg_wal
à tout moment pour qu'ils soient rejoués.
Au démarrage, le serveur de standby commence par restaurer tous les WAL
disponibles à l'endroit où se trouvent les archives, en appelant la
restore_command
. Une fois qu'il a épuisé tous les WAL
disponibles à cet endroit et que restore_command
échoue, il essaie de restaurer tous les WAL disponibles dans le répertoire
pg_wal
. Si cela échoue, et que la réplication en flux
a été activée, le standby essaie
de se connecter au serveur primaire et de démarrer la réception des WAL depuis
le dernier enregistrement valide trouvé dans les archives ou
pg_wal
. Si cela
échoue ou que la streaming replication n'est pas configurée, ou que la connexion
est plus tard déconnectée, le standby retourne à l'étape 1 et essaie de
restaurer le fichier à partir de l'archive à nouveau. Cette boucle de
retentatives de l'archive, pg_wal
et par la
streaming replication continue
jusqu'à ce que le serveur soit stoppé ou que le failover (bascule) soit
déclenché par un fichier trigger (déclencheur).
Le mode de standby est quitté et le serveur bascule en mode de fonctionnement normal
quand pg_ctl promote
est exécuté ou qu'un fichier de trigger est trouvé (trigger_file
).
Avant de basculer, tout WAL immédiatement disponible dans l'archive ou le
pg_wal
sera
restauré, mais aucune tentative ne sera faite pour se connecter au primaire.
Mettez en place un archivage en continu sur le primaire vers un répertoire d'archivage accessible depuis le standby, comme décrit dans Section 25.3. La destination d'archivage devrait être accessible du standby même quand le primaire est inaccessible, c'est à dire qu'il devrait se trouver sur le serveur de standby lui-même ou un autre serveur de confiance, pas sur le serveur primaire.
Si vous voulez utiliser la streaming replication, mettez en place l'authentification sur le
serveur primaire pour autoriser les connexions de réplication à partir du (des) serveur de
standby ; c'est-à-dire, créez un rôle et mettez en place une ou des entrées appropriées dans
pg_hba.conf
avec le champ database positionné à
replication
. Vérifiez aussi que max_wal_senders
est positionné
à une valeur suffisamment grande dans le fichier de configuration du serveur primaire.
Si des slots de réplication seront utilisés, il faut s'assurer que
max_replication_slots
est également positionné à une
valeur suffisamment grande.
Effectuez une sauvegarde de base comme décrit dans Section 25.3.2 pour initialiser le serveur de standby.
Pour paramétrer le serveur de standby, restaurez la sauvegarde de base effectué sur
le serveur primaire (voir (see Section 25.3.4). Créez un
fichier de commande de récupération recovery.conf
dans
le répertoire de données du cluster de standby, et positionnez standby_mode
à on. Positionnez restore_command
à une simple commande qui recopie
les fichiers de l'archive de WAL. Si vous comptez disposer de plusieurs serveurs de stanby pour
mettre en œuvre de la haute disponibilité, définissez recovery_target_timeline
à
latest
, pour indiquer que le serveur de standby devra prendre en compte
la ligne temporelle définie lors de la bascule à un autre serveur de standby.
N'utilisez pas pg_standby ou des outils similaires avec le mode de standby intégré
décrit ici. restore_command
devrait retourner immédiatement
si le fichier n'existe pas; le serveur essayera la commande à nouveau si nécessaire.
Voir Section 26.4 pour utiliser des outils tels que pg_standby.
Si vous souhaitez utiliser la streaming replication, renseignez
primary_conninfo
avec une chaîne de connexion libpq,
contenant le nom d'hôte (ou l'adresse IP) et tout détail supplémentaire
nécessaire pour se connecter au serveur primaire. Si le primaire a besoin d'un
mot de passe pour l'authentification, le mot de passe doit aussi être spécifié dans
primary_conninfo
.
Si vous mettez en place le serveur de standby pour des besoins de haute disponibilité, mettez en place l'archivage de WAL, les connexions et l'authentification à l'identique du serveur primaire, parce que le serveur de standby fonctionnera comme un serveur primaire après la bascule.
Si vous utilisez une archive WAL, sa taille peut être réduite en utilisant
l'option archive_cleanup_command pour supprimer les
fichiers qui ne sont plus nécessaires au serveur de standby. L'outil
pg_archivecleanup est conçu spécifiquement pour
être utilisé avec archive_cleanup_command
dans des
configurations typiques de standby, voir pg_archivecleanup.
Notez toutefois que si vous utilisez l'archive à des fins de sauvegarde,
vous avez besoin de garder les fichiers nécessaires pour restaurer à partir
de votre dernière sauvegarde de base, même si ces fichiers ne sont plus
nécessaires pour le standby.
Si vous utilisez l'archivage des journaux de transactions, la taille des archives peut être minimisée en utilisant le paramètre des suppressions de fichiers qui ne sont plus nécessaires au serveur standby. Néanmoins, notez que si vous utilisez l'archive pour la sauvegarde, vous devez conserver les fichiers nécessaires pour la restauration, au moins pour la dernière sauvegarde de base, même s'ils ne sont plus nécessaire au standby.
Un simple exemple de recovery.conf
est:
standby_mode = 'on' primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' restore_command = 'cp /path/to/archive/%f %p' archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
Vous pouvez avoir n'importe quel nombre de serveurs de standby, mais si vous
utilisez la streaming replication, assurez vous d'avoir positionné
max_wal_senders
suffisamment haut sur le primaire pour leur permettre
de se connecter simultanément.
La streaming replication permet à un serveur de standby de rester plus à jour qu'il n'est possible avec l'envoi de journaux par fichiers. Le standby se connecte au primaire, qui envoie au standby les enregistrements de WAL dès qu'ils sont générés, sans attendre qu'un fichier de WAL soit rempli.
La streaming replication est asynchrone par défaut (voir Section 26.2.8), auquel cas il y a un petit délai
entre la validation d'une transaction sur le primaire et le moment où les
changements sont visibles sur le standby. Le délai est toutefois beaucoup plus petit
qu'avec l'envoi de fichiers, habituellement en dessous d'une seconde en partant
de l'hypothèse que le standby est suffisamment puissant pour supporter la charge. Avec
la streaming replication, archive_timeout
n'est pas nécessaire
pour réduire la fenêtre de perte de données.
Si vous utilisez la streaming replication sans archivage en continu des fichiers,
le serveur pourrait recycler de vieux journaux de transactions avant que le
serveur ne les ait reçus. Si cela arrive, le serveur en standby devra être
recréé d'une nouvelle sauvegarde de l'instance. Vous pouvez éviter cela en
positionnant wal_keep_segments
à une valeur suffisamment
grande pour s'assurer que les journaux de transactions ne sont pas recyclés
trop tôt, ou en configurant un slot de réplication pour le serveur en
standby. Si un archivage des journaux de transactions est en place, et que
les fichiers archivés sont disponibles depuis le serveur en standby, cette
solution n'est pas nécessaire, puisque le serveur en standby peut toujours
utiliser les fichiers archivés pour rattraper son retard, sous réserve que
suffisamment de fichiers soient conservés.
Pour utiliser la streaming replication, mettez en place un serveur de standby
en mode fichier comme décrit dans Section 26.2. L'étape qui
transforme un standby en mode fichier en standby en streaming replication est de
faire pointer primary_conninfo
dans le fichier
recovery.conf
vers le serveur primaire. Positionnez
listen_addresses et les options d'authentification
(voir pg_hba.conf
) sur le primaire pour que le serveur
de standby puisse se connecter à la pseudo-base replication
sur le serveur primaire (voir Section 26.2.5.1).
Sur les systèmes qui supportent l'option de keepalive sur les sockets, positionner tcp_keepalives_idle, tcp_keepalives_interval et tcp_keepalives_count aide le primaire à reconnaître rapidement une connexion interrompue.
Positionnez le nombre maximum de connexions concurrentes à partir des serveurs de standby (voir max_wal_senders pour les détails).
Quand le standby est démarré et que primary_conninfo
est
positionné correctement, le standby se connectera au primaire après avoir
rejoué tous les fichiers WAL disponibles dans l'archive. Si la connexion
est établie avec succès, vous verrez un processus walreceiver dans le standby, et
un processus walsender correspondant sur le primaire.
Il est très important que les privilèges d'accès pour la réplications soient
paramétrés pour que seuls les utilisateurs de confiance puissent lire le
flux WAL, parce qu'il est facile d'en extraire des informations
privilégiées. Les serveurs de standby doivent s'authentifier au serveur
primaire en tant que superutilisateur ou avec un compte disposant de
l'attribut REPLICATION
. Il est recommandé de créer
un compte utilisateur dédié pour la réplication. Il doit disposer des
attributs REPLICATION
et LOGIN
.
Alors que l'attribut REPLICATION
donne beaucoup de
droits, il ne permet pas à l'utilisateur de modifier de données sur le
serveur primaire, contrairement à l'attribut SUPERUSER
.
L'authentification cliente pour la réplication est contrôlée par un enregistrement de
pg_hba.conf
spécifiant replication
dans le champ
database
. Par exemple, si le standby s'exécute sur un hôte d'IP
192.168.1.100
et que le nom de l'utilisateur pour la réplication est
foo
, l'administrateur peut ajouter la ligne suivante au fichier
pg_hba.conf
sur le primaire:
# Autoriser l'utilisateur "foo" de l'hôte 192.168.1.100 à se connecter au primaire # en tant que standby de replication si le mot de passe de l'utilisateur est correctement fourni # # TYPE DATABASE USER ADDRESS METHOD host replication foo 192.168.1.100/32 md5
Le nom d'hôte et le numéro de port du primaire, le nom d'utilisateur de la connexion,
et le mot de passe sont spécifiés dans le fichier recovery.conf
.
Le mot de passe peut aussi être enregistré dans le fichier
~/.pgpass
sur le serveur en attente (en précisant
replication
dans le champ
database
).
Par exemple, si le primaire s'exécute sur l'hôte d'IP 192.168.1.50
,
port 5432
, que le nom de l'utilisateur pour la réplication est
foo
, et que le mot de passe est foopass
, l'administrateur
peut ajouter la ligne suivante au fichier recovery.conf
sur le standby:
# Le standby se connecte au primaire qui s'exécute sur l'hôte 192.168.1.50 # et port 5432 en tant qu'utilisateur "foo" dont le mot de passe est "foopass" primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
Un important indicateur de santé de la streaming replication est le nombre
d'enregistrements générés sur le primaire, mais pas encore appliqués sur
le standby. Vous pouvez calculer ce retard en comparant le point d'avancement
des écritures du WAL sur le primaire avec le dernier point d'avancement reçu par
le standby. Ils peuvent être récupérés en utilisant
pg_current_wal_lsn
sur le primaire et
pg_last_wal_receive_lsn
sur le standby,
respectivement (voir Tableau 9.79 et
Tableau 9.80 pour plus de détails).
Le point d'avancement de la réception dans le standby est aussi affiché dans
le statut du processus de réception des WAL (wal receiver), affiché par
la commande ps
(voyez Section 28.1 pour plus de détails).
Vous pouvez obtenir la liste des processus émetteurs de WAL au moyen de la vue
pg_stat_replication
D'importantes différences entre les champs pg_current_wal_lsn
et
sent_lsn
peuvent indiquer que le serveur primaire est en surcharge,
tandis que des différences entre sent_lsn
et
pg_last_wal_receive_lsn
sur le standby peuvent soit indiquer une latence
réseau importante, soit que le standby est surchargé.
Les slots de réplication fournissent une manière automatisée de s'assurer que le primaire ne supprime pas les journaux de transactions avant qu'ils n'aient été reçus par tous les serveurs en standby, et que le serveur primaire ne supprime pas des lignes qui pourraient causer un conflit de restauration même si le serveur en standby est déconnecté.
Au lieu d'utiliser des slots de réplication, il est possible d'empêcher la
suppression des anciens journaux de transations en utilisant
wal_keep_segments, ou en les stockant dans un
répertoire d'archive en utilisant archive_command.
Cependant, ces méthodes ont souvent pour résultat le stockage de plus de
journaux de transactions que nécessaire, alors que les slots de réplication
ne conservent que le nombre nécessaire de journaux de transactions. Un
avantage de ces méthodes est qu'elles limitent l'espace requis pour
pg_wal
; il n'y a pour le moment aucun moyen d'en
faire de même en utilisant les slots de réplication.
De la même manière, hot_standby et vacuum_defer_cleanup_age fournissent des protections contre la suppression de lignes utiles par vacuum, mais le premier paramètre n'offre aucune protection durant la période pendant laquelle le serveur de standby n'est pas connecté, et le second nécessite souvent d'être positionné à une grande valeur pour fournir une protection adéquate. Les slots de réplication surmontent ces désavantages.
Chaque slot de réplication à un nom, qui peut contenir des lettres en minuscule, des nombres ou un tiret bas.
Les slots de réplication existants et leur états peuvent être vus dans la vue
pg_replication_slots
.
Les slots de réplication peuvent être créés et supprimés soit via le protocole de réplication en flux (voir Section 52.6) soit via des fonctions SQL (voir Section 9.26.6).
Il est possible de créer un slot de réplication ainsi :
postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot'); slot_name | lsn -------------+----- node_a_slot | postgres=# SELECT * FROM pg_replication_slots; slot_name | slot_type | datoid | database | active | xmin | restart_lsn | confirmed_flush_lsn -------------+-----------+--------+----------+--------+------+-------------+--------------------- node_a_slot | physical | | | f | | |(1 row)
Pour configurer le serveur en standby pour utiliser ce slot,
primary_slot_name
devrait être configuré dans le
recovery.conf
du secondaire.
Voilà un exemple simple :
standby_mode = 'on' primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' primary_slot_name = 'node_a_slot'
La fonctionnalité de la réplication en cascade permet à un serveur standard d'accepter les connexions de réplication et d'envoyer un flux d'enregistrements de journaux de transactions à d'autres secondaires, agissant ainsi comme un relai. C'est généralement utilisé pour réduire le nombre de connexions directes au primaire et minimise ainsi l'utilisation de bande passante entre sites distants.
Un serveur standby agissant à la fois comme un receveur et comme un émetteur est connu sous le nom de standby en cascade (cascading standby). Les standbys qui sont plus proches du serveur primaire sont connus sous le nom de serveurs upstream alors que les serveurs standby en bout de chaîne sont des serveurs downstream. La réplication en cascade ne pose pas de limites sur le nombre ou l'arrangement des serveurs downstream. Chaque standby se connecte à un seul serveur upstream, qui finit par arriver à un seul serveur primaire/primaire.
Un standby en cascade envoie non seulement les enregistrements reçus de journaux de transactions mais aussi ceux restaurés des archives. Donc, même si la connexion de réplication d'une connexion upstream est rompue, la réplication en flux continue vers le serveur downstream tant que de nouveaux enregistrements de journaux de transactions sont disponibles.
La réplication en cascade est actuellement asynchrone. La réplication synchrone (voir Section 26.2.8) n'a aucun effet sur la réplication en cascade.
Les messages en retour des serveurs Hot Standby se propagent vers les serveurs upstream, quelque soit la configuration de la réplication en cascade.
Si un serveur standby upstream est promu pour devenir le nouveau serveur
primaire, les serveurs downstream continueront à recevoir le flux de
réplication du nouveau primaire si le paramètre
recovery_target_timeline
est configuré à
'latest'
.
Pour utiliser la réplication en cascade, configurez le standby en cascade
de façon à ce qu'il accepte les connexions de réplication (configurez
max_wal_senders et hot_standby,
ainsi que l'authentification).
Vous aurez aussi besoin de configurer la variable
primary_conninfo
dans le standby downstream pour qu'elle
pointe vers le standby en cascade.
La streaming réplication mise en œuvre par PostgreSQL est asynchrone par défaut. Si le serveur primaire est hors-service, les transactions produites alors peuvent ne pas avoir été répliquées sur le serveur de standby, impliquant une perte de données. La quantité de données perdues est proportionnelle au délai de réplication au moment de la bascule.
La réplication synchrone permet de confirmer que tous les changements
effectués par une transaction ont bien été transférées à un ou plusieurs
serveurs de standby synchrone. Cette propriété étend le niveau de robustesse
standard offert par un commit. En science informatique, ce niveau de
protection est appelé réplication à deux états (2-safe
replication) et group-1-safe
(group-safe et
1-safe) quand
synchronous_commit
est configuré à la valeur
remote_write
.
Lorsque la réplication synchrone est utilisée, chaque validation portant sur une écriture va nécessiter d'attendre la confirmation de l'écriture de cette validation sur les journaux de transaction des disques du serveur primaire et des serveurs en standby. Le seul moyen possible pour que des données soient perdues est que les serveur primaire et de standby soient hors service au même moment. Ce mécanisme permet d'assurer un niveau plus élevé de robustesse, en admettant que l'administrateur système ait pris garde à l'emplacement et à la gestion de ces deux serveurs. Attendre après la confirmation de l'écriture augmente la confiance que l'utilisateur pourra avoir sur la conservation des modifications dans le cas où un serveur serait hors service mais il augmente aussi en conséquence le temps de réponse à chaque requête. Le temps minimum d'attente est celui de l'aller-retour entre les serveurs primaire et de standby.
Les transactions où seule une lecture est effectuée ou qui consistent à annuler une transaction ne nécessitent pas d'attendre les serveurs de standby. Les validations concernant les transactions imbriquées ne nécessitent pas non plus d'attendre la réponse des serveurs de standby, cela n'affecte en fait que les validations principales. De longues opérations comme le chargement de données ou la création d'index n'attendent pas le commit final pour synchroniser les données. Toutes les actions de validation en deux étapes nécessitent d'attendre la validation du standby, incluant autant l'opération de préparation que l'opération de validation.
Un standby synchrone peut être un standby de réplication physique ou un
abonné d'une réplication logique. Il peut aussi être tout autre
consommateur de flux de réplication physique ou logique qui sait comment
gérer les messages de retour appropriés. En plus des systèmes intégrés de
réplication physique et logique, cela inclut le support des outils tels
que pg_receivewal
et pg_recvlogical
ainsi que les systèmes de réplication et outils personnalisés tiers.
Une fois la streaming replication configurée, la configuration de la réplication synchrone
ne demande qu'une unique étape de configuration supplémentaire :
la variable synchronous_standby_names doit être définie à
une valeur non vide. La variable synchronous_commit
doit aussi être définie à
on
, mais comme il s'agit d'une valeur par défaut, il n'est pas nécessaire de la
modifier. (Voir Section 19.5.1 et
Section 19.6.2.)
Cette configuration va entraîner l'attente de la confirmation de l'écriture permanente de chaque validation
sur le serveur de standby.
La variable synchronous_commit
peut être définie soit par des
utilisateurs, soit par le fichier de configuration pour des utilisateurs ou des bases de données fixées, soit
dynamiquement par des applications, pour contrôler la robustesse des échanges transactionnels.
Suite à l'enregistrement sur disque d'une validation sur le serveur primaire,
l'enregistrement WAL est envoyé au serveur de standby. Le serveur de standby
retourne une réponse à chaque fois qu'un nouveau lot de données WAL est
écrit sur disque, à moins que le paramètre
wal_receiver_status_interval
soit défini à zéro sur le
serveur standby. Dans le cas où le paramètre synchronous_commit
est configuré à la valeur remote_apply
, le serveur
standby envoie des messages de réponse quand l'enregistrement de validation
(commit) est rejoué, rendant la transaction visible. Si le serveur standby
est configuré en serveur synchrone d'après la configuration du paramètre
synchronous_standby_names
sur le primaire, le message de réponse provenant du standby sera considéré
parmi ceux des autres serveurs standby pour décider du moment de libération
des transactions attendant la confirmation de la bonne réception de
l'enregistrement de commit. Ces paramètres permettent à l'administrateur
de spécifier quels serveurs de standby suivront un comportement synchrone.
Remarquez ici que la configuration de la réplication synchrone se situe
sur le serveur primaire. Les serveurs standbys nommés doivent être
directement connectés au primaire ; le primaire ne connaît rien des
serveurs standbys utilisant la réplication en cascade.
Configurer synchronous_commit
à
remote_write
fera que chaque COMMIT attendra la
confirmation de la réception en mémoire de l'enregistrement du COMMIT
par le standby et son écriture via la système d'exploitation, sans que
les données du cache du système ne soient vidées sur disque au niveau
du serveur en standby. Cette configuration fournit une garantie moindre
de durabilité que la configuration on
: le standby
peut perdre les données dans le cas d'un crash du système d'exploitation,
mais pas dans le cas du crash de PostgreSQL.
Cependant, il s'agit d'une configuration utile en pratique car il diminue
le temps de réponse pour la transaction. Des pertes de données ne peuvent
survenir que si le serveur primaire et le standby tombent en même temps et
que la base de données du primaire est corrompue.
Configurer synchronous_commit
à remote_apply
fera en sorte que chaque commit devra attendre le retour des standbys synchrones
actuels indiquant qu'ils ont bien rejoué la transaction, la rendant visible aux
requêtes des utilisateurs. Dans des cas simples, ceci permet une répartition de
chaque sans incohérence.
Habituellement, un signal d'arrêt rapide (fast shutdown) annule les transactions en cours sur tous les processus serveur. Cependant, dans le cas de la réplication asynchrone, le serveur n'effectuera pas un arrêt complet avant que chaque enregistrement WAL ne soit transféré aux serveurs de standby connectés.
La réplication synchrone supporte un ou plusieurs serveurs standbys
synchrones. Les transactions attendront que tous les serveurs en standby
considérés synchrones confirment la réception de leurs données. Le nombre
de standbys dont les transactions doivent attendre la réponse est indiqué
dans le paramètre synchronous_standby_names
. Ce paramètre
indique aussi une liste des noms des serveurs standbys ou l'emploi
de la méthode (FIRST
ou ANY
) pour choisir
sur quel serveur synchrone basculer parmi l'ensemble des serveurs listés.
La méthode FIRST
définit une réplication synchrone
priorisée : elle temporise la validation de la transaction
jusqu'à que les enregistrements WAL soient répliqués en
fonction de la priorité définie des serveurs standbys dans une liste
ordonnée.
Le serveur standby dont le nom apparait en premier sur la liste est
prioritaire et est celui qui est considéré comme synchrone.
Les serveurs standbys suivants sont considérés comme un/des
serveurs standbys synchrones potentiels.
Si le premier serveur synchrone venait à tomber,
il serait immédiatement remplacé par le serveur
standby prioritaire suivant.
Voici un exemple de configuration de synchronous_standby_names
pour la
réplication synchrone priorisée :
synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'
Dans cet exemple, si les quatre serveurs standbys s1
,
s2
, s3
et s4
sont fonctionnels et en cours d'exécution, les deux serveurs
s1
et s2
seront choisis comme
standbys synchrones car leurs noms apparaissent en premier dans la
liste des serveurs standbys. s3
est un serveur
standby synchrone potentiel et prendra le rôle d'un standby synchrone
si s1
ou s2
tombe.
s4
est un standby asynchrone et son nom n'est pas dans la liste.
La méthode ANY
définit une réplication synchrone
basée sur un quorum : elle temporise la validation de la
transaction jusqu'à ce que les enregistrements WAL soient répliqués
au moins sur le nombre de serveurs définis dans
la liste.
Voici un exemple de configuration du paramètre synchronous_standby_names
pour la
réplication synchrone avec un quorum :
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
Dans cet exemple, sur quatre serveurs standbys démarrés s1
,
s2
,s3
et s4
,
pour obtenir la validation d'une transaction, le serveur primaire
attendra la réponse d'au minimum deux standbys parmi s1
,
s2
et s3
. s4
est un standby asynchrone et son nom n'est pas dans la liste.
L'état de synchronicité des serveurs standbys peut être consulté
avec la vue pg_stat_replication
.
La réplication synchrone nécessite souvent d'organiser avec une grande attention les serveurs de standby pour apporter un bon niveau de performances aux applications. Les phases d'attente d'écriture n'utilisent pas les ressources systèmes, mais les verrous transactionnels restent positionnés jusqu'à ce que le transfert vers les serveurs de standby soit confirmé. En conséquence, une utilisation non avertie de la réplication synchrone aura pour impact une baisse des performances de la base de donnée d'une application due à l'augmentation des temps de réponses et à un moins bon support de la charge.
PostgreSQL permet aux développeurs d'application de spécifier le niveau de robustesse à employer pour la réplication. Cela peut être spécifié pour le système entier, mais aussi pour des utilisateurs ou des connexions spécifiques, ou encore pour des transactions individuelles.
Par exemple, une répartition du travail pour une application pourrait être constituée de : 10 % de modifications concernant des articles de clients importants, et 90 % de modifications de moindre importance et qui ne devraient pas avoir d'impact sur le métier si elles venaient à être perdues, comme des dialogues de messagerie entre utilisateurs.
Les options de réplication synchrone spécifiées par une application (sur le serveur primaire) permettent de n'utiliser la réplication synchrone que pour les modifications les plus importantes, sans affecter les performances sur la plus grosse partie des traitements. Les options modifiables par les applications sont un outil important permettant d'apporter les bénéfices de la réplication synchrone aux applications nécessitant de la haute performance.
Il est conseillé de disposer d'une bande passante réseau supérieure à la quantité de données WAL générées.
synchronous_standby_names
indique le nombre et les noms
des serveurs standbys synchrones pour lesquels les validations de
transactions effectuées lorsque synchronous_commit
est
configurée à on
, remote_apply
ou
remote_write
, attendront leur réponse. Ces validations
de transactions pourraient ne jamais se terminer si un des standbys
synchrones s'arrêtait brutalement.
La meilleure solution pour la haute disponibilité est de s'assurer que vous
conservez autant de serveurs standbys synchrones que demandés. Ceci se fait
en nommant plusieurs standbys synchrones potentiels avec
synchronous_standby_names
.
Dans la réplication synchrone dite priorisée, les serveurs standbys dont les noms apparaissent en premier seront utilisé comme standbys synchrones. Les standbys définis ensuite prendront la place de serveur synchrone si l'un des serveurs venait à tomber.
Dans la réplication dite de quorum, tous les standbys spécifiés dans la liste seront utilisés comme des standbys synchrones potentiels. Même si l'un d'entre eux tombe, les autres standbys continueront de prétendre au rôle de standby synchrone.
Au moment où le premier serveur de standby s'attache au serveur primaire, il est possible qu'il ne soit pas exactement
synchronisé. Cet état est appelé le mode catchup
. Une fois
la différence entre le serveur de standby et le serveur primaire ramenée à zéro,
le mode streaming
est atteint.
La durée du mode catchup peut être longue surtout juste après la création du serveur de standby.
Si le serveur de standby est arrêté sur cette période, alors la durée du mode CATCHUP
sera d'autant plus longue.
Le serveur de standby ne peut devenir un serveur de standby synchrone
que lorsque le mode streaming
est atteint.
L'état de synchronicité des serveurs standbys peut être consulté
avec la vue pg_stat_replication
.
Si le serveur primaire redémarre alors que des opérations de commit étaient en attente de confirmation, les transactions en attente ne seront réellement enregistrées qu'au moment où la base de données du serveur primaire sera redémarrée. Il n'y a aucun moyen de savoir si tous les serveurs de standby ont reçu toutes les données WAL nécessaires au moment où le serveur primaire est déclaré hors-service. Des transactions pourraient ne pas être considérées comme sauvegardées sur le serveur de standby, même si elles l'étaient sur le serveur primaire. La seule garantie offerte dans ce cadre est que l'application ne recevra pas de confirmation explicite de la réussite d'une opération de validation avant qu'il soit sûr que les données WAL sont reçues proprement par tous les serveurs de standby synchrones.
Si vous ne pouvez vraiment pas conserver autant de serveurs standbys
synchrones que demandés, alors vous devriez diminuer le nombre de standbys
synchrones dont le système doit attendre les réponses aux validations de
transactions, en modifiant synchronous_standby_names
(ou
en le désactivant) et en rechargeant le fichier de configuration du serveur
primaire.
Si le serveur primaire n'est pas accessible par les serveurs de standby restants, il est conseillé de basculer vers le meilleur candidat possible parmi ces serveurs de standby.
S'il est nécessaire de recréer un serveur de standby alors que des transactions sont
en attente de confirmation, prenez garde à ce que les commandes pg_start_backup() et
pg_stop_backup() soient exécutées dans un contexte où
la variable synchronous_commit
vaut off
car, dans le cas contraire, ces
requêtes attendront indéfiniment l'apparition de ce serveur de standby.
Lorsque l'archivage continu est utilisé sur un standby, il existe
deux scénarios possibles : soit les archives sont partagées entre le
serveur primaire et le serveur de standby, soit le standby peut avoir
ses propres archives. Si le serveur possède ses propres archives,
en définissant le paramètre archive_mode
à
always
, le standby exécutera la commande
d'archivage pour chaque segment de WAL qu'il aura reçu, peu importe
qu'il utilise la réplication par les archives ou la réplication
streaming.
La gestion par archivage partagé peut être faite de la même manière,
mais archive_command
doit d'abord tester si le segment
de WAL existe, et si le fichier existant contient les mêmes informations.
Cela demande plus de précaution lors de la définition de la commande,
car elle doit vérifier qu'elle n'écrase pas un fichier existant avec
un contenu différent, et doit renvoyer un succès si le même fichier
est archivé deux fois. Tout ceci devant être en plus effectué sans
concurrence si deux serveurs essayent d'archiver le même fichier au
même moment.
Si archive_mode
est défini à on
,
l'archivage n'est pas actif pendant les modes recovery et standby.
Si le serveur standby est promu, il commencera à réaliser l'archivage
après sa promotion, et il archivera uniquement les fichiers (WAL et
historique) qu'il a lui
même produit. Pour être sûr d'obtenir un jeu complet d'archives, vous
devez vous assurer que tous les fichiers WAL ont été archivés avant
qu'ils atteignent le standby. C'est implicitement toujours le cas
avec un log-shipping s'appuyant sur les archives, car le standby ne
récupère que des informations provenant de ces mêmes fichiers
archivés. Ce n'est pas le cas dans le cadre de la réplication
streaming.
Lorsqu'un serveur est en standby il n'y a aucune différence
entre les modes on
et always
.