19
0
Fork 0
wiki/HowtoPostgreSQL/ReplicationLogique.md

4.9 KiB

Réplication Logique avec PostgreSQL

https://www.postgresql.org/docs/11/logical-replication.html

Mise en place

Sur le serveur primaire et réplica, on s'assure d'avoir deux bases :

postgres $ createuser -p 5432 -P foo
Enter password for new role:

postgres $ createdb -p 5432 -O foo foo

Sur le serveur primaire, on modifie la directive wal_level :

wal_level = logical

Puis l'on crée un utilisateur replication et une publication liée à cette base :

postgres $ createuser -p 5432 -P --replication replication

postgres $ psql -p 5432 foo

foo=# GRANT SELECT on ALL TABLES IN SCHEMA public TO replication;
GRANT

foo=# CREATE PUBLICATION alltables FOR ALL TABLES;
CREATE PUBLICATION

Sur le serveur réplica, on crée une subscription liée à cette base :

postgres $ psql -p 5432 foo

foo=# CREATE SUBSCRIPTION mysub CONNECTION 'dbname=foo host=192.0.2.1 port=5436 user=replication password=PASSWORD' PUBLICATION alltables;
NOTICE:  created replication slot "mysub" on publisher
CREATE SUBSCRIPTION

Attention, contrairement à la réplication physique, rien n'empêche d'écrire sur le serveur réplica.

Ensuite, il faut créer les tables de façon identique sur les deux bases :

postgres $ psql -U foo -h 127.0.0.1 -p 5432 foo
foo=> CREATE TABLE t (a INT);

Enfin, l'insertion de données sur le serveur primaire, devrait provoquer le transfert de ces données sur le serveur réplica :

LOG:  logical replication table synchronization worker for subscription "mysub", table "t" has started

Si besoin, on peut « rafraichir » la subscription sur le serveur replica via la commande :

postgres $ psql -p 5432 foo

foo=# ALTER SUBSCRIPTION mysub REFRESH PUBLICATION;

Administration

Ajout / modification d'une table

Si l'on veut ajouter ou modifier une table, il faut :

  • créer / modifier la table sur les 2 serveurs maître et réplica
  • relancer la commande suivante sur le serveur maître :
postgres $ psql -p 5432 foo

foo=# GRANT SELECT on ALL TABLES IN SCHEMA public TO replication;
GRANT
  • relancer la commande suivante sur le serveur réplica :
postgres $ psql -p 5432 foo

foo=# ALTER SUBSCRIPTION mysub REFRESH PUBLICATION;

On peut ensuite insérer des données sur la nouvelle table qui sera répliquée.

Suspendre une réplication

Mettre en pause une réplication :

foo=# ALTER SUBSCRIPTION mysub DISABLE;

LOG:  le processus apply de réplication logique pour la souscription « mysub » s'arrêtera car la souscription a été désactivée

Reprendre une réplication :

foo=# ALTER SUBSCRIPTION mysub ENABLE;

Suppression

DROP PUBLICATION alltables;
DROP SUBSCRIPTION mysub;

Ajout d'un schema à une base / utilisateur répliqué

Si l'on ajoute un schéma à une base répliqué, pour que la syncho des données de ce shcéma se fasse, il faut que l'utilisateur SQL dédié à la réplication est le droit USAGE sur ce schéma :

foo=# GRANT USAGE ON SCHEMA bar TO replication;

Sinon la copié initiale des données de ce schéma n'est pas copié dans la réplication, on auras des erreurs de ce type dans les logs sur le master :

2020-05-30 00:06:26.163 CEST [40846] replication@foo ERROR: permission denied for schema bar
2020-05-30 00:06:26.163 CEST [40846] replication@foo STATEMENT: COPY bar."21GEHAVL" TO STDOUT

Sur le réplica on aura des erreurs de ce type :

020-05-30 15:55:57.594 CEST [986] LOG: le processus de synchronisation des tables en réplication logique pour la souscription « mysub_sql3 », table « 21NOHAII » a démarré
2020-05-30 15:55:57.601 CEST [985] ERREUR: n'a pas pu lancer la copie initiale du contenu de la table « bar.21GEHVRH » : ERROR: permission denied for schema bar

Monitoring

Sur le serveur replica, on peut surveiller le bon fonctionnement de la réplication ainsi :

postgres=# select * from pg_subscription ;
 subdbid | subname | subowner | subenabled |                                subconninfo                                 | subslotname | subsynccommit | subpublications 
---------+---------+----------+------------+----------------------------------------------------------------------------+-------------+---------------+-----------------
   16385 | mysub   |       10 | t          | dbname=foo host=192.0.2.1 port=5432 user=replication password=PASSWORD     | mysub       | off           | {alltables}
(1 row)

postgres=# select * from pg_stat_subscription ;
 subid | subname |  pid  | relid | received_lsn |      last_msg_send_time       |     last_msg_receipt_time     | latest_end_lsn |        latest_end_time        
-------+---------+-------+-------+--------------+-------------------------------+-------------------------------+----------------+-------------------------------
 16388 | mysub   | 12767 |       | 0/16A58D8    | 2019-09-17 21:09:16.512057+00 | 2019-09-17 21:09:16.512241+00 | 0/16A58D8      | 2019-09-17 21:09:16.512057+00