Guide sur la réplication logique PostgreSQL
Guide sur la réplication logique PostgreSQL
Réplication logique
DALIBO
L'expertise PostgreSQL
23.06
Table des matières
Sur ce document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Chers lectrices & lecteurs, . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
À propos de DALIBO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Licence Creative Commons CC‑BY‑NC‑SA . . . . . . . . . . . . . . . . . . . . . . . . . 2
Marques déposées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1/ Réplication logique 5
1.1 Objectifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.1 Au menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Principes de la réplication logique native . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.1 Réplication physique vs. logique . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2.2 Quelques termes essentiels . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.3 Réplication en streaming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.4 Granularité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.2.5 Possibilités sur les tables répliquées . . . . . . . . . . . . . . . . . . . . . . . 12
1.2.6 Limitations de la réplication logique . . . . . . . . . . . . . . . . . . . . . . . 14
1.3 Mise en place . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.3.1 Configurer le serveur origine . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.3.2 Configuration du serveur destination . . . . . . . . . . . . . . . . . . . . . . . 18
1.3.3 Créer une publication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.3.4 Souscrire à une publication . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.3.5 Options de la souscription (1/2) . . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.3.6 Options de la souscription (2/2) . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.4 Mise en place : exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.4.1 Serveurs et schéma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.4.2 Réplication complète . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.4.3 Configuration du serveur origine (1/2) . . . . . . . . . . . . . . . . . . . . . . 25
1.4.4 Configuration du serveur origine (2/2) . . . . . . . . . . . . . . . . . . . . . . 26
1.4.5 Configuration des 4 serveurs destinations . . . . . . . . . . . . . . . . . . . . 27
1.4.6 Créer une publication complète . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.4.7 Souscrire à la publication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.4.8 Tests de la réplication complète . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.4.9 Réplication partielle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.4.10 Réplication croisée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
iii
DALIBO Formations
iv Réplication logique
DALIBO Formations
Réplication logique v
DALIBO Formations
Sur ce document
Formation Module W5
Titre Réplication logique
Révision 23.06
PDF [Link]
EPUB [Link]
HTML [Link]
Slides [Link]
Nos formations PostgreSQL sont issues de nombreuses années d’études, d’expérience de terrain et
de passion pour les logiciels libres. Pour Dalibo, l’utilisation de PostgreSQL n’est pas une marque
d’opportunisme commercial, mais l’expression d’un engagement de longue date. Le choix de l’Open
Source est aussi le choix de l’implication dans la communauté du logiciel.
Au‑delà du contenu technique en lui‑même, notre intention est de transmettre les valeurs qui animent
et unissent les développeurs de PostgreSQL depuis toujours : partage, ouverture, transparence, créati‑
vité, dynamisme… Le but premier de nos formations est de vous aider à mieux exploiter toute la puis‑
sance de PostgreSQL mais nous espérons également qu’elles vous inciteront à devenir un membre
actif de la communauté en partageant à votre tour le savoir‑faire que vous aurez acquis avec nous.
Nous mettons un point d’honneur à maintenir nos manuels à jour, avec des informations précises et
des exemples détaillés. Toutefois malgré nos efforts et nos multiples relectures, il est probable que ce
document contienne des oublis, des coquilles, des imprécisions ou des erreurs. Si vous constatez un
souci, n’hésitez pas à le signaler via l’adresse [email protected] !
À propos de DALIBO
Réplication logique 1
DALIBO Formations
Remerciements
Ce manuel de formation est une aventure collective qui se transmet au sein de notre société depuis
des années. Nous remercions chaleureusement ici toutes les personnes qui ont contribué directement
ou indirectement à cet ouvrage, notamment :
Jean‑Paul Argudo, Alexandre Anriot, Carole Arnaud, Alexandre Baron, David Bidoc, Sharon Bonan,
Franck Boudehen, Arnaud Bruniquel, Damien Clochard, Christophe Courtois, Marc Cousin, Gilles Da‑
rold, Jehan‑Guillaume de Rorthais, Ronan Dunklau, Vik Fearing, Stefan Fercot, Pierre Giraud, Nicolas
Gollet, Dimitri Fontaine, Florent Jardin, Virginie Jourdan, Luc Lamarle, Denis Laxalde, Guillaume Le‑
large, Alain Lesage, Benoit Lobréau, Jean‑Louis Louër, Thibaut Madelaine, Adrien Nayrat, Alexandre
Pereira, Flavie Perette, Robin Portigliatti, Thomas Reiss, Maël Rimbault, Julien Rouhaud, Stéphane
Schildknecht, Julien Tachoires, Nicolas Thauvin, Be Hai Tran, Christophe Truffier, Cédric Villemain,
Thibaud Walkowiak, Frédéric Yhuel.
Cette formation est sous licence CC‑BY‑NC‑SA2 . Vous êtes libre de la redistribuer et/ou modifier aux
conditions suivantes :
– Paternité
– Pas d’utilisation commerciale
– Partage des conditions initiales à l’identique
Vous n’avez pas le droit d’utiliser cette création à des fins commerciales.
Si vous modifiez, transformez ou adaptez cette création, vous n’avez le droit de distribuer la création
qui en résulte que sous un contrat identique à celui‑ci.
Vous devez citer le nom de l’auteur original de la manière indiquée par l’auteur de l’œuvre ou le ti‑
tulaire des droits qui vous confère cette autorisation (mais pas d’une manière qui suggérerait qu’ils
vous soutiennent ou approuvent votre utilisation de l’œuvre). À chaque réutilisation ou distribution
de cette création, vous devez faire apparaître clairement au public les conditions contractuelles de
sa mise à disposition. La meilleure manière de les indiquer est un lien vers cette page web. Chacune
de ces conditions peut être levée si vous obtenez l’autorisation du titulaire des droits sur cette œuvre.
Rien dans ce contrat ne diminue ou ne restreint le droit moral de l’auteur ou des auteurs.
Cela inclut les diapositives, les manuels eux‑mêmes et les travaux pratiques.
2
[Link]
2 Réplication logique
DALIBO Formations
Cette formation peut également contenir quelques images dont la redistribution est soumise à des
licences différentes qui sont alors précisées.
Marques déposées
PostgreSQL® Postgres® et le logo Slonik sont des marques déposées3 par PostgreSQL Community As‑
sociation of Canada.
3
[Link]
Réplication logique 3
1/ Réplication logique
5
DALIBO Formations
1.1 OBJECTIFS
La réplication logique a été ajoutée dans PostgreSQL depuis la version 10, et est améliorée régulière‑
ment à chaque version.
Nous verrons ici les principes derrière ce type de réplication, sa mise en place, son administration et
sa supervision.
Historiquement sont apparus des outils de réplication logique externes à PostgreSQL, qui peuvent
encore rendre des services.
1.1.1 Au menu
® – Principes
– Mise en place
– Exemple
– Administration
– Supervision
– Migration majeure avec la réplication logique
– Limitations
– Autres outils de réplication logique
6 Réplication logique
DALIBO Formations
® – Réplication logique
La réplication physique, qui existe dans PostgreSQL depuis la version 9.0, fonctionne par application
de bloc d’octets ou de delta de bloc. Elle a beaucoup évolué mais possède quelques limitations diffi‑
cilement contournables directement.
La réplication logique apporte des réponses à ces limitations. Seules des solutions tierces apportaient
ce type de réplication à PostgreSQL.
Physique Logique
La réplication physique est une réplication au niveau bloc. Le serveur primaire envoie au secondaire
les octets à ajouter/remplacer dans des fichiers. Le serveur secondaire n’a aucune information sur les
Réplication logique 7
DALIBO Formations
objets logiques (tables, index, vues matérialisées, bases de données). Il n’y a donc pas de granularité
possible, c’est forcément l’instance complète qui est répliquée. Cette réplication est par défaut en
asynchrone mais il est possible de la configurer en synchrone suivant différents modes.
Il est impossible de ne répliquer que certaines bases ou que certaines tables (pour ne pas répliquer
des tables de travail par exemple). Il est aussi impossible de créer des index spécifiques ou même des
tables de travail, y compris temporaires, sur les serveurs secondaires, vu qu’ils sont strictement en
lecture seule.
Un serveur secondaire ne peut se connecter qu’à un serveur primaire de même version majeure. On ne
peut donc pas se servir de la réplication physique pour mettre à jour la version majeure du serveur.
Enfin, il n’est pas possible de faire de la réplication entre des serveurs d’architectures matérielles ou
logicielles différentes (32/64 bits, little/big endian, version de bibliothèque C, etc.).
Réplication logique :
La réplication logique est une réplication du contenu des tables. Plus précisément, elle réplique les ré‑
sultats des ordres SQL exécutés sur la table publiée et l’applique sur la table cible. Les lignes insérées,
modifiées et/supprimées sur le serveur d’origine sont répliquées sur la destination. La table cible peut
être modifiée (index notamment), et son contenu différer de la table source.
Elle se paramètre donc table par table, et même opération par opération.
Elle est asymétrique dans le sens où il existe une seule origine des écritures pour une table. Si elle ne
permet pas un vrai fonctionnement multi‑maîtres, il est possible de réaliser des réplications croisées
où un ensemble de tables est répliqué du serveur 1 vers le serveur 2 et un autre ensemble de tables
est répliqué du serveur 2 vers le serveur 1.
La réplication logique permet de répliquer entre deux serveurs PostgreSQL de versions différentes, et
ainsi de procéder à des migrations majeures.
8 Réplication logique
DALIBO Formations
– publication
– souscription (abonnement)
Dans le cadre de la réplication logique, on ne réplique pas une instance vers une autre. On publie
les modifications effectuées sur le contenu d’une table à partir d’un serveur. Ce serveur est le ser‑
veur origine, ou publieur (publisher). De lui sont enregistrées les modifications que d’autres serveurs
pourront récupérer en s’abonnant (subscription) . Ces serveurs abonnés indiquent leur intérêt sur ces
modifications en s’abonnant à la publication.
– le serveur origine est le serveur où les écritures sur une table sont enregistrées pour publication
vers d’autres serveurs ;
– les serveurs intéressés par ces enregistrements sont les serveurs destinations ;
– un serveur origine doit proposer une publication des modifications ;
– les serveurs destinations intéressés doivent s’abonner à une publication.
Dans un cluster de réplication, un serveur peut avoir un rôle de serveur origine ou de serveur destina‑
tion. Il peut aussi avoir les deux rôles. Dans ce cas, il sera origine pour certaines tables et destinations
pour d’autres. Il ne peut pas être à la fois origine et destination pour la même table.
NB : dans le texte qui suit, peuvent être utilisés indifféremment les termes publieur/éditeur/origine
d’une part, et abonné/souscripteur/destination et abonnement/souscription d’autre part.
Réplication logique 9
DALIBO Formations
® – Paramètre wal_level
– Processus wal sender
– Asynchrone / synchrone
– Slots de réplication
La réplication logique utilise le même canal d’informations que la réplication physique : les en‑
registrements des journaux de transactions. Pour que les journaux disposent de suffisamment
d’informations, le paramètre wal_level doit être configuré avec la valeur logical.
Une fois cette configuration effectuée et PostgreSQL redémarré sur le serveur origine, le serveur desti‑
nation pourra se connecter au serveur origine dans le cadre de la réplication. Lorsque cette connexion
est faite, un processus wal sender apparaîtra sur le serveur origine. Ce processus sera en commu‑
nication avec un processus logical replication worker sur le serveur destination.
Chaque abonné maintient un slot de réplication sur l’instance de l’éditeur. Par défaut, il est créé et
supprimé automatiquement avec la souscription. La copie initiale des données crée également des
slots de réplication temporaires.
10 Réplication logique
DALIBO Formations
1.2.4 Granularité
® – Par table
– table complète
– uniquement certaines lignes (v15+)
– uniquement certaines colonnes (v15+)
– Par opération
Réplication logique 11
DALIBO Formations
ne publier que les opérations d’insertion, de modification ou de suppression. Par défaut, tout est pu‑
blié. La réplication de la commande TRUNCATE n’a été ajoutée qu’à partir de la version 11.
® – Possibilités
– index supplémentaires
– modification des valeurs
– colonnes supplémentaires
– triggers également activables sur la table répliquée
La réplication logique permet plusieurs choses impensables en réplication physique. Les cas
d’utilisation sont en fait très différents.
On peut rajouter ou supprimer des index sur la table répliquée, pourvu que les lignes restent identi‑
fiables. Au besoin on peut préciser l’index, qui doit être unique sur colonne NOT NULL servant de
clé :
Il est possible de modifier des valeurs dans la table répliquée. Ces modifications sont susceptibles
d’être écrasées par des modifications de la table source sur les mêmes lignes. Il est aussi possible de
perdre la synchronisation entre les tables, notamment si on modifie la clé primaire.
Les triggers ne se déclenchent par défaut que sur la base d’origine. On peut activer ainsi un trigger sur
la table répliquée :
Tout cela est parfois très pratique mais peut poser de sérieux problème de cohérence de données
entre les deux instances si l’on ne fait pas attention. On vérifiera régulièrement les erreurs dans les
traces.
12 Réplication logique
DALIBO Formations
Il est dangereux d’ajouter sur la destination des contraintes qui n’existent pas sur les
Á tables d’origine ! Elles ne sont pas forcément contrôlées à l’arrivée (clés étrangères, véri‑
fication par triggers…) Et si elles le sont, elles risquent de bloquer la réplication logique.
De même, sur la destination, ajouter ou modifier des lignes soumises à des contraintes
d’unicité peut empêcher l’insertion de lignes provenant de la source.
En cas de blocage, à cause d’une colonne absente, d’un doublon, d’une autre contrainte
Á sur la cible ou pour une autre raison, il faut corriger sur la destination, puis laisser le
stock de données bloquées s’insérer avant de pouvoir faire autre chose. L’alternative
est de désactiver ou reconstruire la réplication, ce qui peut poser des problèmes de ré‑
conciliation de données.
Il existe quelques cas surprenants. Par exemple, une colonne remplie grâce à une valeur DEFAULT sur
l’origine sera répliquée à l’identique sur la destination ; mais une colonne calculée (clause GENERA-
TED avec expression) sera calculée sur l’origine et sur la destination, éventuellement différemment.
Pour que la réplication logique fonctionne sans souci, il faut viser au plus simple, avec
b un modèle de données sur la destination aussi proche que possible de la source, soi‑
gneusement maintenu à jour à l’identique. Éviter de modifier les données répliquées.
Au plus, se contenter d’ajouter sur la destination des index non uniques ou des colonnes
calculées.
Prévoir dès le début le cas où cette réplication devra être arrêtée et reprise de zéro.
Réplication logique 13
DALIBO Formations
– à refaire manuellement
– être rigoureux et surveiller les traces !
La réplication logique n’a pas que des atouts, elle a aussi ses propres limitations.
La première, et plus importante, est qu’elle ne réplique que les changements de données des tables
(commandes DML), et pas de la définition des objets de la base de données (commandes DDL). L’ajout
(ou la suppression) d’une colonne ne sera pas répliqué, causant de ce fait un problème de réplication
quand l’utilisateur y ajoutera des données. La mise à jour sera bloquée jusqu’à ce que les tables abon‑
nées soient aussi mises à jour.
D’autres opérations moins évidentes peuvent aussi poser problème, comme une contrainte ou un
index supprimé sur l’origine mais pas la cible ; ou un index fonctionnel dont la fonction n’est corrigée
que sur la source. Il faut être rigoureux et surveiller les erreurs dans les traces.
Une table nouvellement créée ne sera pas non plus automatiquement répliquée.
Le TRUNCATE n’est pas répliqué en version 10, mais il l’est bien à partir de la version 11.
Il n’y a pas non plus de réplication des valeurs des séquences. Les valeurs des séquences sur les ser‑
veurs destinations seront donc obsolètes.
Les Large Objects étant stockés dans une table système, ils ne sont pas pris en compte par la réplica‑
tion logique.
Les opérations UPDATE et DELETE nécessitent la présence d’une contrainte unique pour s’assurer de
modifier ou supprimer les bonnes lignes. Une clé primaire est conseillée de toute manière pour bien
identifier les lignes.
14 Réplication logique
DALIBO Formations
La réplication logique a un coût en CPU (sur les deux instances concernées) relativement important :
attention aux petites configurations. Il y a également un coût en disque (voir plus bas).
La situation peut devenir compliquée lors d’une restauration ou bascule d’un des serveurs impliqués
(voir plus bas).
Réplication logique 15
DALIBO Formations
® – Cas simple
– 2 serveurs
– une seule origine
– un seul destinataire
– une seule publication
– Plusieurs étapes
Dans cette partie, nous allons aborder un cas simple avec uniquement deux serveurs. Le premier
sera l’origine, le second sera le destinataire des informations de réplication. Toujours pour simplifier
l’explication, il n’y aura pour l’instant qu’une seule publication.
16 Réplication logique
DALIBO Formations
– wal_level = logical
– logical_decoding_work_mem = 64MB (v13+)
Dans le cadre de la réplication avec PostgreSQL, c’est toujours le serveur destination qui se connecte
au serveur origine. Pour la réplication physique, on utilise plutôt les termes de serveur primaire et de
serveur secondaire mais c’est toujours du secondaire vers le primaire, de l’abonné vers l’éditeur.
Tout comme pour la réplication physique, il est nécessaire de disposer d’un utilisateur PostgreSQL
capable de se connecter au serveur origine et capable d’initier une connexion de réplication. Voici
donc la requête pour créer ce rôle :
Cet utilisateur doit pouvoir lire le contenu des tables répliquées. Il lui faut donc le droit SELECT sur
ces objets :
Les journaux de transactions doivent disposer de suffisamment d’informations pour que le wal
sender puisse envoyer les bonnes informations au logical replication worker. Pour cela,
il faut configurer le paramètre wal_level à logical dans le fichier [Link].
La réplication logique, contrairement à la réplication physique, n’est déclenchée que lors d’un COM-
MIT (voir cet article1 ). Par défaut, il n’y a pas d’envoi des données tant que la transaction est en cours,
ce qui peut ajouter beaucoup de délai de réplication pour les transactions longues.
Réplication logique 17
DALIBO Formations
disque. Avant PostgreSQL version 13 et l’apparition de ce paramètre, les modifications d’une tran‑
saction étaient stockées en mémoire jusqu’à ce que la transaction soit validée par un COMMIT. En
conséquence, si cette transaction possédait de nombreuses sous‑transactions, chaque walsender
pouvait allouer énormément de mémoire, menant parfois à un dépassement de mémoire. Avec
ce paramètre, il est possible de diminuer sa valeur pour réduire l’utilisation de la mémoire des
walsender ou définir une valeur plus élevée pour réduire les écritures sur le disque. La valeur par
défaut est de 64 Mo.
Enfin, la connexion du serveur destination doit être possible sur le serveur origine. Il est donc néces‑
saire d’avoir une ligne du style :
– Souscription
Sur le serveur destination, il n’y a pas de configuration à réaliser dans les fichiers [Link]
et pg_hba.conf.
Ensuite, il faut récupérer la définition des objets répliqués pour les créer sur le serveur de destination.
Un moyen simple est d’utiliser pg_dump et d’envoyer le résultat directement à psql pour restaurer
immédiatement les objets. Cela se fait ainsi :
18 Réplication logique
DALIBO Formations
Il est aussi possible de sauvegarder la définition d’une seule table en ajoutant l’option -t suivi du nom
de la table pour avoir son script.
Il est conseillé de déclarer l’objet sur la destination avec la même définition que sur l’origine, mais
ce n’est pas obligatoire tant que les mises à jour arrivent à sa faire. Les index, notamment, peuvent
différer, des types être plus laxistes, des colonnes supplémentaires ajoutées.
Avant la version 14, le walsender attendait toujours le COMMIT avant d’envoyer une transaction
aux abonnés, et de grosses transactions pouvaient entraîner l’apparition d’énormes fichiers dans le
répertoire pg_replslot du serveur d’origine. Depuis la version 14, cela reste le comportement par
défaut, mais il est possible de forcer l’envoi des données au serveur destinataire sans attendre le COM-
MIT. Le serveur distant stockera les données dans un fichier et ne les rejouera qu’à partir du moment
où le COMMIT est reçu.
– parametre_publication = publish
– parametre_publication = publish_via_partition_root
Une fois que les tables sont définies des deux côtés (origine et destination), il faut créer une publi‑
cation sur le serveur origine. Cette publication indiquera à PostgreSQL les tables répliquées et les
Réplication logique 19
DALIBO Formations
opérations concernées.
La clause FOR ALL TABLES permet de répliquer toutes les tables de la base, sans avoir à les nommer
spécifiquement. De plus, toute nouvelle table sera répliquée automatiquement dès sa création.
À partir de la version 15, la clause FOR TABLES IN SCHEMA permet de répliquer toutes les tables
du schéma indiqué sans avoir à nommer les tables spécifiquement. De plus, toute nouvelle table de
ce schéma sera répliquée automatiquement dès sa création.
Si on ne souhaite répliquer qu’un sous‑ensemble, il faut spécifier toutes les tables à répliquer en uti‑
lisant la clause FOR TABLE et en séparant les noms des tables par des virgules.
Depuis la version 15, il est possible de ne répliquer que certaines colonnes d’une table. Dans ce cas, il
faut indiquer les colonnes en question. En voici un exemple :
Toujours depuis cette version, il est possible de ne répliquer que les lignes validant une certaine ex‑
pression. Par exemple :
Par défaut, une table est répliquée intégralement, donc toutes les colonnes et toutes les lignes.
Cette publication est concernée par défaut par toutes les opérations d’écriture (INSERT, UPDATE,
DELETE, TRUNCATE). Cependant, il est possible de préciser les opérations si on ne les souhaite pas
toutes. Pour cela, il faut utiliser le paramètre de publication publish en utilisant les valeurs insert,
update, delete et/ou truncate et en les séparant par des virgules si on en indique plusieurs.
Lorsque l’on publie les modifications sur une table partitionnée, PostgreSQL utilise par défaut le nom
de la partition finale. Il est possible de lui demander d’utiliser le nom de la table partitionnée grâce
à l’option publish_via_partition_root = true. Cela permet de répliquer d’une table par‑
titionnée vers une table normale ou une table partitionnée avec un agencement de partitions diffé‑
rent.
20 Réplication logique
DALIBO Formations
Une fois la publication créée, le serveur destination doit s’y abonner. Il doit pour cela indiquer sur quel
serveur se connecter et à quel publication souscrire.
Le serveur s’indique avec la chaîne infos_connexion, dont la syntaxe est la syntaxe habituelle des
chaînes de connexion. Pour rappel, on utilise les mots clés host, port, user, password, dbname,
etc.
Le champ nom_publication doit être remplacé par le nom de la publication créée précédemment
sur le serveur origine.
Réplication logique 21
DALIBO Formations
® – copy_data
– create_slot
– enabled
– slot_name
– synchronous_commit
– surcharge synchronous_commit
Les options de souscription sont assez nombreuses et permettent de créer une souscription pour des
cas particuliers. Par exemple, si le serveur destination possède déjà les données du serveur origine, il
faut placer le paramètre copy_data à la valeur off.
22 Réplication logique
DALIBO Formations
® – connect
Réplication logique 23
DALIBO Formations
Pour rendre la mise en place plus concrète, voici trois exemples de mise en place de la réplication
logique. On commence par une réplication complète d’une base, qui permettrait notamment de faire
une montée de version. On continue avec une réplication partielle, ne prenant en compte que 2 des 3
tables de la base. Et on finit par une réplication croisée sur la table partitionnée.
® – 4 serveurs
– Schéma
– 2 tables ordinaires
– 1 table partitionnée, avec trois partitions
24 Réplication logique
DALIBO Formations
Pour ce premier exemple, nous allons détailler les quatre étapes nécessaires.
– Fichier [Link]
wal_level = logical
Réplication logique 25
DALIBO Formations
La configuration du serveur d’origine commence par la création du rôle de réplication. On lui donne
ensuite les droits sur toutes les tables. Ici, la commande ne s’occupe que des tables du schéma pu-
blic, étant donné que nous n’avons que ce schéma. Dans le cas où la base dispose d’autres schémas,
il serait nécessaire d’ajouter les ordres SQL pour ces schémas.
Les fichiers [Link] et pg_hba.conf sont modifiés pour y ajouter la configuration né‑
cessaire.
® – Fichier pg_hba.conf
Comme dit précédemment, les fichiers [Link] et pg_hba.conf sont modifiés pour
y ajouter la configuration nécessaire. Le serveur PostgreSQL du serveur d’origine est alors redémarré
pour qu’il prenne en compte cette nouvelle configuration.
Il est important de répéter que la méthode d’authentification trust ne devrait jamais être utilisée
en production. Elle n’est utilisée ici que pour se faciliter la vie.
26 Réplication logique
DALIBO Formations
createdb -h s2 b1
pg_dump -h s1 -s b1 | psql -h s2 b1
Pour cet exemple, nous ne devrions configurer que le serveur s2 mais tant qu’à y être, autant le faire
pour les quatre serveurs destinations.
® – Création d’une publication de toutes les tables de la base b1 sur le serveur origine
s1
On utilise la clause ALL TABLES pour une réplication complète d’une base.
Réplication logique 27
DALIBO Formations
Maintenant que le serveur s1 est capable de publier les informations de réplication, le serveur inté‑
ressé doit s’y abonner. Lors de la création de la souscription, il doit préciser comment se connecter
au serveur origine et le nom de la publication.
Les données initiales de la table t1 sont envoyées du serveur s1 vers le serveur s2.
Toute opération d’écriture sur la table t1 du serveur s1 doit être répliquée sur le serveur s2.
Sur le serveur s1 :
28 Réplication logique
DALIBO Formations
id_t1 | label_t1
-------+---------------
101 | t1, ligne 101
10 | T1, LIGNE 10
(2 rows)
Sur le serveur s2 :
b1=# SELECT count(*) FROM t1;
count
-------
100
id_t1 | label_t1
-------+---------------
101 | t1, ligne 101
10 | T1, LIGNE 10
(2 rows)
La mise en place d’une réplication partielle est identique à la mise en place d’une réplication complète
à une exception près : la publication doit mentionner la liste des tables à répliquer. Chaque nom de
table est séparé par une virgule.
Mise en place :
Cela donne donc dans notre exemple :
Réplication logique 29
DALIBO Formations
Il ne reste plus qu’à souscrire à cette publication à partir du serveur s3 avec la requête indiquée.
Vérification :
Sur s3, nous n’avons que les données des deux tables répliquées :
count
-------
100
count
-------
1000
count
-------
0
id_t1 | label_t1
-------+---------------
101 | t1, ligne 101
10 | T1, LIGNE 10
Et vérifions qu’elles apparaissent bien sur s3 pour t1 et t2, mais pas pour t3 :
id_t1 | label_t1
-------+---------------
102 | t1, ligne 102
30 Réplication logique
DALIBO Formations
id_t2 | label_t2
-------+----------------
1001 | t2, ligne 1002
– et répliquer sur s4
– et répliquer sur s1
– Pour compliquer :
La réplication logique ne permet pas pour l’instant de faire du multi‑maîtres pour une même table.
Cependant, il est tout à fait possible de croiser les réplications, c’est‑à‑dire de répliquer un ensemble
de tables de serveur s1 (origine) vers s4 (destination), de répliquer un autre ensemble en sens inverse,
du serveur s4 vers s1.
Pour rendre cela encore plus intéressant, nous allons utiliser la table t3 et ses partitions. Le but est de
pouvoir écrire dans la partition t3_1 sur s1 et dans la partition t3_2 sur s2, simulant ainsi une table
où il sera possible d’écrire sur les deux serveurs à condition de respecter la clé de partitionnement.
Réplication logique 31
DALIBO Formations
– Y souscrire sur s4
– wal_level , pg_hba.conf
Rien de bien nouveau ici, il s’agit d’une réplication partielle. On commence par créer la publication
sur le serveur s1 et on souscrit à cette publication sur le serveur s4.
Cependant, le serveur s4 n’est plus seulement un serveur destination, il devient aussi un serveur ori‑
gine. Il est donc nécessaire de le configurer pour ce nouveau rôle. Cela passe par une configuration
similaire et symétrique à celle vue pour s1 :
– Fichier [Link] :
wal_level = logical
(Si ce n’était pas déjà fait, il faudra redémarrer l’instance PostgreSQL sur s4).
– Fichier pg_hba.conf :
32 Réplication logique
DALIBO Formations
– Y souscrire sur s1
Là‑aussi, rien de bien nouveau. On crée la publication sur le serveur s4 et on souscrit à cette publica‑
tion sur le serveur s1.
Sur s1 :
INSERT 0 1
Réplication logique 33
DALIBO Formations
Sur s4 :
INSERT 0 1
Sur s1 :
34 Réplication logique
DALIBO Formations
1.5 ADMINISTRATION
® – Processus
– Fichiers
– Procédures
Dans cette partie, nous allons tout d’abord voir les changements de la réplication logique du niveau
du système d’exploitation, et tout particulièrement au niveau des processus et des fichiers.
Ensuite, nous regarderons quelques procédures importantes d’administration et de maintenance.
1.5.1 Processus
® – Serveur origine
– wal sender
– Serveur destination
Tout comme il existe un processus wal sender communiquant avec un processus wal receiver
dans le cadre de la réplication physique, il y a aussi deux processus discutant ensemble dans le cadre
de la réplication logique.
Pour commencer, un serveur en version 10 dispose d’un processus supplémentaire, le logical re-
plication launcher. Ce processus a pour but de demander le lancement d’un logical re-
plication worker lors de la création d’une souscription. Ce worker se connecte au serveur ori‑
Réplication logique 35
DALIBO Formations
gine et applique toutes les modifications dont s1 lui fait part (on a aussi le terme de apply worker, no‑
tamment dans certains messages des traces). Si la connexion se passe bien, un processus wal sen-
der est ajouté sur le serveur origine pour communiquer avec le worker sur le serveur destination.
Sur notre serveur s2, destinataire pour la publication complète du serveur s1, nous avons les proces‑
sus suivant :
postmaster -D /opt/postgresql/datas/s2
postgres: checkpointer process
postgres: writer process
postgres: wal writer process
postgres: autovacuum launcher process
postgres: bgworker: logical replication launcher
postgres: bgworker: logical replication worker for subscription 16445
Le serveur s1 est origine de trois publications (d’où les 3 wal sender) et destinataire d’une sous‑
cription (d’où le seul logical replication worker). Il a donc les processus suivants :
postmaster -D /opt/postgresql/datas/s1
postgres: checkpointer process
postgres: writer process
postgres: wal writer process
postgres: autovacuum launcher process
postgres: bgworker: logical replication launcher
postgres: bgworker: logical replication worker for subscription 16573
postgres: wal sender process logrepli [local] idle
postgres: wal sender process logrepli [local] idle
postgres: wal sender process logrepli [local] idle
36 Réplication logique
DALIBO Formations
Streaming Logique
Réplication logique 37
DALIBO Formations
Streaming Logique
primary_conninfo
wal_level=replica
standby_mode
max_worker_processes max_worker_processes
max_logical_replication_workers
Streaming Logique
restore_command
primary_slot_name
hot_standby
promote_trigger_file
max_replication_slots
hot_standby_feedback
38 Réplication logique
DALIBO Formations
® – 2 répertoires importants
– pg_replslot
– slots de réplication
– 1 répertoire par slot (+ slots temporaires)
– 1 fichier state dans le répertoire
– fichiers .snap (volumétrie !)
– pg_logical
– métadonnées
– snapshots
La réplication logique maintient des données dans deux répertoires : pg_replslot et pg_logical.
pg_replslot contient un répertoire par slot de réplication physique ou logique. On y trouvera aussi
des slots temporaires lors de l’initialisation de la réplication logique.
pg_replslot contient aussi les snapshots des transactions en cours (fichiers .snap). Il peut donc
atteindre une taille importante si le serveur exécute beaucoup de transactions longues avec du vo‑
lume en écriture, ou si l’abonné met du temps à répliquer les données. Il est donc important de sur‑
veiller la place prise par ce répertoire.
À cela s’ajoutent les journaux de transaction conservés en fonction de l’avancement des slots de répli‑
cation.
Réplication logique 39
DALIBO Formations
® – Par défaut, toutes les écritures sont autorisées sur le serveur destination
– y compris écrire dans une table répliquée avec un autre serveur comme ori‑
gine
– Problèmes
– Solution
Sur s2, nous allons créer un utilisateur applicatif en lui donnant tous les droits sur les tables répliquées,
entre autres :
Maintenant, nous nous connectons avec cet utilisateur et vérifions s’il peut écrire dans la table répli‑
quée :
b1=# \c b1 u1
You are now connected to database "b1" as user "u1".
b1=> INSERT INTO t1 VALUES (103, 't1 sur s2, ligne 103');
INSERT 0 1
C’est bien le cas, contrairement à ce que l’on aurait pu croire instinctivement. Le seul moyen
d’empêcher ce comportement par défaut est de lui supprimer les droits d’écriture :
b1=> \c b1 postgres
You are now connected to database "b1" as user "postgres".
b1=# REVOKE INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public FROM u1;
REVOKE
b1=# \c b1 u1
You are now connected to database "b1" as user "u1".
40 Réplication logique
DALIBO Formations
Sans cette interdiction, on peut arriver à des problèmes très gênants. Par exemple, nous avons inséré
dans la table t1 de s2 la valeur 103 :
b1=# SELECT * FROM t1 WHERE id_t1=103;
id_t1 | label_t1
-------+----------------------
103 | t1 sur s2, ligne 103
id_t1 | label_t1
-------+----------
(0 rows)
INSERT 0 1
– sur s1 :
b1=# SELECT * FROM t1 WHERE id_t1=103;
id_t1 | label_t1
-------+----------------------
103 | t1 sur s1, ligne 103
(1 row)
– sur s2 :
b1=# SELECT * FROM t1 WHERE id_t1=103;
id_t1 | label_t1
-------+----------------------
103 | t1 sur s2, ligne 103
(1 row)
Notez que le contenu de la colonne label_t1 n’est pas identique sur les deux serveurs.
Ce n’est pas le seul problème : cette valeur insérée sur s1 va devoir être répliquée. Le processus de répli‑
cation logique n’arrive alors plus à appliquer les données sur s2, avec ces messages dans les traces :
Réplication logique 41
DALIBO Formations
LOG: logical replication apply worker for subscription "subscr_complete" has started
ERROR: duplicate key value violates unique constraint "t1_pkey"
DETAIL: Key (id_t1)=(103) already exists.
LOG: worker process: logical replication worker for subscription 16445 (PID 31113)
↪ exited with exit code 1
Il faut corriger manuellement la situation, par exemple en supprimant la ligne de t1 sur le serveur
s2 :
DELETE 1
id_t1 | label_t1
-------+----------
(0 rows)
Au bout d’un certain temps, le worker est relancé, et la nouvelle ligne est finalement disponible :
id_t1 | label_t1
-------+----------------------
103 | t1 sur s1, ligne 103
(1 row)
Dans des cas plus complexes et avec plus de données, la réconciliation des données peut devenir très
complexe et chronophage.
42 Réplication logique
DALIBO Formations
Seules les opérations DML sont répliquées pour les tables ciblées par une publication. Toutes les opé‑
rations DDL sont ignorées, que ce soit l’ajout, la modification ou la suppression d’un objet, y compris
si cet objet fait partie d’une publication.
Il est donc important que toute modification de schéma soit effectuée sur toutes les instances d’un
cluster de réplication. Ce n’est cependant pas requis. Il est tout à fait possible d’ajouter un index sur
un serveur sans vouloir l’ajouter sur d’autres. C’est d’ailleurs une des raisons de passer à la réplication
logique.
Par contre, dans le cas du changement de définition d’une table répliquée (ajout ou suppression d’une
colonne, par exemple), il est nettement préférable de réaliser cette opération sur tous les serveurs
intégrés dans cette réplication.
La création d’une table est une opération DDL. Elle est donc ignorée dans le contexte de la réplication
logique.
Si l’on veut la répliquer, il faudra créer la table manuellement dans la base destinataire. Puis, deux
cas se présentent : la publication a été déclarée pour certaines tables uniquement, ou avec FOR ALL
TABLES.
Si elle ne concerne qu’un sous‑ensemble de tables, il faut ajouter la nouvelle table à la publication :
Si la publication a été créée avec la clause FOR ALL TABLES, la nouvelle table est immédiatement
prise en compte dans la publication.
Dans les deux cas, sur les serveurs destinataires, il va falloir rafraîchir les souscriptions :
Réplication logique 43
DALIBO Formations
Si l’on a oublié de créer la table sur le destinataire, cela provoquera une erreur :
Si la publication contient des tables partitionnées, la même commande doit être exécutée lorsque
l’on ajoute ou retire des partitions à une de ces tables partitionnées.
Sur le serveur s1, on crée la table t4, on lui donne les bons droits, et on insère des données :
La table n’existe pas. En effet, la réplication logique ne s’occupe que des modifications de contenu
des tables, pas des changements de définition. Il est donc nécessaire de créer la table sur le serveur
destination, ici s2 :
Elle ne contient toujours rien. Ceci est dû au fait que la souscription n’a pas connaissance de la répli‑
cation de cette nouvelle table. Il faut donc rafraîchir les informations de souscription :
44 Réplication logique
DALIBO Formations
Dans la réplication physique, les opérations de maintenance ne sont réalisables que sur le serveur
primaire, qui va envoyer le résultat de ces opérations aux serveurs secondaires.
Ce n’est pas le cas dans la réplication logique. Il faut bien voir les serveurs d’une réplication logique
comme étant des serveurs indépendants les uns des autres.
Donc il faut configurer leur maintenance, avec les opérations VACUUM, ANALYZE, REINDEX, comme
pour n’importe quel serveur PostgreSQL.
® – pg_dumpall et pg_dump
Les sauvegardes logiques incluent les publications et souscriptions. Deux options (--no-
publications et --no-subscriptions) permettent de les exclure.
Réplication logique 45
DALIBO Formations
Par contre, les slots de réplication liées aux publications, et leur position dans le flux de transaction,
ne sont pas sauvegardés. Cela peut poser problème pour une restauration sans perte.
Après une restauration, il faudra soigneusement vérifier dans les traces que les réplications logiques
ont repris leur fonctionnement, et qu’il n’y a pas de perte dans les données transmises.
La publication sera fonctionnelle, mais il peut être délicat d’y raccrocher les abonne‑
Á ments existants. Selon ce qui s’est passé, le slot de réplication a souvent disparu, et il
peut être plus simple de recréer ces abonnements.
Ces opérations sont obligatoirement manuelles. De toute façon, il faudra se poser la question de la
resynchronisation des données. Généralement, l’origine aura été restaurée dans un état antérieur à
celui déjà répliqué : les données répliquées à présent absentes de l’origine sont‑elles toutes à conser‑
ver ? Comment gérer les clés primaires qui vont souvent entrer en conflit ?
Contrairement à l’ordre exécuté manuellement à la création, celui‑ci précise le nom du slot de répli‑
cation (au cas où il aurait été personnalisé) et désactive la connexion immédiate. Cette désactivation
a pour effet de désactiver la souscription, de ne pas créer le slot de réplication et d’empêcher la copie
46 Réplication logique
DALIBO Formations
initiale des données (dont nous n’avons pas besoin étant donné que nous les avons dans la sauve‑
garde, au moins en partie).
Une fois la sauvegarde restaurée et les vérifications nécessaires effectuées, il est possible d’activer la
souscription et de la rafraîchir :
auquel cas on risque d’avoir un « trou » entre les données restaurées et celles qui vont
apparaître sur le publieur ; qu’il faudra corriger à la main dans les nombreux cas où cela
est important.
Réplication logique 47
DALIBO Formations
– publications et souscriptions
– slots ?
– bascule origine
– restauration origine
– restauration destination
– Contrôle délicat !
– Bascule de la destination
Pendant ces opérations, il est fortement conseillé d’interdire les écritures dans les tables répliquées
pour avoir une vision claire de ce qui a été répliqué et ne l’a pas été. Les slots doivent souvent être
reconstruits, et il faut éviter que les tables soient modifiées entre‑temps.
Il faudra recréer les slots, peut‑être recréer les souscriptions, et pendant ce temps des trous dans les
données répliquées peuvent apparaître, qu’il faudra vérifier ou corriger manuellement.
Ici, l’instance d’origine est arrêtée et un de ses secondaires est promu comme nouveau serveur princi‑
pal. Les slots de réplication étant propres à une instance, il ne seront pas disponibles immédiatement
sur la nouvelle origine. Il faudra aussi reparamétrer la connexion des abonnements.
48 Réplication logique
DALIBO Formations
Un slot de réplication sur l’origine garantit seulement que les journaux seront toujours disponibles
pendant une indisponibilité du souscripteur. Ils ne permettent pas de revenir sur des données déjà
répliquées.
C’est le cas le plus favorable. Si la bascule s’est faite proprement sans perte entre l’ancienne destina‑
tion et la nouvelle, il ne devrait pas y avoir de perte de données répliquées. Cela devra tout de même
faire partie des contrôles
Réplication logique 49
DALIBO Formations
1.6 SUPERVISION
® – Méta‑données
– Statistiques
– Outils
® – pg_publication
– pg_publication_tables
– pg_subscription
Le catalogue système pg_publication contient la liste des publications, avec leur méta‑
données :
Le catalogue système pg_publication_tables contient une ligne par table par publication :
50 Réplication logique
DALIBO Formations
pubname | tables_list
-----------------+------------------------------
publi_complete | {t1,t2,t3_1,t3_2,t3_3,t4,t5}
publi_partielle | {t1,t2}
publi_t3_1 | {t3_1}
tablename | publicationss_list
-----------+----------------------------------
t1 | {publi_complete,publi_partielle}
t2 | {publi_complete,publi_partielle}
t3_1 | {publi_complete,publi_t3_1}
t3_2 | {publi_complete}
t3_3 | {publi_complete}
t4 | {publi_complete}
t5 | {publi_complete}
b1=# \x
Expanded display is on.
b1=# SELECT * FROM pg_subscription;
Réplication logique 51
DALIBO Formations
-[ RECORD 1 ]---+----------------------------------
subdbid | 16443
subname | subscr_t3_2
subowner | 10
subenabled | t
subconninfo | port=5444 user=logrepli dbname=b1
subslotname | subscr_t3_2
subsynccommit | off
subpublications | {publi_t3_2}
® – pg_stat_replication
– statut de réplication
– pg_stat_replication_slots (v14)
– pg_stat_subscription
– pg_replication_origin_status
Comme pour la réplication physique, le retard de réplication est calculable en utilisant les informa‑
tions de la vue pg_stat_replication sur le serveur origine :
-[ RECORD 1 ]----+------------------------------
pid | 18200
usesysid | 16442
usename | logrepli
application_name | subscr_t3_1
client_addr |
client_hostname |
client_port | -1
backend_start | 2017-12-20 [Link].13489+01
52 Réplication logique
DALIBO Formations
backend_xmin |
state | streaming
sent_lsn | 0/182D3C8
write_lsn | 0/182D3C8
flush_lsn | 0/182D3C8
replay_lsn | 0/182D3C8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 2 ]----+------------------------------
pid | 26606
usesysid | 16442
usename | logrepli
application_name | subscr_partielle
client_addr |
client_hostname |
client_port | -1
backend_start | 2017-12-20 [Link].196654+01
backend_xmin |
state | streaming
sent_lsn | 0/182D3C8
write_lsn | 0/182D3C8
flush_lsn | 0/182D3C8
replay_lsn | 0/182D3C8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
-[ RECORD 3 ]----+------------------------------
pid | 15127
usesysid | 16442
usename | logrepli
application_name | subscr_complete
client_addr |
client_hostname |
client_port | -1
backend_start | 2017-12-20 [Link].267249+01
backend_xmin |
state | streaming
sent_lsn | 0/182D3C8
write_lsn | 0/182D3C8
flush_lsn | 0/182D3C8
replay_lsn | 0/182D3C8
Réplication logique 53
DALIBO Formations
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
Depuis la version 14, une autre vue, pg_stat_replication_slots (description complète dans
la documentation2 , permet de suivre les volumétries (octets, nombre de transactions) écrites sur
disque (spilled) ou envoyées en streaming :
-[ RECORD 1 ]+-----------
slot_name | abonnement
spill_txns | 3
spill_count | 7
spill_bytes | 412435584
stream_txns | 0
stream_count | 0
stream_bytes | 0
total_txns | 30467
total_bytes | 161694536
stats_reset |
L’état des souscriptions est disponible sur les serveurs destination à partir de la vue pg_stat_subscription :
-[ RECORD 1 ]---------+------------------------------
subid | 16573
subname | subscr_t3_2
pid | 18893
relid |
received_lsn | 0/168A748
last_msg_send_time | 2017-12-20 [Link].315798+01
last_msg_receipt_time | 2017-12-20 [Link].315849+01
latest_end_lsn | 0/168A748
latest_end_time | 2017-12-20 [Link].315798+01
2
[Link]
54 Réplication logique
DALIBO Formations
® – check_pgactivity
– replication_slots
– check_postgres
– same_schema
Peu d’outils ont déjà été mis à jour pour ce type de réplication.
Néanmoins, il est possible de surveiller le retard de réplication via l’état des slots de réplication,
comme le propose l’outil check_pgactivity (disponible sur github3 ). Ici, il n’y a pas de retard sur
la réplication, pour les trois slots :
Service : POSTGRES_REPLICATION_SLOTS
Returns : 0 (OK)
Message : Replication slots OK
Perfdata : subscr_complete_wal=0File
Perfdata : subscr_complete_spilled=0File
Perfdata : subscr_t3_1_wal=0File
Perfdata : subscr_t3_1_spilled=0File
Perfdata : subscr_partielle_wal=0File
Perfdata : subscr_partielle_spilled=0File
Faisons quelques insertions après l’arrêt de s3 (qui correspond à la souscription pour la réplication
partielle) :
INSERT 0 1000001
L’outil détecte bien que le slot subscr_partielle a un retard conséquent (8 journaux de transac‑
tions) et affiche le nombre de fichiers de débordement créés :
Service : POSTGRES_REPLICATION_SLOTS
3
[Link]
Réplication logique 55
DALIBO Formations
Returns : 0 (OK)
Message : Replication slots OK
Perfdata : subscr_t3_1_wal=8File
Perfdata : subscr_t3_1_spilled=0File
Perfdata : subscr_partielle_wal=8File
Perfdata : subscr_partielle_spilled=9File
Perfdata : subscr_complete_wal=8File
Perfdata : subscr_complete_spilled=9File
Il est aussi possible d’utiliser l’action same_schema avec l’outil check_postgres (disponible
aussi sur github4 ) pour détecter des différences de schémas entre deux serveurs (l’origine et une
destination).
4
[Link]
56 Réplication logique
DALIBO Formations
La réplication logique rend possible une migration entre deux instances de version majeure différente
avec une indisponibilité très courte. La base à migrer doit bien sûr être en version 10 ou supérieure.
C’était déjà possible avec des outils de réplication par trigger comme Slony ou Bucardo. Ces outils
externes ne sont maintenant plus nécessaires. (Noter que Slony en particulier reste parfaitement uti‑
lisable et recommandable, et sert encore pour nombre de migrations).
Le principe est de répliquer une base à l’identique alors que la production tourne. Lors de la bascule, il
suffit d’attendre que les dernières données soient répliquées, ce qui peut être très rapide, et de connec‑
ter les applications au nouveau serveur. La réplication peut alors être inversée pour garder l’ancienne
production synchrone, permettant de rebasculer dessus en cas de problème sans perdre les données
modifiées depuis la bascule.
Les étapes sont :
– les modifications de schéma effectuées pendant la synchronisation ne sont pas répliquées (cela
est problématique si l’application elle‑même effectue du DDL sur des tables non temporaires) ;
Réplication logique 57
DALIBO Formations
Cette méthode reste donc plus complexe et fastidieuse qu’une migration par pg_dump/pg_restore
ou pg_upgrade.
58 Réplication logique
DALIBO Formations
– ni TRUNCATE en v10
La réplication logique native ne réplique pas les ordres DDL. Elle se base uniquement au niveau des
données (donc les ordres DML). Une exception a été faite à partir de la version 11 pour répliquer les
ordres TRUNCATE car, même s’il s’agit d’un ordre DDL d’après le standard, cet ordre modifie les don‑
nées d’une table.
Avant la version 13, il n’était pas possible d’ajouter une table partitionnée à une publication pour
qu’elle et ses partitions soient répliquées. Il fallait ajouter chaque partition individuellement. Cette
limitation a été supprimée en version 13.
Toujours avant la version 13, il n’était pas possible d’envoyer des données dans une table partition‑
née.
Les valeurs des séquences et les Larges Objects ne sont pas répliqués.
Pour les versions inférieures à 14, la réplication logique n’est déclenchée que lors d’un COMMIT. Il
n’y a pas d’envoi des données tant que la transaction est en cours, ce qui peut rajouter un délai de
réplication pour les transactions longues.
Réplication logique 59
DALIBO Formations
Enfin, la réplication logique doit tenir compte des cas de restauration, ou bascule, d’une
Á des instances impliquées. Le concept de flux unique de transaction unique ne s’applique
plus ici, et il n’est pas prévu de moyen pour garantir que la réplication se fera sans au‑
cune perte ou risque de doublon. La mise en place de la réplication logique doit toujours
prévoir ce qu’il faudra faire dans ce cas.
Certaines applications supporteront cette limite. Dans d’autres, il sera plus ou moins facile de re‑
prendre la réplication à zéro. Parfois, une réconciliation manuelle sera nécessaire (la présence de clés
primaires peut grandement aider). Dans certains cas, ce problème peut devenir bloquant ou réclamer
des développements.
60 Réplication logique
DALIBO Formations
® – Slony
– Bucardo
Slony5 est un très ancien projet libre de réplication pour PostgreSQL. C’était l’outil de choix avant
l’arrivée de la réplication native dans PostgreSQL.
– switchover / switchback
– failover / failback
Slony permet de choisir les tables à répliquer. Il faudra ajouter à la réplication toute nouvelle table qui
serait créée après sa mise en place.
5
[Link]
Réplication logique 61
DALIBO Formations
Les procédures de bascule chez Slony sont très simples. Il est ainsi possible de basculer un serveur
primaire et son serveur secondaire autant de fois qu’on le souhaite, très rapidement, sans avoir à
reconstruire quoi que ce soit.
Les démons et les triggers sont écrits en C, ce qui permet à Slony d’être très performant.
Au niveau du vocabulaire utilisé, le primaire est souvent appelé un « provider » (il fournit les données
aux serveurs secondaires) et les secondaires sont souvent des « subscribers » (ils s’abonnent au flux
de réplication pour récupérer les données modifiées).
Slony dispose de nombreux points forts, parfois liés au simple fait qu’il s’agit d’une réplication lo‑
gique.
62 Réplication logique
DALIBO Formations
Il permet de ne répliquer qu’un sous‑ensemble des objets d’une instance : pas forcément toutes les
bases, pas forcément toutes les tables d’une base particulière, etc.
Le serveur primaire et les serveurs secondaires n’ont pas besoin d’utiliser la même version majeure
de PostgreSQL. Il est donc possible de mettre à jour en plusieurs étapes (plutôt que tous les serveurs
à la fois). Cela facilite aussi le passage à une version majeure ultérieure.
Même si la réplication des DDL est impossible, leur envoi aux différents serveurs est possible grâce à
un outil fourni. Tous les systèmes de réplication par triggers ne peuvent pas en dire autant.
Slony peut survivre avec un réseau coupé. Cependant, il n’aime pas quand le réseau passe son temps à
être disponible puis indisponible. Les démons slon ont tendance à croire qu’ils sont toujours connec‑
tés alors que ce n’est plus le cas.
Superviser Slony n’est possible que via une table statistique appelée sl_status. Elle fournit princi‑
palement deux informations : le retard en nombre d’événements de synchronisation et la date de la
dernière synchronisation.
Enfin, la modification de la structure d’une base, même si elle est simplifiée avec le script fourni, n’est
pas simple, en tout cas beaucoup moins simple que d’exécuter une requête DDL seule.
® – Réplications complexes
– Infocentre (many to one)
– Bases spécialisées (recherche plein texte, traitements lourds, etc.)
– Migrations de versions majeures avec indisponibilité réduite
Réplication logique 63
DALIBO Formations
Bien que la réplication logique soit arrivée avec PostgreSQL 10, Slony garde son utilité pour les nom‑
breuses instances des versions précédentes.
Slony peut se révéler intéressant car il est possible d’avoir des tables de travail en écriture sur le secon‑
daire avec Slony. Il est aussi possible d’ajouter des index sur le secondaire qui ne seront pas présents
sur le serveur primaire (on évite donc la charge de maintenance des index par le serveur primaire, tout
en permettant de bonnes performances pour la création des rapports).
Il est fréquent d’utiliser Slony pour des migrations entre deux versions majeures avec une indispo‑
nibilité réduite, voire avec un retour en arrière possible. La réplication logique native n’a pas encore
atteint le niveau de robustesse de Slony.
Pour plus d’informations sur Slony, n’hésitez pas à lire un de nos articles disponibles sur notre site6 .
Le thème des réplications complexes a aussi été abordé lors du PostgreSQL Sessions 20127 .
Bucardo8 est un des rares outils à proposer du multi‑maîtres, avec plusieurs primaires possibles. Il
s’agit aussi de réplication logique par triggers, mais sa mise en place est vraiment différente par rap‑
port à Slony.
Bucardo offre plusieurs types de réplication, mais le plus intéressant sur un PostgreSQL moderne est
le mode de synchronisation multi‑maîtres.
Le problème de toute réplication logique étant la résolution d’éventuels conflits, Bucardo offre plu‑
sieurs méthodes de résolution :
64 Réplication logique
DALIBO Formations
Il est également possible de créer son propre gestionnaire de résolution de conflit personnalisé.
Bucardo ne s’attelle qu’à la réplication des données, c’est à l’administrateur de réagir en cas de panne
et de réaliser les opérations de bascule et de remise en réplication.
La propagation des DDL n’est pas prise en compte. Il faut donc, comme pour Slony, exécuter les DDL
sur chaque serveur séparément.
Le projet est porté surtout par Greg Sabino Mulane, développeur très connu (et apprécié) dans la com‑
munauté PostgreSQL. Cela explique un développement apparemment peu actif9 , même si la correc‑
tion des bugs est généralement très rapide.
La mise en place de Bucardo est intéressante quand on tient à un cluster maître/maître sur les mêmes
tables. Le réseau doit être fiable. La moindre erreur peut tout de même poser des soucis de réconci‑
liation des données. En dehors de cela, il est préférable de se baser sur des solutions comme la répli‑
cation interne ou Slony, surtout si l’on peut séparer nettement les données dont chaque serveur est
responsable.
9
[Link]
Réplication logique 65
DALIBO Formations
1.10 CONCLUSION
La réplication logique de PostgreSQL apparue en version 10 continue de s’améliorer avec les versions.
Elle complète la réplication physique sans la remplacer.
Les cas d’utilisation sont nombreux, mais la supervision est délicate et il faut prévoir les sauve‑
gardes/restaurations et bascules.
1.10.1 Questions
66 Réplication logique
DALIBO Formations
1.11 QUIZ
[Link]
®
Réplication logique 67
DALIBO Formations
1.12.1 Pré‑requis
Ensuite, afin de réaliser l’ensemble des TP, créer 4 nouvelles instances PostgreSQL « instance[1‑4] »,
en leur attribuant des ports différents :
# rm -rf /var/lib/pgsql/15/instance1
# rm -rf /var/lib/pgsql/15/instance2
# rm -rf /var/lib/pgsql/15/instance3
# rm -rf /var/lib/pgsql/15/instance4
# export PGSETUP_INITDB_OPTIONS='--data-checksums'
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance1
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance2
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance3
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance4
$ ps -o pid,cmd fx
PID CMD
7077 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/14/instance4/
7079 \_ postgres: logger
7081 \_ postgres: checkpointer
7082 \_ postgres: background writer
7083 \_ postgres: walwriter
7084 \_ postgres: autovacuum launcher
7085 \_ postgres: logical replication launcher
7056 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/14/instance3/
7058 \_ postgres: logger
7060 \_ postgres: checkpointer
68 Réplication logique
DALIBO Formations
Le schéma de la base b1 de l’instance origine (instance1) est le suivant. Noter que la table t3 est
partitionnée.
Réplication logique 69
DALIBO Formations
But : Mettre en place la réplication complète d’une base avec la réplication logique.
®
Pour répliquer toute la base b1 sur le serveur instance2 :
Sur instance1, créer l’utilisateur de réplication logrepli et lui donner les droits de lecture sur les
tables de la base b1.
Redémarrer instance1.
Sur instance2, ajouter dans la base b1 les tables répliquées (sans contenu).
Vérifier que les tables ont le même contenu que sur instance1 et que les modifications sont éga‑
lement répliquées.
70 Réplication logique
DALIBO Formations
But : Mettre en place la réplication partielle d’une base avec la réplication logique.
®
On veut répliquer uniquement les tables t1 et t2 de la base b1 sur le serveur instance3.
Sur instance3, créer la base b1, les tables à répliquer, puis souscrire à la nouvelle publication de
instance1.
Sur instance4, souscrire à cette nouvelle publication de instance1. Pour créer la table t3_1, il
faut aussi créer la table mère t3.
Réplication logique 71
DALIBO Formations
Sur instance4, adapter les autorisations dans pg_hba.conf pour permettre une réplication
depuis instance4.
Redémarrer instance4.
Sur instance4, créer la publication pour t3_4. Il faudra importer la partition t3_4 et donner les
droits de lecture à logrepli.
Insérer des données dans t3_4 sur instance4 et vérifier que la réplication se fait de instance4
à instance1.
Voici un exemple de réplication entre des tables qui n’ont pas le même schéma de partitionnement
:
– Sur instance1, créer une base bench_part.
72 Réplication logique
DALIBO Formations
– Sur instance1 et instance2, compter les lignes dans chaque partition de pgbench_accounts.
Qu’observez‑vous ?
Réplication logique 73
DALIBO Formations
1.13.1 Pré‑requis
Ensuite, afin de réaliser l’ensemble des TP, créer 4 nouvelles instances PostgreSQL « instance[1‑4] »,
en leur attribuant des ports différents :
# rm -rf /var/lib/pgsql/15/instance1
# rm -rf /var/lib/pgsql/15/instance2
# rm -rf /var/lib/pgsql/15/instance3
# rm -rf /var/lib/pgsql/15/instance4
# export PGSETUP_INITDB_OPTIONS='--data-checksums'
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance1
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance2
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance3
# /usr/pgsql-15/bin/postgresql-14-setup initdb instance4
$ ps -o pid,cmd fx
PID CMD
7077 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/14/instance4/
7079 \_ postgres: logger
7081 \_ postgres: checkpointer
7082 \_ postgres: background writer
7083 \_ postgres: walwriter
7084 \_ postgres: autovacuum launcher
7085 \_ postgres: logical replication launcher
7056 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/14/instance3/
7058 \_ postgres: logger
7060 \_ postgres: checkpointer
74 Réplication logique
DALIBO Formations
Le schéma de la base b1 de l’instance origine (instance1) est le suivant. Noter que la table t3 est
partitionnée.
Réplication logique 75
DALIBO Formations
Sur instance1, créer l’utilisateur de réplication logrepli et lui donner les droits de lecture sur les
tables de la base b1.
wal_level = logical
Redémarrer instance1.
$ createdb -p 5433 b1
Sur instance2, ajouter dans la base b1 les tables répliquées (sans contenu).
Vérifier sur instance1, dans la vue pg_stat_replication l’état de la réplication logique. Sur
instance2, consulter pg_stat_subscription.
Sur instance1 :
76 Réplication logique
DALIBO Formations
-[ RECORD 1 ]----+------------------------------
pid | 7326
usesysid | 16451
usename | logrepli
application_name | subscr_complete
client_addr | [Link]
client_hostname |
client_port | 48094
backend_start | ...
backend_xmin |
state | streaming
sent_lsn | 0/195BF78
write_lsn | 0/195BF78
flush_lsn | 0/195BF78
replay_lsn | 0/195BF78
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | ...
Sur instance2 :
-[ RECORD 1 ]---------+------------------------------
subid | 16521
subname | subscr_complete
pid | 7325
relid |
received_lsn | 0/195BF78
last_msg_send_time | ...
last_msg_receipt_time | ...
latest_end_lsn | 0/195BF78
latest_end_time | ...
Vérifier que les tables ont le même contenu que sur instance1 et que les modifications sont éga‑
lement répliquées.
Toute opération d’écriture sur la base b1 du serveur instance1 est répliquée sur instance2.
Sur instance1 :
Réplication logique 77
DALIBO Formations
INSERT 0 1
UPDATE 1
DELETE 1
id_t1 | label_t1
-------+---------------
101 | t1, ligne 101
10 | T1, LIGNE 10
(2 rows)
Sur instance2 :
count
-------
100
id_t1 | label_t1
-------+---------------
101 | t1, ligne 101
10 | T1, LIGNE 10
Sur instance3, créer la base b1, les tables à répliquer, puis souscrire à la nouvelle publication de
instance1.
78 Réplication logique
DALIBO Formations
Sur instance1 :
b1=# SELECT * FROM pg_stat_replication \gx
-[ RECORD 1 ]----+------------------------------
pid | 7326
usesysid | 16451
usename | logrepli
application_name | subscr_complete
client_addr | [Link]
client_hostname |
client_port | 48094
backend_start | ...
backend_xmin |
state | streaming
sent_lsn | 0/1965548
write_lsn | 0/1965548
flush_lsn | 0/1965548
replay_lsn | 0/1965548
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | ...
-[ RECORD 2 ]----+------------------------------
pid | 7511
usesysid | 16451
usename | logrepli
application_name | subscr_partielle
client_addr | [Link]
client_hostname |
client_port | 48124
backend_start | ...
backend_xmin |
state | streaming
sent_lsn | 0/1965548
write_lsn | 0/1965548
flush_lsn | 0/1965548
replay_lsn | 0/1965548
write_lag |
flush_lag |
Réplication logique 79
DALIBO Formations
replay_lag |
sync_priority | 0
sync_state | async
reply_time | ...
Sur instance3 :
Sur instance4, souscrire à cette nouvelle publication de instance1. Pour créer la table t3_1, il
faut aussi créer la table mère t3.
$ createdb -p 5435 b1
$ pg_dump -p 5432 -s -t t3 -t t3_1 b1 | psql -p 5435 b1
wal_level = logical
80 Réplication logique
DALIBO Formations
Sur instance4, adapter les autorisations dans pg_hba.conf pour permettre une réplication
depuis instance4.
Redémarrer instance4.
Sur instance4, créer la publication pour t3_4. Il faudra importer la partition t3_4 et donner les
droits de lecture à logrepli.
Insérer des données dans t3_4 sur instance4 et vérifier que la réplication se fait de instance4
à instance1.
Sur instance1 :
INSERT 0 1
Sur instance4 :
Réplication logique 81
DALIBO Formations
INSERT 0 1
Sur instance1 :
pgbench --initialize \
--partition-method=hash \
--partitions=5 \
--port=5432 bench_part
82 Réplication logique
DALIBO Formations
pgbench --initialize \
--init-steps=dtp \
--partition-method=range \
--partitions=3 \
--port=5433 bench_part
L’erreur fait référence à une partition qui n’existe pas sur la souscription. C’est normal puisque le
schéma de partitionnement est différent. Un autre cas de figure peut se présenter : la partition existe,
mais les lignes ne correspondent pas aux contraintes de partitionnement. Dans ce cas la souscription
sera créée, mais des erreurs seront présentes dans les traces de PostgreSQL.
Réplication logique 83
DALIBO Formations
– Sur instance1 et instance2, compter les lignes dans chaque partition de pgbench_accounts.
Qu’observez‑vous ?
tableoid | count
--------------------+-------
pgbench_accounts_1 | 19851
pgbench_accounts_2 | 20223
pgbench_accounts_3 | 19969
pgbench_accounts_4 | 19952
pgbench_accounts_5 | 20005
¤ | 100000
(6 rows)
tableoid | count
--------------------+-------
pgbench_accounts_1 | 33334
pgbench_accounts_2 | 33334
pgbench_accounts_3 | 33332
¤ | 100000
(4 rows)
On constate que toutes les lignes sont répliquées et qu’elles sont ventilées différemment sur les deux
serveurs.
Ce paramétrage peut également être utilisé pour répliquer depuis une table partitionnée vers une
table classique.
84 Réplication logique
Les formations Dalibo
Pour toute information ou question, n’hésitez pas à nous écrire sur contact@[Link].
85
DALIBO Formations
– Industrialiser PostgreSQL
[Link]
Téléchargement gratuit
Les versions électroniques de nos publications sont disponibles gratuitement sous licence open
source ou sous licence Creative Commons.
86 Réplication logique