La réplication en flux (_Streaming Replication_) est disponible à partir de la version 9.0 de PostgreSQL. Celle-ci est aussi appelée _Réplication Physique_ en opposition à la _Réplication Logique_ apparue dans la version 10.
* Réplication de type asynchrone (le maître et le réplica peuvent ne pas être synchro à un instant _t_) ou synchrone (une transaction est commitée uniquement si elle a pu être écrite sur le maître et envoyé au réplicat);
* réplication basée sur les journaux binaires générés par PostgreSQL (WAL, pour _Write Ahead Log_);
* réplication de l'intégralité des données et structures (toutes les bases de données sont répliquées, avec leurs tables et leurs données, pas de granularité possible). Cette fonctionnalité commencera à être introduite à partir de la 9.3;
Par rapport au mode de réplication _Hot Standby_, l'avantage avec la réplication en flux est qu'il n'est pas besoin d'attendre qu'un journal soit plein et fermé pour qu'il soit communiqué au serveur réplica. À l'inverse cela introduit une légère charge supplémentaire (au niveau CPU) puisqu'un (ou plusieurs) processus supplémentaire doit tourner sur le maître (wal_senders).
> **Note** : Cette configuration est relative au serveur maître, mais elle doit également être reprise à l'identique sur le serveur réplica, dans le cas où les rôles doivent être échangés (suite à un failover/switchover).
> *Note* 1 : A partir de Postgresql 10 il n'est plus necessaire de modifier la variable hot_standby, ni de créer au préalable le fichier recovery.conf, voir directement la section **Synchronisation initiale des données (Méthode courante)**
> *Note* 2 : Cette configuration est relative au serveur réplica, mais elle doit également être reprise à l'identique sur le serveur maître, en renommant le fichier `recovery.conf` pour qu'il ne soit pas pris en compte.
> *Note* 3 : En Debian 8 ou 9 et postgresql >v9 on ferra comme ceci :
Il est nécessaire que ce fichier appartienne à l'utilisateur _postgres_, notamment en cas de promotion en master (car PostgreSQL va renommer le fichier en `recovery.done`) :
* sur le maître, indiquer à PostgreSQL qu'on commence une sauvegarde. Il va notamment faire un checkpoint dans son WAL courant et retourner sa position:
L'option `-R` s'occupe de créer le fichier recovery.conf (ou postgresql.auto.conf si version suppérieure à 11) dans `/var/lib/postgresql/<version>/<cluster>/`
pg_basebackup s'occupe de faire un checkpoint du WAL courant (pg_start_backup) de transférer les fichiers des bases puis d'exécuter la fonction SQL _pg_stop_backup_
Pendant le transfert des fichiers, la base a pu subir des modifications. C'est pourquoi pg_basebackup attend que le primaire et fait un checkpoint dans sont WAL avant de tranférés les données, par défaut un checkpoint est fait toutes les 5 minutes, donc la commande pg_basebackup peut prendre 5 minutes avant de commencer a synchronisé les données.
Il est nécessaire que ce fichier appartienne à l'utilisateur _postgres_, notamment en cas de promotion en master (car PostgreSQL va renommer le fichier en `recovery.done`) :
* Si version Postgresql supérieure à 11, le `recovery.conf` n'existe plus, il est remplacé par le fichier postgresql.auto.conf, et le fichier `standby.signal`
### Création d'un slot de réplication physique pour éviter un décrochage entre le primaire et le secondaire
Pour éviter qu'il y ait un décrochage entre le primaire et le secondaire, dans le cas où le secondaire soit stoppé quelques minutes ou qu'il soit très chargé par des requêtes, on créeun slot de réplication physique sur le primaire comme ceci :
Sur le secondaire, on rajoute la variable *primary_slot_name* dans le fichier recovery.conf (version <=11) ou postgresql.conf en v12 avec la mention du slot a utilisé :
~~~
primary_slot_name = 'nom_du_secondaire'
~~~
On redémarre postgresql sur le secondaire.
**Attention:** Si on doit stopper le secondaire pendant un temps assez long, il faut supprimer le slot de réplication physique, sinon les WAL vont s'accumuler sur le primaire, ce qui peu crée un danger en cas de saturation de l'espace disque.
Il est donc impératif de supprimer un slot de réplication si le secondaire a été désactivé ou hors ligne un certain temps, quitte à devoir reconstruire le secondaire complétement.
Pour listés tous les slots de réplication active sur un serveur, que ce soit des slots physique ou logique, on peux le faire avec la requête suivante :
* Les données à surveiller sont notamment les `*_location`, qui indique la position courante dans les WAL à différentes étapes de la réplication. Voir <https://www.postgresql.org/docs/current/static/monitoring-stats.html#PG-STAT-REPLICATION-VIEW> pour le détails des champs.
* Pour pouvoir quantifier le retard de réplication, on peut utiliser la commande [check_postgres](http://bucardo.org/check_postgres/check_postgres.pl.html) avec l'option _hot_standby_delay_:
Où localhost est le maître et 192.0.2.2 le réplica. Les valeurs de _replay_delay_ et _receive-delay_ sont *à priori* exprimées en octets de WAL à rejouer.
Si sur le primaire on a aussi des slot de réplication logique, on peut les exclure du check *streaming_delta* avec l'option --exclude qui supporte les regex, dans l'exemple on part du principe que les slots de réplication logique sont nommées mysub_* :
Le réplica va d'abord rattraper son éventuel retard dans le traitement des logs de réplication, puis une fois prêt se mettra à accepter les requêtes en écritures.
> *Note* : Attention, à partir du moment où le réplica cesse de lire les journaux du maître, toutes les écritures qui continuent de se faire sur le maître seront perdues. Il faut donc être certain que le maître soit réellement inaccessible avant de faire la bascule.
État courant: le serveur réplica accepte les écritures suite à la procédure de failover, et le serveur maître contient des données obsolètes car pas mises à jour.
Il faut alors mettre en place le `recovery.conf` sur l'ancien master et démarrer PostgreSQL. Il va alors rejouer les WAL pour rattraper le retard accumulé, puis se mettre en mettre en mode _streaming replication_.
* Arrêter/reprendre le flux des WAL depuis le maître. Il ne semble pas y avoir de solution autre que de couper le flux au niveau réseau. Sur le maître:
* Si une requête sur le serveur réplica bloque la réplication (par exemple un `SELECT` qui bloque un `DROP TABLE`) pendant un temps trop long, la requête sur le réplica sera tuée (ici le SELECT). Ce temps est défini par la directive `max_standby_streaming_delay` sur la configuration du réplica.
Ce comportement peut-être désactivé grâce à la directive `hot_standby_feedback`, qui fait en sorte que le réplica communique l'état des requêtes au maître, mais cela à un impact sur le maître.