
La réplication streaming de PostgreSQL copie en continu les journaux de transactions (WAL) du primary vers un ou plusieurs standby. Le standby peut servir de hot standby (lectures en temps réel) et prendre le relais en cas de panne via un failover (promote). Ce guide monte un cluster à deux nœuds de bout en bout, de la configuration du primary jusqu'au promote du standby, avec toutes les commandes testées sur PostgreSQL 18.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Configurer un primary pour la réplication streaming (wal_level, rôle dédié, slot, pg_hba)
- Initialiser un standby avec
pg_basebackup -Ret comprendrestandby.signal - Surveiller la réplication :
pg_stat_replication,pg_stat_wal_receiver,pg_wal_lsn_diff() - Utiliser le hot standby pour les lectures et comprendre ses limites
- Exécuter un failover manuel avec
pg_promote()et vérifier le changement de timeline - Distinguer réplication physique et logique pour choisir la bonne approche
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »La réplication streaming répond à des besoins concrets d'administration :
- Vous administrez un PostgreSQL en production et vous voulez éliminer le point de défaillance unique (SPOF)
- Vous avez besoin d'un standby en lecture pour décharger le primary des requêtes de reporting
- Vous préparez une maintenance planifiée (montée de version, migration) avec basculement contrôlé
- Vous devez garantir une reprise rapide (RTO court) en cas de crash du serveur principal
- Vous préparez la certification LFCS ou RHCSA et devez maîtriser la réplication PostgreSQL
Ce guide ne couvre pas…
Section intitulée « Ce guide ne couvre pas… »Trois sujets voisins reviennent systématiquement dès qu'on parle de réplication, et les mélanger conduit à des architectures bancales. Voici où ils sont traités :
- La sauvegarde et le PITR (Point-In-Time Recovery) → voir le guide sauvegarde-restauration
- L'orchestration automatique du failover (Patroni, repmgr, pg_auto_failover) → mentionnée en fin de guide
- La réplication logique détaillée → aperçu en fin de guide, guide dédié à venir
pg_basebackup apparaît ici comme outil d'initialisation du standby, pas comme
outil de sauvegarde.
Prérequis
Section intitulée « Prérequis »- Deux serveurs avec PostgreSQL installé (même version majeure)
- Un réseau permettant la connexion TCP entre les deux nœuds (port 5432)
- Les bases du guide d'installation et de configuration
- Accès superuser (
postgres) ou un rôle avecREPLICATION
Lab utilisé dans ce guide :
| Rôle | Hostname | IP | OS | PostgreSQL |
|---|---|---|---|---|
| Primary | pg-primary | 192.168.122.61 | Debian 12 | 18.3 |
| Standby | pg-standby | 192.168.122.62 | Debian 12 | 18.3 |
La réplication n'est pas une sauvegarde
Section intitulée « La réplication n'est pas une sauvegarde »C'est la confusion la plus coûteuse en exploitation, et elle vient d'un raccourci compréhensible : « mes données sont sur deux machines, donc elles sont protégées ». La réplication protège contre la perte d'une machine, pas contre la perte de données. Les deux risques appellent deux dispositifs différents, et l'un ne remplace jamais l'autre.
Réplication physique vs logique
Section intitulée « Réplication physique vs logique »PostgreSQL propose deux types de réplication. Ce guide se concentre sur la réplication physique (streaming), la plus courante pour la haute disponibilité.
Physique : copie bit à bit des WAL
Section intitulée « Physique : copie bit à bit des WAL »La réplication physique (streaming) copie les journaux WAL octet par octet. Le standby est une copie exacte du primary : même structure, mêmes bases, mêmes données, même état.
Caractéristiques :
- Copie tout le cluster (toutes les bases, tous les rôles)
- Le standby est en lecture seule (hot standby)
- Très faible latence (quasi temps réel)
- Le standby peut servir de base pour un failover
Logique : réplication sélective par publication/souscription
Section intitulée « Logique : réplication sélective par publication/souscription »La réplication logique transmet des changements au niveau des lignes (INSERT,
UPDATE, DELETE) pour des tables choisies. Elle utilise le mécanisme
PUBLICATION / SUBSCRIPTION introduit en PostgreSQL 10.
Caractéristiques :
- Réplique des tables spécifiques, pas le cluster entier
- Le souscripteur est un serveur indépendant (lecture-écriture)
- Permet la réplication entre versions différentes de PostgreSQL
- Utile pour la migration, l'agrégation de données ou le partage sélectif
Quand utiliser quoi
Section intitulée « Quand utiliser quoi »La ligne Objectif principal suffit à trancher dans la grande majorité des cas : si vous cherchez à survivre à la perte d'un serveur, c'est la réplication physique ; si vous cherchez à déplacer ou partager des données, c'est la logique. La ligne Versions différentes est celle qui décide dans un cas particulier mais fréquent, la montée de version majeure : la réplication physique impose la même version majeure des deux côtés, donc elle ne peut pas servir à migrer d'un PostgreSQL 16 vers un 18.
| Critère | Physique (streaming) | Logique |
|---|---|---|
| Objectif principal | Haute disponibilité, failover | Migration, réplication sélective |
| Granularité | Cluster entier | Tables choisies |
| Standby en lecture | Oui (hot standby) | Le souscripteur est en lecture-écriture |
| Failover | Oui (pg_promote) | Non conçu pour |
| Versions différentes | Non (même version majeure) | Oui |
| Latence | Très faible | Faible à modérée |
| Complexité | Simple | Plus complexe (conflits possibles) |
Configurer le primary
Section intitulée « Configurer le primary »La configuration du primary se fait en quatre étapes : paramètres de réplication, rôle dédié, slot de réplication et autorisation réseau.
Paramètres de réplication
Section intitulée « Paramètres de réplication »Les paramètres essentiels se trouvent dans postgresql.conf. Sur Debian, on
utilise ALTER SYSTEM pour les modifier proprement :
-- Niveau WAL nécessaire à la réplication.-- C'est déjà la valeur par défaut : cette ligne sert à s'en assurer,-- notamment si le serveur a été passé en 'minimal' pour du chargement massif.ALTER SYSTEM SET wal_level = 'replica';
-- Nombre maximum de connexions de réplication simultanéesALTER SYSTEM SET max_wal_senders = 5;
-- Nombre maximum de slots de réplicationALTER SYSTEM SET max_replication_slots = 10;
-- Quantité de WAL conservée pour les standby en retardALTER SYSTEM SET wal_keep_size = '256MB';
-- Écouter sur toutes les interfaces (pas uniquement localhost)ALTER SYSTEM SET listen_addresses = '*';Après redémarrage, vérifiez que les paramètres sont bien appliqués :
SELECT name, settingFROM pg_settingsWHERE name IN ( 'wal_level', 'max_wal_senders', 'max_replication_slots', 'wal_keep_size', 'listen_addresses'); name | setting------------------------+--------- listen_addresses | * max_replication_slots | 10 max_wal_senders | 5 wal_keep_size | 256 wal_level | replicaCréer un rôle REPLICATION dédié
Section intitulée « Créer un rôle REPLICATION dédié »Le standby doit s'authentifier auprès du primary pour ouvrir son flux de WAL. Utiliser le rôle
postgres (superuser) pour cette connexion est une mauvaise pratique : le mot de passe se retrouve
stocké côté standby, et il ouvrirait un accès total au primary si le standby était compromis. Créez
un rôle dédié avec uniquement les privilèges LOGIN et REPLICATION :
CREATE ROLE replicator WITH LOGIN REPLICATION PASSWORD 'motdepasse_fort';Ce rôle ne peut ni créer de bases, ni lire vos données, ni modifier quoi que ce soit. Il sert exclusivement à la connexion de réplication.
Créer un slot de réplication physique
Section intitulée « Créer un slot de réplication physique »Un slot de réplication garantit que le primary conserve les WAL nécessaires au standby, même si celui-ci est temporairement déconnecté. Sans slot, un standby déconnecté trop longtemps peut perdre la synchronisation si les WAL ont été recyclés.
SELECT pg_create_physical_replication_slot('standby_slot');Vérification :
SELECT slot_name, slot_type, active FROM pg_replication_slots; slot_name | slot_type | active--------------+-----------+-------- standby_slot | physical | fLe slot est inactif (active = f) tant qu'aucun standby ne l'utilise.
Supprimer un slot orphelin à la main suppose de s'en apercevoir à temps. PostgreSQL fournit deux garde-fous qui rendent cette surveillance beaucoup moins critique.
Autoriser la réplication dans pg_hba.conf
Section intitulée « Autoriser la réplication dans pg_hba.conf »Le fichier pg_hba.conf contrôle les connexions autorisées. Ajoutez une ligne
pour autoriser le rôle replicator depuis l'IP du standby :
# TYPE DATABASE USER ADDRESS METHODhost replication replicator 192.168.122.62/32 scram-sha-256Rechargez la configuration :
sudo systemctl reload postgresqlVérification, les règles actives sont visibles dans pg_hba_file_rules :
SELECT line_number, type, database, user_name, address, netmask, auth_methodFROM pg_hba_file_rulesWHERE 'replication' = ANY(database); line_number | type | database | user_name | address | netmask | auth_method-------------+------+---------------+--------------+----------------+---------------+--------------- 117 | host | {replication} | {replicator} | 192.168.122.62 | 255.255.255.255 | scram-sha-256Initialiser le standby avec pg_basebackup
Section intitulée « Initialiser le standby avec pg_basebackup »Le standby est initialisé en copiant l'intégralité du cluster du primary avec
pg_basebackup. Cette commande s'exécute sur le standby.
Préparer le standby
Section intitulée « Préparer le standby »Avant de lancer pg_basebackup, le répertoire de données du standby doit être
vide. Si PostgreSQL a été installé et initialisé automatiquement, videz-le :
# Arrêter PostgreSQL sur le standbysudo systemctl stop postgresql
# Vider le répertoire de donnéessudo -u postgres find /var/lib/postgresql/18/main -mindepth 1 -deleteCopier le cluster avec pg_basebackup -R
Section intitulée « Copier le cluster avec pg_basebackup -R »L'option -R est cruciale : elle génère automatiquement standby.signal et
écrit le primary_conninfo dans postgresql.auto.conf.
sudo -u postgres pg_basebackup \ -h 192.168.122.61 \ -U replicator \ -D /var/lib/postgresql/18/main \ -Fp -Xs -P -R| Option | Rôle |
|---|---|
-h | Adresse du primary |
-U | Rôle de réplication |
-D | Répertoire de données cible |
-Fp | Format plain (fichiers) |
-Xs | Streaming des WAL pendant la copie |
-P | Afficher la progression |
-R | Générer standby.signal + primary_conninfo |
Un dernier point avant de lancer la commande : pg_basebackup s'exécute avec les droits du compte
système local et fait confiance à ce que le primary lui envoie. Cette confiance a déjà été
exploitée.
Ce que -R génère
Section intitulée « Ce que -R génère »Deux éléments sont créés automatiquement par l'option -R :
1. Le fichier standby.signal, un fichier vide qui indique à PostgreSQL de
démarrer en mode standby :
ls -la /var/lib/postgresql/18/main/standby.signal-rw------- 1 postgres postgres 0 Apr 13 11:44 standby.signal2. Le paramètre primary_conninfo dans postgresql.auto.conf, la chaîne
de connexion vers le primary :
grep primary_conninfo /var/lib/postgresql/18/main/postgresql.auto.confprimary_conninfo = 'user=replicator password=motdepasse_fort channel_binding=prefer host=192.168.122.61 port=5432 sslmode=prefer sslnegotiation=postgres sslcompression=0 sslcertmode=allow sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable'pg_basebackup inscrit tous les paramètres libpq avec leur valeur effective,
y compris ceux que vous n'avez pas fournis. La ligne est donc longue, mais seuls
user, host, port et password viennent de votre commande ; le reste
reprend les valeurs par défaut du client.
Il reste un paramètre à ajouter, que pg_basebackup -R ne génère pas : le nom du slot. Sans
lui, le standby se connectera bien au primary, mais sans réserver de WAL, et le slot créé plus haut
restera inutilisé. Renseignez primary_slot_name avant le premier démarrage :
echo "primary_slot_name = 'standby_slot'" | \ sudo -u postgres tee -a /var/lib/postgresql/18/main/postgresql.auto.confDémarrer le standby
Section intitulée « Démarrer le standby »À ce stade, le répertoire de données contient une copie complète du primary, le fichier
standby.signal et la chaîne de connexion. PostgreSQL détecte standby.signal au démarrage et
entre directement en mode recovery au lieu d'ouvrir la base en lecture-écriture. Le démarrage
peut prendre quelques secondes de plus qu'un démarrage normal, le temps de rejouer les WAL
accumulés pendant la copie.
sudo systemctl start postgresqlVérifiez immédiatement que le standby est bien en mode recovery :
SELECT pg_is_in_recovery(); pg_is_in_recovery------------------- tt (true) confirme que PostgreSQL fonctionne en mode standby.
Vérifier la réplication
Section intitulée « Vérifier la réplication »Une fois le standby démarré, il faut vérifier que la réplication streaming est
active et fonctionnelle. Les deux vues clés sont pg_stat_replication (côté
primary) et pg_stat_wal_receiver (côté standby).
Sur le primary : pg_stat_replication
Section intitulée « Sur le primary : pg_stat_replication »Cette vue montre les connexions de réplication actives :
SELECT pid, state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsnFROM pg_stat_replication; pid | state | sync_state | sent_lsn | write_lsn | flush_lsn | replay_lsn------+-----------+------------+-----------+-----------+-----------+------------ 4536 | streaming | async | 0/30067F0 | 0/30067F0 | 0/30067F0 | 0/30067F0| Colonne | Signification |
|---|---|
state | streaming = réplication active en temps réel |
sync_state | async = réplication asynchrone (par défaut) |
sent_lsn | Dernière position WAL envoyée au standby |
write_lsn | Dernière position écrite en mémoire par le standby |
flush_lsn | Dernière position écrite sur disque par le standby |
replay_lsn | Dernière position rejouée par le standby |
Quand les quatre colonnes LSN sont identiques, le standby est parfaitement synchronisé.
Sur le standby : pg_stat_wal_receiver
Section intitulée « Sur le standby : pg_stat_wal_receiver »Cette vue montre la connexion de réplication active côté standby :
SELECT status, sender_host, sender_port, slot_name, flushed_lsnFROM pg_stat_wal_receiver; status | sender_host | sender_port | slot_name | flushed_lsn-----------+----------------+-------------+--------------+------------- streaming | 192.168.122.61 | 5432 | standby_slot | 0/30067F0Le status = streaming confirme que le standby reçoit les WAL en continu.
Contrôlez aussi la colonne slot_name : si elle est vide, le standby
n'utilise pas le slot que vous avez créé sur le primary, parce que
primary_slot_name n'a pas été renseigné. La réplication fonctionne quand
même, mais vous perdez la garantie de rétention des WAL et le slot restera
active = f sur le primary.
Calculer le lag avec pg_wal_lsn_diff()
Section intitulée « Calculer le lag avec pg_wal_lsn_diff() »Pour mesurer l'écart entre le primary et le standby en octets :
-- Sur le primarySELECT client_addr, pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytesFROM pg_stat_replication; client_addr | replay_lag_bytes-----------------+------------------ 192.168.122.62 | 0Un lag de 0 octets signifie que le standby a rejoué tout ce que le primary lui a envoyé. En production sous charge, un léger lag (quelques Ko) est normal.
Tester la réplication en temps réel
Section intitulée « Tester la réplication en temps réel »Le test le plus parlant : écrire sur le primary, lire sur le standby.
Sur le primary, insérez une ligne :
INSERT INTO app.servers (hostname, ip_address, os, role, env, cpu_cores, ram_gb)VALUES ('srv-repl-test', '10.0.0.42', 'Debian 12', 'test', 'dev', 2, 4);Sur le standby, vérifiez immédiatement :
SELECT hostname, ip_address FROM app.serversWHERE hostname = 'srv-repl-test'; hostname | ip_address---------------+------------ srv-repl-test | 10.0.0.42La ligne est visible quasi instantanément. Le standby reçoit et rejoue les WAL en continu.
Hot standby : lectures sur le réplica
Section intitulée « Hot standby : lectures sur le réplica »Le hot standby permet d'exécuter des requêtes en lecture sur un standby
pendant qu'il continue de recevoir et rejouer les WAL. Le paramètre
hot_standby contrôle cette fonctionnalité, il est à on par défaut
depuis PostgreSQL 10 et n'a d'effet que sur un serveur en recovery/standby.
Aucune configuration n'est nécessaire sur le primary.
Ce qu'on peut faire
Section intitulée « Ce qu'on peut faire »Le hot standby accepte les opérations en lecture seule :
-- Requêtes SELECTSELECT * FROM app.servers WHERE env = 'prod';
-- Vues statistiquesSELECT * FROM pg_stat_user_tables;
-- Plans d'exécutionEXPLAIN ANALYZE SELECT * FROM app.servers WHERE hostname LIKE 'srv%';C'est idéal pour :
- Le reporting et les requêtes analytiques longues
- Les lectures distribuées (connecter les applications en lecture au standby)
- Le debug et l'analyse de performances sans impacter le primary
Ce qu'on ne peut pas faire
Section intitulée « Ce qu'on ne peut pas faire »Toute opération en écriture est refusée :
-- INSERT → erreurINSERT INTO app.servers (hostname) VALUES ('test');ERROR: cannot execute INSERT in a read-only transaction-- DDL → erreurCREATE TABLE app.test (id serial);ERROR: cannot execute CREATE TABLE in a read-only transactionC'est un comportement normal et attendu : le standby est une copie en lecture seule du primary.
Conflits hot standby
Section intitulée « Conflits hot standby »Parfois, le rejeu des WAL sur le standby entre en conflit avec des requêtes de
lecture longues. Par exemple, si le primary fait un VACUUM qui supprime des
lignes mortes, le standby doit rejouer cette opération, mais une requête
SELECT est peut-être en train de lire ces lignes.
Le paramètre max_standby_streaming_delay contrôle combien de temps le standby
attend avant d'annuler la requête en conflit :
SHOW max_standby_streaming_delay; max_standby_streaming_delay----------------------------- 30sPar défaut, le standby attend 30 secondes avant d'annuler la requête conflictuelle. Augmentez cette valeur si vos requêtes de reporting sont longues :
ALTER SYSTEM SET max_standby_streaming_delay = '120s';SELECT pg_reload_conf();Failover manuel
Section intitulée « Failover manuel »Le failover consiste à promouvoir le standby en nouveau primary quand l'ancien primary est indisponible (panne, maintenance, migration).
Vérifier l'état avant le promote
Section intitulée « Vérifier l'état avant le promote »Avant de promouvoir, assurez-vous que le standby est bien synchronisé :
-- Sur le standby : vérifier qu'on est bien en recoverySELECT pg_is_in_recovery();-- → t
-- Vérifier la timeline actuelleSELECT timeline_id FROM pg_control_checkpoint();-- → 1
-- Vérifier que standby.signal existe-- ls -la /var/lib/postgresql/18/main/standby.signalPromouvoir avec pg_promote()
Section intitulée « Promouvoir avec pg_promote() »La promotion se fait en une seule commande SQL, exécutée sur le standby :
SELECT pg_promote(); pg_promote------------ tVérifier le promote
Section intitulée « Vérifier le promote »Après le promote, plusieurs changements sont immédiatement observables sur l'ex-standby :
1. Plus en recovery :
SELECT pg_is_in_recovery(); pg_is_in_recovery------------------- ff (false), le serveur n'est plus un standby, il accepte les écritures.
2. Nouvelle timeline :
SELECT timeline_id FROM pg_control_checkpoint(); timeline_id------------- 2La timeline passe de 1 à 2. Chaque promote crée une nouvelle timeline pour éviter toute confusion avec les WAL de l'ancienne.
3. standby.signal supprimé :
ls /var/lib/postgresql/18/main/standby.signalls: cannot access '/var/lib/postgresql/18/main/standby.signal': No such file or directoryPostgreSQL a automatiquement supprimé le fichier.
4. pg_stat_wal_receiver vide :
SELECT * FROM pg_stat_wal_receiver;(0 rows)Le standby ne reçoit plus de WAL, il est maintenant un primary autonome.
5. Les écritures fonctionnent :
INSERT INTO app.servers (hostname, ip_address, os, role, env, cpu_cores, ram_gb)VALUES ('srv-after-promote', '10.0.0.99', 'Debian 12', 'test', 'dev', 2, 4);INSERT 0 1L'INSERT passe, le DDL aussi. Le serveur est pleinement opérationnel en lecture-écriture.
Que faire de l'ancien primary ?
Section intitulée « Que faire de l'ancien primary ? »Après le promote, l'ancien primary est toujours sur la timeline 1 et ne sait pas que le standby a été promu. Il y a trois options :
| Option | Quand l'utiliser |
|---|---|
| pg_basebackup complet | L'ancien primary a beaucoup divergé ou est corrompu |
| pg_rewind | L'ancien primary a peu divergé (recommandé) |
| Reconstruire entièrement | Changement de version ou de configuration |
pg_rewind est l'option la plus efficace quand l'ancien primary n'a accepté que peu d'écritures après la déconnexion du standby :
# Arrêter l'ancien primarysudo systemctl stop postgresql
# Resynchroniser avec le nouveau primarysudo -u postgres pg_rewind \ --target-pgdata=/var/lib/postgresql/18/main \ --source-server="host=192.168.122.62 user=postgres dbname=postgres"Ensuite, créez un standby.signal et configurez primary_conninfo pour que
l'ancien primary devienne le nouveau standby et pointe vers le nouveau primary.
Réplication synchrone
Section intitulée « Réplication synchrone »Jusqu'ici, tout ce qui a été monté fonctionne en mode asynchrone, le comportement par défaut de PostgreSQL. Cette section décrit le mode qui garantit qu'aucune transaction validée n'est perdue, au prix d'un couplage fort entre le primary et son standby. C'est un choix de RPO, pas d'architecture : le montage reste exactement le même, seuls deux paramètres changent.
La réplication synchrone garantit qu'un COMMIT n'est validé côté client
que lorsque le standby a confirmé avoir écrit (ou rejoué) les WAL
correspondants. C'est le mode le plus sûr pour le RPO (zéro perte de données).
Activer la réplication synchrone
Section intitulée « Activer la réplication synchrone »Le point qui trompe le plus souvent : synchronous_commit vaut déjà on par défaut, et pourtant
la réplication reste asynchrone. La raison est que synchronous_commit = on garantit seulement
l'écriture locale du WAL sur disque avant de rendre la main au client. Le mode synchrone à
proprement parler s'active en désignant au moins un standby dans synchronous_standby_names,
qui est vide par défaut. C'est ce paramètre, et lui seul, qui fait passer sync_state de async
à sync.
-- Sur le primary-- synchronous_commit = on est déjà la valeur par défaut-- C'est synchronous_standby_names qui active le mode synchroneALTER SYSTEM SET synchronous_standby_names = 'FIRST 1 (standby1)';SELECT pg_reload_conf();| Paramètre | Rôle |
|---|---|
synchronous_commit = on | Déjà la valeur par défaut, le COMMIT attend la confirmation du standby |
synchronous_standby_names | L'activateur réel : quels standby sont synchrones (par application_name) |
Après configuration, pg_stat_replication affiche sync au lieu de async :
SELECT application_name, sync_state FROM pg_stat_replication; application_name | sync_state------------------+------------ walreceiver | syncCompromis de la réplication synchrone
Section intitulée « Compromis de la réplication synchrone »Lisez ce tableau ligne par ligne, en couple : chaque avantage a un prix direct en face. La deuxième ligne est la plus lourde de conséquences, et elle surprend souvent en production : la disponibilité du primary devient dépendante de celle du standby. Vous avez déplacé le point de défaillance unique, vous ne l'avez pas supprimé. C'est pourquoi la réplication synchrone se déploie avec deux standby au minimum.
| Avantage | Inconvénient |
|---|---|
| RPO = 0 (zéro perte de données) | Latence accrue sur chaque COMMIT |
| Garantie de cohérence | Si le standby tombe, le primary bloque les COMMIT |
| Confiance pour les données critiques | Nécessite un réseau fiable et rapide |
Réplication logique : aperçu
Section intitulée « Réplication logique : aperçu »La réplication logique est un sujet à part entière. Voici un aperçu rapide du mécanisme pour comprendre quand l'envisager.
Principe
Section intitulée « Principe »Le primary crée une publication sur des tables choisies. Un autre serveur PostgreSQL crée une souscription pour recevoir les changements :
-- Sur le primary (publisher)CREATE PUBLICATION ma_publication FOR TABLE app.servers, app.deployments;
-- Sur le souscripteur (un serveur indépendant)CREATE SUBSCRIPTION ma_souscription CONNECTION 'host=192.168.122.61 dbname=labdb user=replicator password=motdepasse_fort' PUBLICATION ma_publication;Quand utiliser la réplication logique
Section intitulée « Quand utiliser la réplication logique »Les trois premiers cas ont un point commun : la source et la destination sont deux serveurs autonomes qui poursuivent des objectifs différents. Le quatrième point est une limite à retenir avant de partir sur cette voie par erreur, car un souscripteur ressemble à un standby vu de loin : il reçoit des données en continu et reste à jour. Mais il n'a ni timeline commune avec la source, ni notion de promotion, et rien ne garantit qu'il contient l'intégralité du cluster.
- Migration de version : répliquer d'un PostgreSQL 16 vers un 18
- Réplication sélective : ne transmettre que certaines tables
- Agrégation : collecter des données de plusieurs sources
- Pas pour le failover : le souscripteur n'est pas un standby (pas de timeline, pas de promote)
Outils d'orchestration automatique
Section intitulée « Outils d'orchestration automatique »Le failover manuel décrit plus haut suppose qu'un humain constate la panne, vérifie l'état du standby et lance la promotion. En pratique, cela représente plusieurs minutes d'indisponibilité, et un risque bien pire : le split-brain, quand l'ancien primary redevient joignable et accepte des écritures alors que le standby a déjà été promu. Automatiser le failover, c'est avant tout se doter d'un mécanisme de consensus capable de désigner un seul primary légitime.
Dépannage
Section intitulée « Dépannage »Le standby ne se connecte pas
Section intitulée « Le standby ne se connecte pas »Suivez ces quatre vérifications dans l'ordre, du réseau vers l'applicatif : chacune élimine une
couche. L'étape 3 est la plus discriminante, parce qu'elle reproduit exactement ce que fait le
standby : une connexion en mode réplication, qui emprunte une ligne différente de pg_hba.conf
qu'une connexion psql ordinaire. Un psql classique qui passe alors que la réplication échoue
signale presque toujours une ligne replication manquante ou mal placée.
-
Vérifier la connectivité réseau :
Fenêtre de terminal # Depuis le standbypg_isready -h 192.168.122.61 -p 5432 -
Vérifier pg_hba.conf sur le primary, le rôle de réplication doit être autorisé depuis l'IP du standby :
SELECT user_name, address, auth_methodFROM pg_hba_file_rulesWHERE 'replication' = ANY(database); -
Vérifier le mot de passe, testez la connexion manuellement :
Fenêtre de terminal psql "host=192.168.122.61 user=replicator dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;" -
Vérifier les logs du standby :
Fenêtre de terminal sudo tail -20 /var/log/postgresql/postgresql-18-main.log
Le lag augmente en continu
Section intitulée « Le lag augmente en continu »Un lag qui croît sans jamais redescendre ne se traite pas comme un pic ponctuel : cela signifie
que le standby rejoue les WAL moins vite que le primary ne les produit, et l'écart ne se comblera
pas tout seul. Avant de parcourir ce tableau, isolez la couche fautive en comparant les colonnes de
pg_stat_replication : si sent_lsn est loin devant flush_lsn, le problème est réseau ou disque
côté standby ; si flush_lsn est proche de sent_lsn mais que replay_lsn traîne, c'est le rejeu
qui bloque, souvent à cause d'une requête de lecture en conflit.
| Cause possible | Solution |
|---|---|
| Charge d'écriture très élevée sur le primary | Augmenter wal_keep_size, vérifier les IOPS disque du standby |
| Requêtes longues sur le standby (conflits) | Augmenter max_standby_streaming_delay ou déporter les requêtes |
| Réseau saturé | Vérifier la bande passante entre primary et standby |
| Slot de réplication non utilisé | Vérifier pg_replication_slots, supprimer les slots orphelins |
Le promote échoue
Section intitulée « Le promote échoue »pg_promote() renvoie f plutôt qu'une erreur quand la promotion n'aboutit pas dans le délai
imparti, ce qui donne un diagnostic pauvre. Les trois contrôles ci-dessous couvrent les causes
réelles, et le dernier est le plus rentable : le journal du serveur explique toujours pourquoi la
bascule a été refusée.
- Vérifiez que
pg_is_in_recovery()retournetavant le promote - Vérifiez que l'utilisateur a les droits (superuser ou rôle avec
pg_promote) - Consultez les logs :
sudo tail -30 /var/log/postgresql/postgresql-18-main.log
Slot orphelin qui remplit le disque
Section intitulée « Slot orphelin qui remplit le disque »Le symptôme se manifeste sur le primary, pas sur le standby : pg_wal grossit sans limite alors
que l'activité n'a pas changé. La requête ci-dessous quantifie le problème avant d'agir, en
traduisant l'écart de LSN retenu par chaque slot inactif en volume lisible. Ne supprimez un slot
qu'après avoir confirmé que le standby correspondant ne reviendra pas : la suppression est
définitive, et un standby qui se reconnecterait ensuite devrait être reconstruit.
-- Identifier les slots inactifsSELECT slot_name, active, pg_size_pretty( pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_walFROM pg_replication_slotsWHERE NOT active;
-- Supprimer un slot orphelinSELECT pg_drop_replication_slot('standby_slot');À retenir
Section intitulée « À retenir »- La réplication streaming copie les WAL en continu du primary vers le standby, en production, combinez-la avec l'archivage WAL (
restore_command) pour couvrir les déconnexions prolongées - La réplication n'est pas une sauvegarde : un
DROP TABLEest immédiatement répliqué pg_basebackup -Rinitialise le standby et génère automatiquementstandby.signal+primary_conninfo- Depuis PostgreSQL 12,
recovery.confn'existe plus, tout passe par les paramètres normaux - Les slots de réplication empêchent le recyclage prématuré des WAL, configurez
max_slot_wal_keep_sizeetidle_replication_slot_timeoutpour éviter un disque plein - Le hot standby accepte les lectures mais refuse toutes les écritures (
INSERT,UPDATE,DELETE, DDL) pg_promote()transforme le standby en primary autonome sur une nouvelle timeline, c'est irréversible- La réplication synchrone s'active via
synchronous_standby_names, elle garantit zéro perte de données mais bloque si le standby tombe - En production, utilisez un outil d'orchestration automatique (Patroni, repmgr) pour le failover