From 90fe47f2a288a7a11484c0851510b58f76acb558 Mon Sep 17 00:00:00 2001 From: mathieu Date: Wed, 31 Jan 2024 16:31:37 +0100 Subject: [PATCH 1/4] atelier maj repli logique --- fr/atelier-maj-repli-logique/Makefile | 220 ++++ fr/atelier-maj-repli-logique/README.md | 92 ++ .../maj_replication_logique.md | 978 ++++++++++++++++++ .../medias/cas_repli_1.png | Bin 0 -> 18446 bytes .../medias/cas_repli_2.png | Bin 0 -> 17610 bytes .../medias/cas_repli_3.png | Bin 0 -> 12991 bytes .../medias/common-postgresql_logo.png | Bin 0 -> 50279 bytes .../medias/miseenplace_1.png | Bin 0 -> 8720 bytes .../medias/miseenplace_2.png | Bin 0 -> 14089 bytes .../medias/miseenplace_3.png | Bin 0 -> 15773 bytes .../medias/miseenplace_4.png | Bin 0 -> 13190 bytes 11 files changed, 1290 insertions(+) create mode 100644 fr/atelier-maj-repli-logique/Makefile create mode 100644 fr/atelier-maj-repli-logique/README.md create mode 100644 fr/atelier-maj-repli-logique/maj_replication_logique.md create mode 100644 fr/atelier-maj-repli-logique/medias/cas_repli_1.png create mode 100644 fr/atelier-maj-repli-logique/medias/cas_repli_2.png create mode 100644 fr/atelier-maj-repli-logique/medias/cas_repli_3.png create mode 100644 fr/atelier-maj-repli-logique/medias/common-postgresql_logo.png create mode 100644 fr/atelier-maj-repli-logique/medias/miseenplace_1.png create mode 100644 fr/atelier-maj-repli-logique/medias/miseenplace_2.png create mode 100644 fr/atelier-maj-repli-logique/medias/miseenplace_3.png create mode 100644 fr/atelier-maj-repli-logique/medias/miseenplace_4.png diff --git a/fr/atelier-maj-repli-logique/Makefile b/fr/atelier-maj-repli-logique/Makefile new file mode 100644 index 0000000..deec7a2 --- /dev/null +++ b/fr/atelier-maj-repli-logique/Makefile @@ -0,0 +1,220 @@ +############################################################################### +# +# How To Use this Makefile +#------------------------------------------------------------------------------ +# Let's say you have a markdown source file named foo.md in the 'fr' directory +# +# - `make fr/foo.pdf` will build a PDF from fr/foo.md +# - `make fr/foo.epub` will build an EPUB from fr/foo.md +# - `make all` will build all source files in all formats +# - `make clean` will remove all build artifacts +# +# Pandoc or docker ? +#------------------------------------------------------------------------------ +# +# - by default, we use pandoc to compile documents +# - if pandoc is not installed, we use a docker image instead +# - use `DOCKER=latest make all` to force make to use docker +# +# +# Dalibo Themes or not ? +#------------------------------------------------------------------------------- +# +# - dalibo themes are not open source but they're optionnal +# - you can compile the docs without them +# - use `LOCAL_DLB=/tmp/dalibo make all` to change the dalibo themes location +# +# +############################################################################### + + +ECHO=$(info Compiling $^ into $@) + +# +# Folders +# +IN=`basename $^` +OUT=`basename $@` +DIR=`dirname $^` + + +# +# LOCAL_DLB is a directory containing dalibo themes +# by default it's ~/.dalibo/themes/ +# +# dalibo themes are not open source but they're optionnal +# you can compile the docs without them +# +ifeq ($(LOCAL_DLB),) + LOCAL_DLB=$(HOME)/.dalibo/themes/ +endif + +# Normally DLB == LOCAL_DLB, but this will change when we'll use docker +DLB=$(LOCAL_DLB) + +# +# Pandoc binary +# +# TODO: factorize with docker call below +PANDOC_PARAMS=--filter pandoc-include +P=pandoc $(PANDOC_PARAMS) --metadata=dlb:$(LOCAL_DLB) + +# +# If pandoc is not installed, +# Then let's use the docker image by setting DOCKER_TAG +# +ifeq (, $(shell which pandoc)) + DOCKER?=19.08 +endif + +# If make was launched with DOCKER=... or pandoc was not there, +# Then we force usage of docker by setting DOCKER_TAG +ifneq ($(DOCKER),) + DOCKER_TAG=$(DOCKER) +endif + +# If DOCKER_TAG is defined +# Then we replace $P with a docker call +ifneq ($(DOCKER_TAG),) + DOCKER_DLB=/root/.dalibo/themes + P=docker run --rm -it --privileged --volume `pwd`:/pandoc --volume $(LOCAL_DLB):$(DOCKER_DLB) dalibo/pandocker:$(DOCKER_TAG) --metadata=dlb:$(DOCKER_DLB) $(PANDOC_PARAMS) + DLB=$(DOCKER_DLB) +endif + +# +# Pandoc Compilation Flags +# +ifeq ("$(wildcard $(LOCAL_DLB))","") + ##### + # dalibo themes are not available + # Let's use default compilation flags + #### + + # self-contained mode is currently buggy with the official revealjs css file + # REVEAL_FLAGS=-t revealjs --self-contained --standalone -V revealjs-url:http://lab.hakim.se/reveal-js/ + REVEAL_FLAGS=-t revealjs --standalone -V revealjs-url:http://lab.hakim.se/reveal-js/ + TEX_FLAGS= -st beamer + BEAMER_FLAGS= -st beamer + PDF_FLAGS=--toc --pdf-engine=xelatex + ODT_FLAGS=-t odt --toc + DOC_FLAGS=-t doc --toc + EPUB_FLAGS=-t epub --toc + HANDOUT_HTML_FLAGS=-t html5 --self-contained --standalone --toc --toc-depth=2 +else + #### + # Dalibo's Compilation Flags + #### + REVEAL_FLAGS=-t revealjs --template="$(DLB)/reveal.js/pandoc/templates/dalibo.revealjs" --self-contained --standalone -V revealjs-url="$(DLB)/reveal.js/" + TEX_FLAGS= -st beamer -V theme=Dalibo + BEAMER_FLAGS= -st beamer -V theme=Dalibo + PDF_FLAGS=--pdf-engine=xelatex --toc --template=$(DLB)/tex/book1/template.tex --filter pandoc-latex-admonition + ODT_FLAGS=-t odt --toc --reference-odt=$(DLB)/odt/template_conference.dokuwiki.odt + DOC_FLAGS=-t doc --toc --reference-doc=$(DLB)/doc/template_conference.dokuwiki.doc + EPUB_FLAGS= + HANDOUT_HTML_FLAGS=-t html5 --self-contained --standalone --toc --toc-depth=2 --template=$(DLB)/html/uikit/dalibo.html +endif + +# +# SRCS is the list of all the source markdown files +# README files and other documentation markdown files are not compiled +# +EXCLUDE_FILES=\./\(LICENSE\|QUICKSTART\|CONTRIBUTING\|SYNTAX\|INSTALL\|AUTHORS\)\.md +SRCS=$(shell find . -name '*.md' -and -not -name README.md -and -not -regex '$(EXCLUDE_FILES)' -and -not -path './themes/*' -and -not -path './include/*' -and -not -path './fr/include/*' ) + +JSON_OBJS=$(SRCS:.md=.json) +REVEAL_OBJS=$(SRCS:.md=.slides.html) +TEX_OBJS=$(SRCS:.md=.tex) +BEAMER_OBJS=$(SRCS:.md=.beamer.pdf) +PDF_OBJS=$(SRCS:.md=.pdf) +PEECHO_OBJS=$(SRCS:.md=.peecho.pdf) +ODT_OBJS=$(SRCS:.md=.odt) +DOC_OBJS=$(SRCS:.md=.doc) +EPUB_OBJS=$(SRCS:.md=.epub) +HANDOUT_HTML_OBJS=$(SRCS:.md=.handout.html) + +_PHONY: all + +test: + echo $(DLB) + echo $(REVEAL_FLAGS) + +install: + ln -s $(HOME)/.dalibo/themes/ + +uninstall: + rm themes + +# +# Supported formats +# +#all: reveal tex beamer pdf odt doc epub +all: reveal handout_html pdf epub + +json: $(JSON_OBJS) +handout_html: $(HANDOUT_HTML_OBJS) +reveal: $(REVEAL_OBJS) +tex: $(TEX_OBJS) +beamer: $(BEAMER_OBJS) +pdf: $(PDF_OBJS) +peecho: $(PEECHO_OBJS) +odt: $(ODT_OBJS) +doc: $(DOC_OBJS) +epub: $(EPUB_OBJS) + +%.all: %.html %.tex %.beamer.pdf %.pdf %.odt %.doc %.epub + $(ECHO) + +%.json: %.md + $(ECHO) + cd $(DIR) && $P $(JSON_FLAGS) $(IN) -o $(OUT) + +%.slides.html: %.md + $(ECHO) + cd $(DIR) && $P $(REVEAL_FLAGS) $(IN) -o $(OUT) + +%.handout.html: %.md + $(ECHO) + cd $(DIR) && $P $(HANDOUT_HTML_FLAGS) $(IN) -o $(OUT) + +%.tex: %.md + $(ECHO) + cd $(DIR) && $P $(TEX_FLAGS) $(IN) -o $(OUT) + +%.beamer.pdf: %.md + $(ECHO) + TEXMFHOME=$(DLB)/beamer cd $(DIR) && $P $(BEAMER_FLAGS) $(IN) -o $(OUT) + +%.pdf: %.md + $(ECHO) + cd $(DIR) && $P $(PDF_FLAGS) $(IN) -o $(OUT) + + +%.peecho.pdf: %.pdf + $(ECHO) + cd $(DIR) && $(LOCAL_DLB)/tex/book1/postprod.peecho.py -b $(LOCAL_DLB)/_build/tex/book1/backcover.pdf -n $(LOCAL_DLB)/_build/tex/book1/note.pdf -p $(LOCAL_DLB)/_build/tex/book1/publications.pdf $(IN) -o $(OUT) + +%.odt: %.md + $(ECHO) + cd $(DIR) && $P $(ODT_FLAGS) $(IN) -o $(OUT) + + +%.doc: %.md + $(ECHO) + cd $(DIR) && $P $(DOC_FLAGS) $(IN) -o $(OUT) + + +%.epub: %.md + $(ECHO) + cd $(DIR) && $P $(EPUB_FLAGS) $(IN) -o $(OUT) + +clean: + rm -fr $(REVEAL_OBJS) + rm -fr $(HANDOUT_HTML_OBJS) + rm -fr $(TEX_OBJS) + rm -fr $(BEAMER_OBJS) + rm -fr $(PDF_OBJS) + rm -fr $(PEECHO_OBJS) + rm -fr $(ODT_OBJS) + rm -fr $(DOC_OBJS) + rm -fr $(EPUB_OBJS) + rm -fr $(HTML_HANDOUT_OBJS) diff --git a/fr/atelier-maj-repli-logique/README.md b/fr/atelier-maj-repli-logique/README.md new file mode 100644 index 0000000..9f28a6a --- /dev/null +++ b/fr/atelier-maj-repli-logique/README.md @@ -0,0 +1,92 @@ +# atelier-maj-repli-logique + + + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin https://gitlab.dalibo.info/mathieu/atelier-maj-repli-logique.git +git branch -M main +git push -uf origin main +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](https://gitlab.dalibo.info/mathieu/atelier-maj-repli-logique/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/fr/atelier-maj-repli-logique/maj_replication_logique.md b/fr/atelier-maj-repli-logique/maj_replication_logique.md new file mode 100644 index 0000000..edf8977 --- /dev/null +++ b/fr/atelier-maj-repli-logique/maj_replication_logique.md @@ -0,0 +1,978 @@ +--- +title: "Mise à jour majeure par réplication logique" +subtitle : "Pour les versions de PostgreSQL supérieures à 10" +licence : "PostgreSQL" +author: "Mathieu RIBES" +reviewer: "" +date: "17 novembre 2020" + +to: '' +customer: '' +address: '' +reference: '' +url: www.dalibo.com +revision: 1.2 + +## +## PDF Options +## + +## Sommaire +# toc: true + +## Limiter la profondeur de la table des matières +toc-depth: 4 + +## Mettre les liens http en pieds de page +links-as-notes: true + +## Police plus petite dans un bloc de code +code-blocks-fontsize: small + +## Filtre : pandoc-latex-admonition +pandoc-latex-admonition: + - color: DodgerBlue + classes: [slide-content] + linewidth: 4 + +--- + +## Au menu + +
+ + * Principes de la réplication logique + * Rappels sur les migrations de versions majeures + * Exemples d'utilisation + * Mise en place d'une mise à jour majeure +
+ +
+ +
+ +----- + +## Principes de la réplication logique + +
+ + * Fonctionnement + * Quelques termes + * Processus et paramètres + * Granularité et Type de réplication + * Limitations +
+ +
+ +
+ +----- +### Fonctionnement + +
+ + * Réplication logique avant la version 10 + * Non native + * Uniquement grâce à des outils externes par triggers (slony, bucardo,...) + * Réplication logique après la 10 + * Native + * Asymétrique + * Asynchrone / synchrone +
+ +
+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. La table cible peut être modifiée 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. Cependant, il est possible de réaliser des réplications croisées où un +ensemble de tables est répliqué de l'instance 1 vers l'instance 2 et un autre +ensemble de tables est répliqué de l'instance 2 vers l'instance 1. + +Comme la réplication physique, la réplication logique peut être configurée en +asynchrone comme en synchrone, suivant le même paramétrage (`synchronous_commit`, `synchronous_standby_names`). +
+ + +----- +### Quels termes +
+ + * Sur l'instance d'**origine** (ou **primaire**) + * Publication + * Sur l'instance de **destination** (ou **réplicat**) + * 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'une instance. Cette instance est l'instance origine. De cette instance sont +enregistrées les modifications qu'une ou plusieurs autres instances pourront récupérer. Ces +instances de destination indiquent leur intérêt sur ces modifications en +s'abonnant à la publication. +De ceci, il découle que : + + * l'instance origine est l'instance où les écritures sur une table sont + enregistrées pour publication vers d'autres instances ; + * les instances intéressés par ces enregistrements sont les instances + destinations ; + * une instance origine doit proposer une publication des modifications ; + * les instances destinations intéressés doivent s'abonner à une publication. + +Dans un cluster de réplication, une instance peut avoir un rôle d'instance +origine ou d'instance destination. Elle peut aussi avoir les deux rôles. Dans ce +cas, elle sera origine pour certaines tables et destination pour d'autres. Elle +ne peut pas être à la fois origine et destination pour la même table. +
+ +----- +### Les processus et les paramètres +
+ +Sur l'instance d'origine (primaire) + + * Paramètre `wal_level` = logical + * Processus `wal sender` (`max_wal_senders`) + * Slot de réplication créé automatiquement (`max_replication_slots`) + +Sur l'instance de destination (réplicat) + + * Processus `logical replication worker` + * Autorisation de connexion sur l'instance de publication +
+ +
+La réplication logique utilise le même canal d'informations que la réplication +physique, à savoir, les enregistrements des journaux de transactions. Pour que les +journaux disposent de suffisamment d'informations, le paramètre `wal_level` +doit être configuré à `logical`. +Une fois cette configuration effectuée et PostgreSQL redémarré sur l'instance origine, l'instance destination pourra se connecter à l'instance origine dans le +cadre de la réplication. Lorsque cette connexion est faite, un processus `wal sender` apparaîtra sur l'instance origine. Ce processus sera en communication avec un processus `logical replication worker` sur l'instance destination. +Chaque abonné maintient un slot de réplication sur l'instance de l'éditeur. Par +défaut il est créé et supprimé automatiquement. La copie initiale des données +crée également des slots de réplication temporaires. +
+ +----- +### Granularité de la réplication logique + +
+ + * Par table + * publication pour toutes les tables + * publications pour des tables spécifiques + * Par opération + * insert, update, delete +
+ + +
+La granularité de la réplication physique est simple : c'est l'instance et +rien d'autre. +Avec la réplication logique, la granularité est la table. Une publication se +crée en indiquant la table pour laquelle on souhaite publier les +modifications. On peut en indiquer plusieurs. On peut en ajouter après en +modifiant la publication. Cependant, une nouvelle table ne sera pas ajoutée +automatiquement à la publication. Ceci n'est possible que dans un cas précis : +la publication a été créée en demandant la publication de toutes les tables +(clause `FOR ALL TABLES`). +La granularité peut aussi se voir au niveau des opérations de modification +réalisées. On peut très bien ne publier que les opérations d'insertion, de +modification ou de suppression. Par défaut, tout est publié. +
+ +----- + +### Type de réplication logique +
+ + * Réplication complète + + * `CREATE PUBLICATION bd1_publication FOR ALL TABLES;` + * Réplication partielle + + * `CREATE PUBLICATION bd1_publication FOR TABLE t1,t2,...;` + * Réplication croisée +
+ +
+ +La réplication physique a le désavantage notamment de ne pouvoir répliquer que l'intégralité de l'instance. A contrario, la réplication logique peut répliquer de façon plus granulaire une ou plusieurs tables d'une base de données de l'instance. + * Si l'on souhaite une réplication complète de l'instance, pour chaque base de données, il faudra publier l'intégralité de ses tables. +```sql +\c bd1 +CREATE PUBLICATION bd1_publication FOR ALL TABLES; +\c bd2 +CREATE PUBLICATION bd2_publication FOR ALL TABLES; +``` + * Si l'on souhaite une réplication partielle de l'instance, il faudra choisir les objects à répliquer. +```sql +\c bd1 +CREATE PUBLICATION bd1_publication FOR TABLE t1,t2,...; +\c bd2 +CREATE PUBLICATION bd2_publication FOR t4; +``` + * Il est possible également de croiser les publications sur différentes tables, mais une table ne peut être à la fois publiée et abonnée. + +
+ +----- + +### Limitations de la réplication logique + +
+ + * Pas de réplication des requêtes DDL (et `TRUNCATE` pour PostgreSQL < 11) + * Pas de réplication des valeurs des séquences + * Pas de réplication des LO (table système) + * Pas de réplication (automatique) des partitions (<13) + * Pas de réplication des vues, vues matérialisées, tables non journalisées + * Coût en CPU et I/O +
+
+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. Donc une table nouvellement créée ne sera pas forcément +répliquée. 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. + +Il n'y a pas non plus de réplication des valeurs des séquences. Les valeurs +des séquences sur les serveurs 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éplication 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. + +Pour répliquer une table partitionnée, il est nécessaire d'ajouter les partitions individuellement à la publication. En version 13 de PostgreSQL lorsqu'une table partitionnée est ajoutée à la réplication, toutes les partitions ou futures partitions sont publiées. + +Enfin, la réplication logique a un coût en CPU (sur les deux instances +concernées) comme en écritures disques +relativement important : attention aux petites configurations. +
+ +----- +## Rappels sur les migrations de versions majeures + +
+ + * pg_dump / pg_restore + * pg_upgrade mode normal + * pg_upgrade mode lien physique + * réplication logique +
+ +----- +
+ +| Outil | Coupure production | Retour arrière | Fragmentation | +| -------------------- | ---------------------------------------- | -------------- | ------------- | +| pg_dump / pg_restore | Elevé = sauvegarde + restauration | OUI | NON | +| pg_upgrade | Moyen = copie physique des données | OUI | OUI | +| pg_upgrade | Court = mise à jour directe des fichiers | NON | OUI | +| réplication logique | Court = mais préparation en amont | OUI | OUI | +
+ +
+Il existe plusieurs méthodes pour mettre à jour une instance PostgreSQL vers une version supérieure. + +**pg_dump/pg_restore** + +La première méthode : utiliser `pg_dump` suivi de `pg_restore`. Cette méthode reste la plus sûre et à privilégier sur de petites volumétries. + +Les avantages sont : + + * Une suppression totale de la fragmentation des tables et des index. + * La vérification de l'intégrité des données. + * L'affranchissement de saut de versions. + * La mise à jour granulaire. + +L' inconvénient majeur de cette méthode est sa lenteur d'exécution. L'arrêt de production durera le temps du début de la sauvegarde, jusqu'à la fin de la restauration. + +**pg_upgrade** + +La deuxième méthode : utiliser `pg_upgrade`. + +`pg_upgrade` va récupérer la déclaration des objets sur l'ancienne instance et l'intégrer dans la nouvelle instance. Il va traiter la mise à jour de ces objets et copier les fichiers de données de l'ancienne instance vers la nouvelle. + +L'avantage est la rapidité (elle dépend tout de même de la rapidité du réseau et d'écriture sur la nouvelle instance). + +L'inconvénient majeur est que `pg_upgrade` conserve la fragmentation des tables et des index. Il est souvent conseillé de faire une réindexation après un `pg_upgrade`. + +Il est possible d'accélérer le processus de mise à jour avec `pg_ugrade` en utilisant les liens physiques (hardlink). On s'affranchit ainsi de la copie des données. Ceci implique bien sûr que la nouvelle instance se trouve sur le même serveur. + +Note importante : `pg_upgrade` n'est pas granulaire, la mise à jour est pour la totalité des données de l'instance. + +**Réplication logique** + +La troisième méthode : la réplication logique. + +Cette méthode a le très gros avantage de minimiser au maximum le temps de coupure de la production. +Le principe est de répliquer l'intégralité des données, à chaud, de l'ancienne instance vers la nouvelle, puis au moment décidé, de basculer sur la nouvelle instance en quelques minutes. +
+ +----- +## Exemples d'utilisation + +### 1 : Partage de bases + +
+ +![](medias/cas_repli_1.png) +
+ +
+Quelques cas d'usage de migration avec la réplication logique que l'on ne peut pas notamment faire avec `pg_upgrade`. + +Premier cas : profiter de la mise à jour majeure pour partager les bases sur plusieurs instances. Par exemple 3 bases migrées sur 3 instances différentes pour respecter des exigences de cloisonnement client. + +
+----- + +### 2 : Rassemblement de bases + +
+ +![](medias/cas_repli_2.png) +
+ +
+Deuxième cas : profiter de la mise à jour majeure pour rassembler des bases sur une même instance. Processus inverse du premier cas, par exemple pour des questions de rationalisation de coût. +
+----- + +### 3 : Migration échelonnée + +
+ +![](medias/cas_repli_3.png) +
+ +
+Troisième cas : la mise à jour majeure échelonnée. + +C'est un cas souvent rencontré lorsqu'on a plusieurs bases de clients différents sur une même instance, mais ces clients n'ont pas les mêmes horaires de maintenance pour leurs bases de données. A ce moment là, on pourra migrer base après base dans des tranches horaires différentes sans impacter les bases entre elles. +
+ +----- +## Mise en place + +
+ +![](medias/miseenplace_1.png) +
+ +
+Le principe est simple. + +On dispose d'une instance de base de données contenant une ou plusieurs bases accédées par différentes applications. Cette instance est en version majeure inférieure à l'instance de destination. + +La première étape est la configuration de l'instance origine (primaire), afin de la préparer à la réplication logique. +
+ +----- +### Préparation de l'instance origine (primaire) + +
+ + * `wal_level` = logical (attention redémarrage requis) + * Création de la publication + * `CREATE PUBLICATION ... FOR ALL TABLES`; + * Création de l'utilisateur pour la réplication + * Attribution des droits sur les objets répliqués + * `GRANT SELECT ON ALL TABLES IN SCHEMA public TO user_repli`; +
+ +
+L'instance origine (primaire) doit être préparée afin de pouvoir utiliser la réplication logique. Pour cela il faut tout d'abord vérifier et modifier si besoin le paramètre `wal_level`. Par défaut ce paramètre à la valeur `replica`. Cette valeur permet à PostgreSQL d'écrire dans les journaux de transactions `WAL` des informations nécessaires à la réplication physique. Mais ces informations ne sont pas suffisantes pour la réplication logique. Pour cela, La valeur du paramètre `wal_level` doit être `logical`. Attention le changement du paramètre `wal_level` implique un redémarrage de l'instance pour être pris en compte. + + +Autre paramètre à vérifier : `max_wal_senders`, par défaut ce paramètre a la valeur 10, donc souvent suffisant pour mettre en place la réplication logique. Attention le changement du paramètre `max_wal_senders` implique un redémarrage de l'instance pour être pris en compte. + +La réplication logique s'appuie également sur un slot de réplication afin de ne pas perdre d'informations lors d'une coupure longue de la réplication. De ce fait il est nécessaire de vérifier que le paramètre `max_replication_slots` soit également suffisant. Par défaut ce paramètre a la valeur 10. Attention le changement du paramètre `max_replication_slots` implique un redémarrage de l’instance pour être pris en compte. + +Une fois les paramètres configurés, la publication des tables peut être initiée. + +Voici la syntaxe : +```sql +CREATE PUBLICATION name + [ FOR TABLE [ ONLY ] table_name [ * ] [, ...] + | FOR ALL TABLES ] + [ WITH ( publication_parameter [= value] [, ... ] ) ] +``` + +L'accès aux données publiées sur l'instance origine (primaire) se fait via un slot de réplication qui sera créé lors de l'abonnement du réplicat. Il faut pour cela créer un rôle (ou utilisateur) et les autorisations de connexion nécessaires pour ce rôle. + +Création du rôle : +```sql +CREATE ROLE user_repli LOGIN REPLICATION; +``` + +Cet utilisateur doit pouvoir lire le contenu des tables répliquées. Il lui faut donc le droit `SELECT` sur celles-ci : + +```sql +GRANT SELECT ON ALL TABLES IN SCHEMA public TO logrepli; +``` + +N'oublions pas la configuration des autorisations au niveau du fichier `pg_hba.conf`, et également d'utiliser le fichier `.pgpass` pour stocker les informations d'identification. Cela évite notamment les `trust` (trou de sécurité) dans le fichier `pg_hba.conf`. + +```sql +host base_origine user_repli xxx.xxx.xxx.xxx/xx scram-sha-256 +``` + +
+ +----- + +
+![](medias/miseenplace_2.png) +
+ +
+L'instance destination (réplicat) est configurée comme une instance normale : en lecture/écriture. Elle est de version majeure supérieure à l'instance d'origine (primaire). +Les données de la base à migrer de l'instance d'origine (primaire) sont répliquées de façon logique sur l'instance de destination (réplicat).
+ +----- +### Réplication des schémas + +
+ + * Récupération et création des objets globaux (utilisateurs, tablespaces) + * utiliser `pg_dumpall -g` pour générer le script + * Récupération et création des objets des bases à répliquer + * utiliser `pg_dump --schema-only` pour générer le script +
+ +
+Avant de lancer la réplication logique entre les 2 instances, il faut dupliquer les objets globaux (utilisateurs, rôles, groupes, tablespaces, ...) sur l'instance de destination (réplicat). Il faut également dupliquer le schéma des bases de données à répliquer sur l'instance de destination. + +Pour cela, sur l'instance origine (primaire), il suffit de récupérer tous les objets avec les utilitaires `pg_dumpall` ou `pg_dump`. + +Exemple : +```shell +$ pg_dumpall -g > objets_globaux.sql +Et pour chaque base : +$ pg_dump -s ma_base > mabase.sql +``` +Ou plus simplement : +```shell +$ pg_dumpall --schema-only > all.sql +``` +
+ +----- +### Abonnement à la publication + +
+Sur l'instance destination (replicat) + + * Création de l'abonnement + * `CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ...` + * Contrôle de la réplication + * `SELECT * FROM pg_subscription_rel` +
+ +
+Les 2 instances sont prêtes pour commencer la réplication logique des données. + +Pour chaque base de données à répliquer sur l'instance destination (réplicat), il faut créer un abonnement à la publication correspondante sur l'instance origine (primaire). + +Voici un exemple complet : +```sql +CREATE SUBSCRIPTION ma_subscription +CONNEXION 'host=instance_origine port=5432 user=user_repli dbname=ma_base' +PUBLICATIONma_publication; +``` +La création de l'abonnement crée automatiquement un slot de réplication sur l'instance origine (primaire). Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquées sur les tables du réplicat. +On pourrait créer l'abonnement sans copier les données initiales et copier les données initiales dans un second temps avec les commandes suivantes. + +```sql +CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ... WITH copy_data(false); +puis plus tard +ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH copy_data(true); +``` + +La réplication initiale peut-être longue suivant la volumétrie de la base à répliquer. Pour surveiller l'avancement de la réplication et vérifier si elle est terminée, la fonction suivante ne doit renvoyer aucune ligne. Tant qu'il y a des lignes affichées, c'est que la réplication initiale n'est pas terminée. Le processus de réplication initiale ne bloque en aucun cas la production. + +```sqll +SELECT * FROM pg_subscription_rel WHERE srsubstate <> 'r'; +``` + +
+ +----- +### La bascule sur l'instance répliquée + +
+ +![](medias/miseenplace_3.png) +
+ +
+L'instance destination (réplicat) est maintenant la réplique logique (données dans les tables) exacte de l'instance origine (primaire). + +Il reste 2 étapes avant de basculer les applications sur la nouvelle instance : + + * Récupérer les paramètres des séquences car elles ne sont pas mises à jour par la réplication logique. Si on oublie cette étape, on aura des erreurs de duplication de clés (primaire notamment) lors de l’insertion de nouveaux enregistrements. + * Arrêter l'abonnement de la réplication logique pour éviter tout problème d'insertion ou de modification de données venant de la publication (sur l'instance origine (primaire)). + +
+ +----- + +
+ + * Sur l'instance origine (primaire) + * Arrêt des connexions applicatives (par le `pg_hba.conf` par exemple) + * Récupération des paramètres des séquences + * Ne pas oublier : les séquences ne sont pas répliquées ! + * Création d'un script de génération des séquences + * Sur l'instance destination (réplicat) + * Modification des paramètres des séquences + * Rejeu du script généré + * Suppression de l'abonnement + * `DROP SUBSCRIPTION ...` +
+ +
+La réplication intiale étant terminée, les 2 instances sont maintenant une copie conforme au niveaux des données dans les tables. + +Pour effectuer la bascule de la production sur la nouvelle instance de version supérieure, il reste 3 actions à effectuer. Ces actions sont très rapides et sont effectuées pendant la coupure de production. + + * Action 1 : Mettre l'instance orgine (primaire) en maintenance. Par exemple en empéchant toute connexion des applications en modifiant les règles dans le fichier `pg_hba.conf`. + * Action 2 : Récupérer les paramètres des séquences sur l'instance orgine (primaire) et les appliquer immédiatement sur l'instance destination (réplicat). + * Action 3 : Supprimer l'abonnement pour éviter toute copie de données intempestives de l'instance origine (primaire), si elle devait être alimentée par une application. + +Pour récupérer les séquences un petit script permet de lister et de préparer les ordres SQL. +```sql +SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' +|| last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' +FROM pg_class c + INNER JOIN pg_namespace n + ON c.relnamespace = n.oid +WHERE c.relkind='S' \gexec +``` +
+ +----- +## Supervision + +
+ + * Contrôle de la réplication initiale + * `SELECT * FROM pg_subscription_rel` + * Contrôle de la réplication + * `SELECT * FROM pg_stat_replication` + * Contrôle de l'abonnement + * `SELECT * FROM pg_stat_subscription` +
+ +
+Comme vu précédemment la vue `pg_subscription_rel` permet de connaître l'état de chaque relation répliquée lors de la création d'un abonnement ou la modification d'un abonnement. + +La vue `pg_stat_replication` permet de contrôler le bon déroulement de la réplication logique et notamment permet d'indiquer un éventuel retard dans la réplication. + +L’état des abonnements est disponible sur l'instance destination à partir de la vue `pg_stat_subscription` : + +```sql +b1=# SELECT * FROM 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 10:36:13.315798+01 +last_msg_receipt_time | 2017-12-20 10:36:13.315849+01 +latest_end_lsn | 0/168A748 +latest_end_time | 2017-12-20 10:36:13.315798+01 +``` +
+----- +\newpage + +## Atelier (Enoncé) + +
+ +
+**But :** Migrer une instance de PostgreSQL de la version 11 à la version 13 grâce à la réplication logique native de PostgreSQL. +Dans le TP : l'instance PostgreSQL en version 11 sera appelée **instance primaire** et l'instance PostgreSQL en version 13 sera appelée **instance répliquée**. +
+### Installation des binaires PostgreSQL + + +
+**But** : Installer les versions 11 et 13 de PostgreSQL +
+**Installation** + +> Installer les paquets de PostgreSQL11 et de PostgreSQL13 . +> Installer les paquets `wget` pour télécharger les exemples. + +**Création des instances** + +> Créer les 2 instances en activant les sommes de contrôle (`checksums`). + +### Installation et configuration du primaire + +
+**But :** Configurer et peupler l’instance primaire (v11). +
+> Démarrer l'instance PostgreSQL primaire (v11) (via la commande `pg_ctl`). + +> Télécharger et restaurer les bases exemples **cave** et **magasin** +> Liens de téléchargement : https://dali.bo/tp_cave et https://dali.bo/tp_magasin + + + +### Mise en réplication logique des bases de l'instance primaire +
+**But : ** Préparer l'instance primaire (v11) pour qu'elle accepte la réplication logique et préparer les scripts de création des bases et objets à répliquer. +
+> Configurer l'instance primaire (v11) pour la préparer à la réplication logique. + +> Configurer l'instance répliquée (v13) pour qu'elle écoute sur le port 5433. + +> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v11). + +> Créer les bases et objets globaux sur l'instance répliquée (v13). + +> Mettre en place la publication de toutes les tables des bases **cave** et **magasin**. + +> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v13). + + + +### Réplication des bases sur l’instance répliquée +
+**But :** Configurer la réplication sur l'instance répliquée et lancer la réplication initiale des données. +
+> Mettre en place les abonnements aux publications des bases **cave** et **magasin**. + +> Surveiller le bon déroulement de la réplication initiale. + + + +### "Promotion" de l'instance répliquée +
+**But :** Finaliser la bascule des instances. +
+> Mettre à jour les séquences de l'instance répliquée (v13). + +> Nettoyer les abonnements de l'instance répliquée (v13) . + +> Nettoyer les publications (si besoin) de l’instance primaire (v11). + +Pour aller plus loin + +On peut mettre en place une SWITCHOVER des 2 instances, qui permet de pouvoir faire une retour arrière sur l’instance sans perdre les données crées sur la nouvelle instance. + +Pour cela, avant de .... + + +
+----- +\newpage + +## Atelier (solutions) + + +
+### Installation des binaires PostgreSQL + + + +**Installation** + +Les installations des paquets et l’initialisation des instances se fait sous le compte ou le sudo **root**. + +```shell +$ sudo -i +``` + +> Installer les paquets de PostgreSQL11 et de PostgreSQL13 . + +Il faut tout d'abord installer les dépôts communautaires. +```shell +$ yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/ \ +EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm +``` +On peut maintenant installer les dernières versions des paquets pour les versions majeures 11 et 13 de PostgreSQL, via la commande `yum` sous Centos (ici dans le TP) ou `apt` sous Debian. + +```shell +$ yum install -y postgresql11-server postgresql13-server +``` + +> Installer les paquets `wget` pour télécharger les exemples. + +```shell +$ yum install -y wget +``` + +**Création des instances** + +> Créer les 2 instances en activant les sommes de contrôle (`checksums`). + +Pour activer les sommes de contrôle, on utilise la variable `PGSETUP_INITDB_OPTIONS`. + +Rappel : pour les versions de PostgreSQL inférieures à 12, l'activation des sommes de contrôle se fait à l'initialisation de l'instance. A partir de la version 12, elles peuvent être activées sur l’instance arrêtée par la commande : `pg_checksum --enable $PGDATA`. + +```shell +$ export PGSETUP_INITDB_OPTIONS="--data-checksums" +``` +Création de l’instance en version 11. +```shell +$ /usr/pgsql-11/bin/postgresql-11-setup initdb +``` +Création de l’instance en version 13. +```shell +$ /usr/pgsql-13/bin/postgresql-13-setup initdb +``` + +### Installation et configuration de l’instance en version 11 à migrer + +La suite du TP se fera sous l'utilisateur système `postgres`. +```shell +$ sudo -iu postgres +``` + +> Démarrer l'instance PostgreSQL primaire (v11) (via la commande `pg_ctl`). +```shell +$ /usr/pgsql-11/bin/pg_ctl start -D /var/lib/pgsql/11/data/ +``` +> Télécharger et restaurer les bases exemples **cave** et **magasin** +> Liens de téléchargement : https://dali.bo/tp_cave et https://dali.bo/tp_magasin + +On utilise l'utilitaire `wget` pour télécharger les dumps des bases.. +```shell +$ wget https://dali.bo/tp_cave -O ~/tp_cave.dump +$ wget https://dali.bo/tp_magasin -O ~/tp_magasin.dump +``` +La restauration des dumps sur l'instance primaire (v11) se fait via la commande `pg_restore`. +On crée d'abord les utilisateurs **caviste** et **magasinier** qui seront propriétaires des bases, puis on crée les bases **cave** et **magasin**, et enfin on restaure les dumps dans leurs bases respectives. + +Pour la base **cave** : +```shell +$ psql -c "SET password_encryption = 'scram-sha-256'; \ +CREATE ROLE caviste LOGIN PASSWORD 'caviste';" +$ psql -c "CREATE DATABASE cave OWNER caviste;" +$ pg_restore -d cave tp_cave.dump +``` + +Pour la base **magasin** : +```shell +$ psql -c "SET password_encryption = 'scram-sha-256'; \ +CREATE ROLE magasinier LOGIN PASSWORD 'magasinier';" +$ psql -c "CREATE DATABASE magasin OWNER magasinier;" +$ pg_restore -d magasin tp_magasin.dump +``` + +**Notre instance PostgreSQL version 11 est prête.** + +### Mise en réplication logique des bases de l'instance + +> Configurer l'instance primaire (v11) pour la préparer à la réplication logique. + +Le paramètre `wal_level` de l'instance primaire (v11) est : `replica`. Les `WAL` contiennent des informations pour la réplication physique, mais pas assez d'informations pour la réplication logique. Il faut donc élever la valeur de `wal_level` à `logical`. +```shell +$ psql -c "SHOW wal_level"; + wal_level +----------- + replica +``` +Le paramètre est modifier via la commande SQL `ALTER SYSTEM`. On peut également le modifier dans le fichier `postgresql.conf` +```shell +$ psql -c "ALTER SYSTEM SET wal_level TO 'logical';" +``` +Le changement de ce paramètre induit un redémarrage de l'instance pour être pris en compte. +```shell +$ /usr/pgsql-11/bin/pg_ctl restart -D /var/lib/pgsql/11/data/ +``` +On peut vérifier le bon paramétrage une fois l'instance redémarrée. +```shell +$ psql -c "SHOW wal_level"; + wal_level +----------- + logical +``` + +> Configurer l'instance répliquée (v13) pour qu'elle écoute sur le port 5433. + +Éditer le fichier de configuration `/var/lib/pgsql/13/data/postgresql.conf` et modifier le numéro de port (ne pas oublier de dé-commenter la ligne). + +Ou utiliser `sed` comme suit : + +```shell +$ sed -i "s/#port = 5432/port = 5433/" /var/lib/pgsql/13/data/postgresql.conf +``` +Démarrer l'instance répliquée (v13). +```shell +$ /usr/pgsql-13/bin/pg_ctl start -D /var/lib/pgsql/13/data/ +``` + +> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v11). + +On utilise l'utilitaire `pg_dumpall` avec l'option `--schema-only` qui va générer l'intégralité des schémas des bases, des utilisateurs, et des tablespaces de l'instance. Le script généré est au format SQL. +```shell +$ pg_dumpall --schema-only > ~/schema_replication_logique.sql +``` +Modifier le fichier si besoin notamment pour corriger les chemins des tablespaces qui seront peut-être différents sur la nouvelle instance. + +> Créer les bases et objets globaux sur l'instance répliquée (v13). + +On importe le script généré ci-dessus sur l'instance répliquée. +```shell +$ psql -p5433 -f ~/schema_replication_logique.sql +``` + +> Mettre en place la publication de toutes les tables des bases **cave** et **magasin**. + +Pour initialiser la réplication logique, il faut tout d'abord créer une publication pour toutes les tables de chaque base de l'instance que l'ont souhaite répliquer. On utilise l'ordre SQL `CREATE PUBLICATION`. +```shell +$ psql -d cave -c "CREATE PUBLICATION maj_cave_publication FOR ALL TABLES;" + +$ psql -d magasin -c "CREATE PUBLICATION maj_magasin_publication FOR ALL TABLES;" +``` + +> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v13) + +L'instance répliquée (v13) va se connecter à l'instance primaire (v11) à l'aide d'un slot de réplication. Pour cela il faut donner les droits de connexions entre les 2 instances. +On va tout d'abord créer un utilisateur pour cette réplication. +```shell +$ psql -c "SET password_encryption ='scram-sha-256'; \ +CREATE ROLE repliusr LOGIN REPLICATION SUPERUSER PASSWORD 'repliusr';" +``` + +**Note :** Dans notre exemple, on donne à l'utilisateur le rôle `SUPERUSER`, ce n'est pas absolument nécessaire. Si l'utilisateur de réplication n'a pas les droits `SUPERUSER`, il faudra lui donner l'accès en lecture à toutes les tables de toutes les bases à répliquer. +*Exemple :* + +```sql +GRANT SELECT ON ALL TABLES IN SCHEMA public TO repliusr; +``` + +*A répéter pour tous les schémas de toutes les bases à répliquer.* + +Éditer le fichier de configuration de la sécurité `/var/lib/pgsql/11/data/pg_hba.conf` et ajouter les lignes suivantes en début de fichier. + +```ini +host all repliusr 127.0.0.1/32 scram-sha-256 +host all repliusr ::1/128 scram-sha-256 +``` +Ne pas oublier de recharger la configuration, action nécessaire après toute modfication du fichier `pg_hba.conf`. +```shell +$ psql -c "select pg_reload_conf();" +``` + +Sur le serveur hébergeant l'instance répliquée (v13), il faut également stocker les informations de connexions dans le fichier `.pgpass` pour que le processus de réplication puisse s'authentifier sans demander de mot de passe. +Dans notre TP, c'est le même serveur qui héberge les 2 instances. + +```shell +$ echo "localhost:5432:*:repliusr:repliusr" >> ~/.pgpass +$ chmod 600 ~/.pgpass +``` + +### Réplication des bases sur l’instance répliquée (v13) + +> Mettre en place les abonnements aux publications des bases **cave** et **magasin**. + +Pour finaliser la réplication logique, il faut maintenant abonner notre réplicat (v13) aux publications de notre instance primaire (v11). On utilise l'ordre SQL `CREATE SUBSCRIPTION` avec les indications de connexion à l'instance primaire, ainsi que le nom de la publication à laquelle on veut s'abonner. + +Pour la base **cave** : +```shell +$ psql -p5433 -d cave -c "CREATE SUBSCRIPTION maj_cave_subscription \ +CONNECTION 'host=localhost port=5432 user=repliusr dbname=cave' \ +PUBLICATION maj_cave_publication" +``` +Pour la base **magasin** : +```shell +$ psql -p5433 -d magasin -c "CREATE SUBSCRIPTION maj_magasin_subscription \ +CONNECTION 'host=localhost port=5432 user=repliusr dbname=magasin' \ +PUBLICATION maj_magasin_publication" +``` + +Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquée sur les tables du réplicat. +On pourrait créer l'abonnement sans copier les données initiales et copier les données initiales dans un second temps avec les commandes suivantes. +```sql +CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ... WITH copy_data(false); +-- puis +ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH copy_data(true); +``` + +> Surveiller le bon déroulement de la réplication initiale. + +Afin de vérifier si la réplication initiale est bien terminée, la fonction suivante ne doit renvoyer aucune ligne. +```shell +$ psql -p5433 -d magasin \ +-c "SELECT * FROM pg_subscription_rel WHERE srsubstate <> 'r';" +``` + +### "Promotion" de l'instance répliquée + +>Mettre à jour les séquences de l'instance répliquée (v13). + +La réplication logique ne réplique pas l'état des séquences. Si des enregistrementes ont été insérés dans l'instance primaire (v11) après avoir exporté le schéma (voir plus haut), alors les numéros des séquences entre le primaire et le réplicat ne sont plus en phase. +Pour cela avant d'ouvrir les connexions à l'applicatif, il est impératif de mettre à jour les séquences sur l'instance répliquée (v13). + +Script de récupération des séquences sur le primaire (v11). + +Pour la base **cave**. +```shell +$ psql cave -t -o ~/maj_sequences_cave.sql +``` +```sql +SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' +|| last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' +FROM pg_class c + INNER JOIN pg_namespace n + ON c.relnamespace = n.oid +WHERE c.relkind='S' \gexec +``` +Pour la base **magasin**. +```shell +$ psql magasin -t -o ~/maj_sequences_magasin.sql +``` +```sql +SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' +|| last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' +FROM pg_class c + INNER JOIN pg_namespace n + ON c.relnamespace = n.oid +WHERE c.relkind='S' \gexec +``` + +Les séquences sont à réinitialiser sur l'instance répliquée (v13), afin d'éviter tout risque d'erreur du type `duplicated key` lors des opérations d'ajout d'enregistrements dans les tables. +```shell +$ psql -p5433 cave -f ~/maj_sequences_cave.sql +$ psql -p5433 magasin -f ~/maj_sequences_magasin.sql +``` + +> Nettoyer les abonnements de l'instance répliquée (v13) . + +Penser à supprimer la subscription surtout si l'ancienne production se trouverait redémarrée. +```shell +$ psql -p5433 cave -c "DROP SUBSCRIPTION maj_cave_subscription;" +$ psql -p5433 magasin -c "DROP SUBSCRIPTION maj_magasin_subscription;" +``` + +> Nettoyer les publications (si besoin) de l’instance primaire (v11). + +Les publications peuvent être supprimées sur l'ancien si elles ne servent plus : attention si vous avez d'autres abonnés sur ces publications, elle ne doit pas être supprimée (un. +```shell +$ psql cave -c "DROP PUBLICATION maj_cave_publication;" +$ psql magasin -c "DROP PUBLICATION maj_magasin_publication;" +``` + +
diff --git a/fr/atelier-maj-repli-logique/medias/cas_repli_1.png b/fr/atelier-maj-repli-logique/medias/cas_repli_1.png new file mode 100644 index 0000000000000000000000000000000000000000..2d256bd9e35504d3e2f020e47f0800a475bb46f0 GIT binary patch literal 18446 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%0A>jttdeDt}QOM9jyIs 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 NUW>|#6bk8l{%<8$XFC7@ literal 0 HcmV?d00001 diff --git a/fr/atelier-maj-repli-logique/medias/common-postgresql_logo.png b/fr/atelier-maj-repli-logique/medias/common-postgresql_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..94612cfef332ce82c70e7da22ce1ebee96805f4d GIT binary patch literal 50279 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 gNtnPZu-d&r&I;c9>kU+8}PAK2We;{X5v literal 0 HcmV?d00001 diff --git a/fr/atelier-maj-repli-logique/medias/miseenplace_1.png b/fr/atelier-maj-repli-logique/medias/miseenplace_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c55ff69acee691063390c9bc8eafee2164d9b2ef GIT binary patch literal 8720 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
  • Hg@49=e!_H1lT!3yREa?$G-JAVz?5E;) zTA8`n5l(=qDXkvyXH;Gjv~l-*HMhuz@#i~#t6sN$%9sH;D)Qm%$Or+rsa{T#L&*sS z0te~<5sin7OBL1G)dfhMhoJCkmRF3|dtY#Yub^bIMxj1>v;ZhzQURyDz(l+oc!5z5 z&3!cg9~wErq7n}o8JWqSRs`c^M)usdeJ}qQ1Db08^i&hUl@kg)my?KyNW1cV6!I<6 z+x#~Ypvwfz;83N7GHTJw({>y&DtdZUW@hI9>^7TkcJ1$J*n7G;U<*#(t-=@~^l=Sq zX?fXkr3WwmsJ*QX_t~>31cC{0q3xzFv$Y@5bxVnXfWb{?hUBl@R`}qxAD?;MVd{cc zg(j6w`2XnQ`&_RQ6BC)3m|BK%V-uI^SgIi17g;acC)-^OV+&?`0{6g$j2%sSFfI_yJlCs|C$~C@*2cU*cBB@MKpT1h8 zbOneDjiK$6Vdhxyz(VKxv^$cF7PU4rGqck^^B&nEtqtm3pgOaPSikh`fxF^mj?)!2bn+gyv@e literal 0 HcmV?d00001 diff --git a/fr/atelier-maj-repli-logique/medias/miseenplace_2.png b/fr/atelier-maj-repli-logique/medias/miseenplace_2.png new file mode 100644 index 0000000000000000000000000000000000000000..90505592e9cf45fba2220c6221d13043b9db53bb GIT binary patch literal 14089 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 SHt>Jj5K`iDVud1ay#Fu00izWF literal 0 HcmV?d00001 diff --git a/fr/atelier-maj-repli-logique/medias/miseenplace_3.png b/fr/atelier-maj-repli-logique/medias/miseenplace_3.png new file mode 100644 index 0000000000000000000000000000000000000000..980d99587fc223037a16e334dc8ec231f8047143 GIT binary patch literal 15773 zcmc)xWmJ{X+64@6LAtvn6+yZ|q$C7Ey1S%Hx>H(0q@_W+yBi5<>F#jT-SDn`&KcwR z@%{OJy)R?1fxFhaS6tV;=A48n$Vpzj|Ge)sRkh3Vb0`iXjR>0e;qr@Z=pEGf)Tb(r}5`UBN*VzekNrnJ^n z>AU+wt{bedCk$E_;-5oVCP&$qi9LaN zH(wvWD;)lq?un3j9q^Oi=Np0mrHD+VUn-EOalSuXKe@WGckMNvq*(oG= z^22o!wZ+kxPYOQ=KO=UF?}xR2cuW5lBzc{bZO3`7ea79{tMH9Qyje#NI0qObNvl*d ztG2y;`1hvmPhToo{Q(kt-u-+Z)j7!WoY6p^vvW(1L>Z3sBH8;O z`d)>BJl8=Cxub?Le)f$4GX!%TL2sVA??T@SI=Odf2twlHFH*FhGmwQD8>*{fH0d7j zXZ^)Qu_pXj9L_Es(Q@ka*@2?FAg|9L{3DHH0?Ax;T#q;F3K}L}G$W0K3_xW8S{9+7hFWf)1NiS}QAWa-VLa&{o23|={ofyAQAQy8E_)ciotos_BqRF{CMCgu`!trBcy{)3fsfsNl zarCTOO4dHY4*sa~<+i#Fb5xGxg^jxaa@vaLS|-zH40xvs>vg`lkXMdX)PM2@37UO_ zT@OuUdZY!9ws)>9{{ej(O z>_F#B@ap~iQiD)TR zjZ3}d8g+>XXGyY{piz3k$-rphWN*64$jDTeoZr`nM;TH&g2~!E11A`m{@ek>4mfk3 z{q%)rKlsK5mAcSVg}Yuw9PCVej0?n4Fx^I>NBa53BJ7S2)fd;3DK6nOu3&n^Zi5U# z!zo#062&g-a9C#mH`U5n!Qe;F);m-q%MB8)+^&Jk*EWUweA!MLWxvCHTNhdbpauZGt_(==Ju^j5*T;rFb39}_aXGtykmVDi{=i*U#G zLyy-ZE6Gj=8~J(LhX2LV=*Vg!P5$f@3iuSvm#sI;98o+JlC2*6{7~=)@O1;-Qb_ zbdNJsYxh@3@OV!M9dfzw<=N+j5C|3IqxgFjx733rcMZIqTi#>4IB&=IbNB=j1)14? zYF58%vsFqJ>Nm2onQcp_br}sVN*ih}G>S_5E+&f}EOKd8zBgr>>t-@!1{BcKWKtc5 z?hl?lzUO>}O(ilt@X*M@GW?mt{q?}v@aMy1_vaDph@!~UEn}in7*v7SG{X4MKXE-z%7c0FeSXdz`DP*5MeHyE^Qun&q zN~C9Ij=wttO<=v?^Rr!QqJHxRrLwXT)wivqLxhi?|Bs30iq{#2%l>TV(&h1SM~P-N zc=qkDygZ}H0!4ZzCY5VP93@Ink#MI$r%|LiwTUlI5?e@2Z12GF#1SgNU7w;d`e^lL-mzT4W33}A@)Rb!1SJl}p{4u#%KPvwt`f$26 zhz^1E0}T_?G&neTe`_#t@xjEz1RVl9;(d2%Qdd`3qTlYbe}8kfDB$n!Z@t+cV|{!6 zuf+4}aA&Y$p+333 zp4Vz34`X6#%H;C$(t4&$H-f!)x>TF)#N$_fel@q%G#e2S(c#I*j~|By2fx+YF8zdk z%ck%|3i{k@7%kP=t&A)#E+%DVQ9C*~7zsb!JGPe3C9xaNK0T~FRi5pPDi_3l0IPKV z(ev)o#$|7sIm|-%{uq8@X2vW&K0eat!Aj|y!qfSLd~$9sZE-kRT>ib~g_K(-PKk4gdkn?@icS`(~;uM#Z#9b?ZG2jGWJT~)O32|{fEP5^di%Uz%v9WlJ%*=q zT-;-0W@h$^me#)B^Ku^rj6>Mnw{PFAqE zw6wHO2Nq1ZA-5ZS(e~>-C|~k5OaJ+hGdqM zpsSbZbb@hd=mVpdRZxHoc09xnj7}GbdSKb~4-J)6lM8yBi+Fi?mF|oV5C8T&Y7GJL zVfFVnBJ-&t0tgi~^)r!+l-JnEP@TH!YEDcL1W!*Lc6U`;d$1@3I&vhV8<-JAxo|F4 z@-9{qS@n&skJs2ZIlGfN%?xa9mw#>bi~eiY2e(0biPcIp{6P$szAx3Ngp-hv;QO)) z;eE=JO~Iz1h-!8{GP>NKqo=3$Yi}2JeFD4tWPmP%ikq7tCMHIs+7x4ZG(&%BAyumubP1tu#iYf?%|PE{4IqM~B|;GmebHIwN`Dhh=D&6{Tm7mkcC zU&4bk;Q8M*Ezzd8M0s^~?jEw2$&poiD5H0-J4}x$v92^|6al}%)Z-(>HavE4Y6%7pyS|Q@P zjSfLzn?`^mY>tkO+dDgbs=X3>ua^leCZM80N`EybeN|_C85tRqLGs$fVKDN&xw(n- z!1{%wpT3%bf`R+gNV6gKGqh`#*4D*?bp7Pt@9e|KW(Wef*F}6nX6psx$b+`G4m#El)toOF%%#%5DMC z_#TPoMwIji>!PHEVscT6xKy=;%+r*bEUBB8HhRi-u;G&fJfuQ8coXd^#)}%G-iWfG zMmPKeJl%S3TpE?|Zao9_~(JtkJggUb+$BPW!Vi z?_YE##T7w;*cQRE6Uz#T?lQV$TLi5l(sBYyRpm5yQ}BgnHQaT6v9)BW){BM~(~6B4 zuL7lNSsXC0o~Ddliz;aUNM^C*EY4uX{O~4t^Y+9|@mL%xz*E}XG0;mcH*ITfGOISg z{3xAZ>pz*u&5kWODgm-OMz}!O-t{7^zq8=mtgA~X9_VvJie#ur`GDmudt_Fj%_RC z=jd;W%lARNt&y^#4>I}DN+fdazHo26C^JpXfn%f=r#6?-?JVe!4n4IvOW+S`!d3K- z$KJ|Rpp%wFP!q)u5lt&VC(uBN5w^i}W{4{y2ES9EifcnH!%<5Dxzc#-3Y812Ad3DM zrg8$|;5kxX=_kW_Gr^-Vz)O%yPQw+$2CJ|`x+a1rgr7i~JFWy_`Z~ffG#^}}^|fx& zJs3R6{0cPA9}OBeXGC@G@>DUPod*cjJQ51Gr}|4!Hilo`*?$TnZJ0cMQB?G&e2Q2a zYOWUS&SNrwS0Ui~`|M$DC_eNTAwvbOEXb%*7@#}jujXGsRp@CsvOu#x z{p%(_Rx9|&7reAtR?1hPa}YyN%VwdUM2X=9cdKSA(22h%RW@+0vKJ!)2j0R)QuK`? zJ@`FarzTfUMRXf(Pq^6}v_LABQa|}-GVBlNdp{Xy%`yPBM4SRVOOX@wYB*~+OD;$$ zI{`K}6JrVd@+Wa&pPNABB=Ee+nVZk4(~In7^re0 zHhrkzs{Z{r`;=MT2p`NBQA}{S&XJzKu4DNe{OIa7WMYLU&t!HMwJa>|V2DC3fo3(7 zU~9`GW&UbGhBSOxp}eECP5%d<=wOHmx#bVO_Ub_d5u*l&Kx1m9aT57Hp7hPxJq4yQ zdyio%oc1p*P|NhwZ`_bC4n^g|75^-3tkt7zv&)4C$GK3zP2Wni_qh#%0`3e~cKpA;!JD1Zw$+x|{I?~`An-T!yw*%zsgnrP zq_WFV;6%w=jN$Ujs_N>P*w~jRcEe9Q+uL1#|Kd(hPgm5{1%sS$_4Kpe*@^4!rCNH#evBO@0{M=T9N%(Xp^Vw!FN&J6Ra3lUPolds7}$!~J};j5d4W z*PDtA0o5s4n&Hf01U2YRxpNrLi&MfOZ%#`B~7{c`C|0=G)zqB z02Hd+o?(%2h##z6x72t_&65TM>`N}z=w*0gret-i%rekm%_|w?`Ybzv{>nUwg-(9G zYYby{avB32t{~-;3X&~`A>-Cg--iqJ)-x>)4XOK@s>;g3i?hMrUc|R=-_|~g3$OIp z&6w?uWxR_jT$F)NLQ6*9x%V50?Q+l1kje?6+U1pa$fgz5Dv(I9+^!i+(rdU;*) zZUcZ0`J8sKjf{+-sb-4}_Q#i(y#TNq+Sp(K1lcGkY>W=t2nCg*0(}oi>wBrLpq=ZP z_Q#;PYO}$E8#0-t_SCR-`sxl3!9Cm;rMLaev*7WGJ>#sZ!VB$U{MB7usE z3Zh+SUFe*VpHByCW@F>4%fbAc8uBXa))UbzY&yBr0_Uf{xiXbL4<5UFdyF;YMPBWp zx60!F+#Bu;mwk^&YNmCvs4mc*aMc}q=$mF&s=dz_()3M!x5sN@Ue{|O4PG}@J?8+i zFlkgk5)u+n-Syo20W!oAzV};QH3<9naC;%9p+U^=qB1l<^A|O{E=ORE%c@K?J=&aQ z4z;9Lr(;IlfFOw9?*r1i3&-EZSDP1+@VKwi;*qFknRKCi&LDgE=ujvBG z&4T7*R5}e`vgQVJ1LzgwkVcQbXdhz`Xgsy~lFFY_eq5ZHTYNTw#1enY2i^Je@~l=L zU-3H{sPET*PYG|xr3-{zEqj)K98{9@eY~M-X=!O#pr)qQX!v3nn;?OpnEeSnYj54? z4zsuU`s1e@pE8}uw#>v9)B;c>eQ|OUS5%yGj-Dyi4#~{S{J<=R2MY9bZB{%yJisz^ z&CfR}4rYRW5on^8aEHMLeaos5EQ{JmcM(rs*P6+hzB96!XAqN{n|>iO_zg^Q10%+} zIkmg1BS~@b=a5XhmA31xM19f;^vJcfwP#rhp^J+;aR~`s)6<0Ti0I#M{-;13h?lhOELu!Zft2TgxHQOCKHprD{EK0VyuLz9)yZtm_JpNRC2 zg2Abt3+9wY8fP?e@&+c&50VYo@c5A#1}-tDc}nWH5cP3tuSZs<*qwx_-QS zlSg%j!-7=$F#raJnelmM_D`n@BRG`m0ElK~ci z926@tW}K6V#^_+X#uiXddJX(TSL{*;-7Nno**@84xk`18wTx^`MrNx8?R=1$YpovX z(`oe}09z==Re7=t&>6JLyFZm&j^dD=z-8d-{uB{;vrk9S9ob~WY?kd7QwP234~MN}K+JfgO3&C>Xy z;sl+K0w%<{;g?({%~8)i%$0=!QxU>X^?*L<_w0dfpwiMxkcWp5d_nxGsyMukJCTwE zJ$cfFyo(~X2V`w+S%hvj@ggXNDFD9)fsm1r_4KNxRj?0KzJo(NpZLiso_4=;%rl#d z&{P%TJ;^oycT`n&ty#b4V{_n9<=wwoQeTXJ|Ng;>`Kqd-=n!rWjxN9lReo6$t+AYv z)*QC30qm3^sQ#}3<)WygGbCGIT`l(M6FR@^VZ`Xt?dn6B%cA$ZQ?U7;^t66{YC=EK zHpXB$U6=J{ePZL5qaE%Ub%HojsK^7tWLLO!2`I{8lkfH(9Uc96Eril&xQ)?N=6Gi=y?R|txl$F#F=#>gbK`T@lh?)tDeR8quh zWm52Ma@nC&2%Z}ZljHW#dnF~M(mnu8I#*UGDZP%Lfx&7or;44H!Ca4?fN)t(j9P=FlGpr-u%vE zD=uFziSMR0Gk8`{`R5_NL-3gB$94F*IBNCxRspFf3K7M_)u7cZ^Mi!MS|6paxQdEO z>)`%)4$}U?fuWsUG+>0Y05b|BOF(IF_0Z~mh6rkRTwiy0_XgLa^d1-$y5}ti=m}Vh zIg;u`&vVnLNxi5EeFaPAjb^qLkhoaE=%tjgQ|DVev^4G&(=%W>i#RR146`d(QP!u$ z#P|b#ikgN-6e`bSVsCHX*0=6hla#GJopb++M_}0cqu4IjzuXX?&Bkb ziiW1Bp%EGo00+Wl_J4UMHV%$}%1ZXD^1{M5{7$=mWxCB>BO{ngP0nA_(#WlCZ1%iu zHCd92G41O3m1aPTiCFHwhpKa)RR@DW|@`K0UU@TYV0)E*2 z^8dS^9O`!)Irk=-U9)zrdr74T72N-O?0@%%fHy@eIGs#o7oS=ip2q)!2|GLf-?P1e z{F(D`mX22^#oZ~TAL9u2@pr>>Z8AKaHS{Ai{QsWI)sfdt zhf=^hhlr-Lnp|P(MN=0snT@1&hT^;&D^g`7CL!tk{TpG$_eqd}k+ISJ^z4kbw?bv} zVwMbV7cjU%B2*p4>gAiKi-Gh%dV}~OHBi&&$4;{GGI@Plt?2>0Q2i$Y>9Z}zUQLTf ztDf>FX(M4DSaBfimZPQvubU3IWn_7I`5K!ALO`?iW{HKYZfyk-Fsd1B{fS@n`mcWR z{oX-Myn@#St<`a71Q{JY(BJ=kb$TMU$ymb@EBBjhzxmVvbKS``v*eS+PSjWGK z^gH_ckU$+n+~99olBqA6vM=-fR|9Knba;4pbYeCL zs8&h{b_WRJck9hjtgWpptY%n1mDD{xj`RBUYZ!?Oup>n3(B};+E37Twr#tYNirW7Uo#cjf{)RWk3 z!PftfORXuoqKRh17wSKM{=mef>zkXk{0tvaEiKZa;b9oi0)D(nW9Mw8@fw)J&CSm} zy}d9#w@)2O`uS}J7RR`EFCE}NzXBFj=x(3W>+YbQ&-<23Nm=;>KzuN)GmUb4Gv$3C zBOdS1ak_bW8iPRZ1_~93!N0$`d|uaVfZYyhXyDu2*?GyurGmrCOkI0SGx_WU&JxL1 z%NVtw7A>2+fQo?*>}D~*)F-g$hHKZ`!ooTbdcHV1cIV0@LLkiAb>bj9QDY+;0BPtU zVrpvYx9f^`$XfS*#y-XP>4T-r5;SO~Da=Nh?&Ygj&q0zeC@JabjU>Y%CPseu?%nyp z0+Gz}VTkMS!WXPCRwmJ(@ff|)lvrSW0ANnCwY7zej4T3P#n9Ne+xyL=NoN4UV!~~e z$)JLkR`~U`TMG!s%`OLBfMf3tD(_XZi>UMBX_=dt@gj zCd7d5m39D~uLblXfbtL#3yU|l%PnC)e&C|N;8QTVv9-0mXcL06yk4UYm;OVR9#in5 zT$CJg{%LrX@S4_I(%oSqU00@OD-*JryA+$m%X&b;f`lNIdTRIX51y^RzU5TrSh$Lw zUKC7lTx@h)tWhh~>I6&xs8oZ2KKl9d=d@^E9-f4T()|38QK36@G)&6(R+ajS#?5nC zr(JJha1cx=pT{}*`!uh~Bw zO6JHygf}P@8j9a813V{&pu!N!5E2!IS*G6}HJrjb!%w;je$X>Aer;@g3z-w0nwx{+ z|J}d2Xv=z4pVq(h?e8jIdk&iN@$nh##eFn?+DCEK|E$Ho|6uyZq7=Hlx(f03_SOM> zcZwRAW2+f1&x#YnGV*5-#Y!yt#i`WZkXxXx8X6e*fkI2`YR-E#vbj!I;ZZ&*6t&=l zY=67qsWy;xy0drN6Fta*9( zZe{!s2;mdV3y=pi8wxNFK|scFyhdrV506avIB%>`7oD0Fmm_jfB#A7YB%S$}Bh z8=e@S4ZZXAGGs?&(v2cy){?RoWc&+uGrR2~-=`EF47>IR9)OZyz;5^7Kkj=2Zl0mq zm*^M8uG()H7iB+vVzc=B3cQ>Kv~mTo86X@SUtDbEZSCxIgTT*gyI8>e1WF3~!^O8R z1U>NS7jfH1qEHd zYK^sg^g-YEA&6QmcomQ`xDw`&zkCEyaq-HR)4cOLscLhv2^kV zHa3x<`f+o2e+GHH-oOGOdIKiNfp8nUfLtIcT&~OfR|L#*2SB6|U=%vKx&l&sRy&?G zG&N;^3uDLSwfTx7|pEo*Q?R2m+^OYBdh^UaKi7K`r zIw?ZW3Pt}Mrs4WyLhPzIVyevY|4J%ofrRRF`;X3gu>l9HgX@*2$B_MfYZyl)Z4<&Z z{IDOdsv??if)=Mf$@2VL-J&rrg~J*PD{SA?+b(_C9it9Y7#$es1QC(er%+Nt!mu}j zM5EG3qEr;f^#}GaxjrXDT;d=+9JR4lJ>IP{S5HF&8E90nCNsP*N&JecZ%ax`Pcm*Y zy0%A{!;1Oq_VySm(ek!ciCA?S{5roP4SLJ8w&zpcdX9V_JS8<=SkIF7l`|=F&npPC zp$qdwg00dM|^HE!I4G+i|u4eIER6e6CJdWltCH zq{ElFnls7)qyeh*OF*6mCNOKmK_1UCo(#^mhx`Bh`QafR3ql&$3H>&O-+)!1qt8|j&w*eA$+WxyS*n|!5lv(1Q;{mRGnz(Z&4{j| zVvgVZET=*k^kZ|vU?%el<32R13bq<)XlRasW{i)I4`Zb)adwNS+t({HGAKcP8J?6x zY&-7{j|6M8(0>`5l9CbtmJJ{mCvk=d&pfUDJ|u!9y>)zzh(!Ss7rN8oBFR6btM2lU zm#)6UXx^>nONeV0SjV}2&5MSSg-BO9yB}G`a`L<8-EVq?N;I3*38h%Jrh}|1IfDj8|XRSr?0opYeXtwkwqkVz1$O^1X|(3v?0%Y`;DLFWEr+ zctuCIaeJ{>8)X|a1^NnsEY#ce^~b!lzdg4=2h_3cfhxgr;4KWRfjVjhlcFcH%7_o8 z$oF=VJJ{S*k^L6Q?mMv~*WM;dO^YLv>Fueo(%NZQ#xsas-_?Nk-28`xVrHd^nd!w_ zX_fu2{P4O0L%*Yc#N?B3ni@Rb-^{jozq>qIi3V-217X+lZ`IIH(dp_p*0v7NL)h}v z3*={YX%F?{amOtw>!Cg}y;%EFm-Au9GuZrsq+m*ThLMB9U{C=I-*nphmR~WgS4T)a z2HwUz1thvuSuYK%Ca~9g(RTx$t_C1(82i~3B1lCp$!xt}0BP~!t;2Il-+TKU3Q8iP z5a9Bl5)@2JQPb26n<>}t2F&8}uqq08|BcyiyY@$z^Z(R*GmA#B<86wEET&(CaVos~ z`EzwS!7jxMMc?@p05#<20b0Hwc<-*X3rA53vs~CCVZQJKv5rNjVXR=s(bcsNcubyU zLN_af0N(Q?7telLAq^9W{v;DJ{OiqyP~O{4TN9HYz#-;wt9^j;hX4$U>W%4M;Ql~l z68!cmH8?nl!vuA@O!pfoIt>5B-LBmIyuCa?v$C=R;1w{I&v@;Ydm>0UkI(-p52Xug zzb{o|(cAYad>d@;ZbEA<{BwL)W_#Xy6+;XSO$X$N%xt)lY`B?v>klzUczQZMt`m8( z$LA$YuQ83$0S_=+VF=&S+6oHI^2tbg2Ej5pd3>$Aq|aI zNDM!UN~^-~o^*DcKinrb2yE>SVHSS~xnC%vlNGJ?L)d$Hfq!^0@xv@im%F>Ko$+VX+Pavxb*O-=3i>Z<%|9y(9O zaQSTHwUD(_QgJu6&!1nId&QN_`uOexi+MU->dGV}Bv}&Q2yrQULH6$kG#wCsYCjN$ zM@4-Akg?K!;{)H@x1B)#fUzSW^1O1s;dX6bY;nf}K8s*bNi#7sv)e5T9R5HD>V1;1 zuMjAtvxohHR@0#beoue$EoU`Gc86f%5n$5dAhnVD2x z_UFVL5uX|?H0h#V8fs6B^4sjb^)F)Af(<+%@VW*DP(YaoAmVBn^Q*SI+?pDEfaAXc z%aB&RZ6wG7Rg+f6*;5m%PNAc0jwo)iHSL&!K?XKAVYFleN3Mn+bT2MPo38 zNHQ{mh`#Fp0_T83Y#c>x;p>3UX^<%zN#VsR*Khw|U_d4M+FQelvT38Q8ma?|>Uu>` zjlKW+DunWdfEyd2LmT!yLtPFasuF)wr)?VD$vhi!m`0PofA@QQxXY3F1}#%lUwg~U zi~%G@+?-d*Nl6{Qe@krh(7slC@Njl?jCI3OR#N%`;%9QA7*}HNeY%qP`x^EVM9hG! zpj`21s!oVSdFUnMfPDb?0KNb<0mMS1p(J*grOg#C#QbyC&DqY3M@wxjH{d`zh>KO9 zGqA8EAhTGUpPxh1%%GEn!1dT0eASo9StS3({qr;Z6f26^Pd>Pet z?8){_nC|a)^LtiWfCi_gq%sg zO=sQG<>cgK(E$wJF>r7Jf&1 z{p6POzrP5krlz=qz?T_+jqs}JvgJCH&Gk?vx)Zv;9|63N0$$e&>w-GKqb8Rjw6x0q z=10>dyt`uJg|cSBw*M1?%=g9MYhU$f5<9$z>U%C=i32RK2H3PZlI~$QMB1Jp*-+qLq3y;Mf3t6#&Xs;1B@DQyAF-INUx^ zl#qEbTc%|?Rq@Xr0b&>AC7FBOCZ~^iJNNt5qsP1BFJXzr^>Fb$h*i^%jt3b(^_5`E z4p`l7_op(jIt&J|0lz?tnhGqZV<6)esTO~aiwo5Exj}$oXxAsdXYg!BJ;+}7Cw(w3 zibBAxgFqix8p*uKH)RuiMu?z5{2+v`-(lc^b+M!`7;MhNTgq-0%AhsOseo2hP1`F% zK-cC2yjj;oKtf#78b_7$#ghRC5)+B^X8h!w8bc0I7X1*q7Hh;O!Mtgsu z9&2YbBc!?coy+0kfH(Cw7=i>K2!_dkQi20eByd1iE8cBy z=$L3j@m_yg1wDEF+JSO5Zt2}CxYljrY-sO)wMBY%M9cpwi|`Qa7cYid$ASG6X5^5b zFD#p69`i5KH{`CLHJR&Ukp;3sFeZ68K*gU;O<}6xHSkBS?(G$i!z&IJmHCYDLMLGh z1enudpwabiVbz(h(Jf00U!1JC3=TT*8|}pAnBR6DYzPA@tK#t2MYPW7PB`uecYr9Z zH0(wMH(|Z#xJud0zH_;y$-4p^(TK)5-qlUpeQU zwKac`P#o)l{gWNIkqPRggnaG}ct8E*3Tqa0J2r^FI!myU$aN#IpPcIa{zJ6paYum} z((kzMpEbBA6t9(5>*^@k6-mbC_J|HK$SV)I+UGZ3Z1*-?(7p*`aQ^l2{oL{}d9J&= z+rwy#Z281t78fhl!P27YBFFGw03*add{`e&De6`Q9Wb=ALIb{hg8GtwmxoJ?ih=cY zb-ln9VPI^W)1_8;&3ADw9N7Q#5}p5PUz@4Cq$jw6F{#SuB_LR%L50j!@%+MJqZb3F zU@A}B!Oqe@?aY2A_lMm023jnV6ohAf^k<TV1D415_&9DN@#WRk%&yPj(b1@^ zBXBMN?BMEVVbHo8^tCh46dkPOXaiAo_>%?VCn?Rii)1O(9v7f87`i|+#&PZ z#-K-m60ox$-8Qz(9vZ7ETNbEe2%V($ph*1Xm(bC90cd2XKD?vVFntgv`#)?mWT?NHrLF4-D5p&r9$~&{GEBiUx>%Kw9z#O@OboGfXlb z^rzdIb~Y=uC3W1%U$I4-LFLc-XD*Zw+AbVbm8A=Kd51VSIdKRH5wjF#SJy;=p#48X z8qi7rV|dT|?j0EbVz^J!sh67ru^t(N-Q8aoegK(Ox%DiZYim$e`9$#gy3OZLZ@y2N zG%A*}yFLdmsCMrxoKB1m_DbmIL6P6UJ3BH`_Hj_5hqwT`y&Tgmh4v8NJUr7;OtQc9 zTGszzv+zP7pg#cXK}Qvz5PCr%zNJdl0!VeBgaG>v@PPXR_Nfu`k^$%mAiM(c)3_@T z1&nNPYpd6#KjX%QBDZ428TXikc&D6y88OgsRo_!*u~@xV!LfX7`Ehy1$jeIv98I-8 zO&{-W^31(hGnd~vXfOuIX-_NbnrjKGzitd^;yK_cifGx1oofDxS+K!$1%=$)1VD{`+DW)mfEL{3hxMK}9swi0kd71!cv$Vq^gJ zUkzDQXH>GSELM3@DPu1F$wI0kFBK8mz&wREM8I%dDcId|?Xt0R`LHa17MX zvC*98C5vwgz<+_^u=NrLJ@Xw)D3x*MgD7DPfy8bm-kr1Q@6 zzP}sa7~lQxj_Vl8=IpcgT5GPkp83pYPD7LxrLZtbF%bv^mW;H73IcJ%8Lmfeqrt!4 zgZ>fl1H(>Q+Yy1l?nM5*5yy;8hCrb4d8lbQy>T~Hhc z)#P6Y__$8qq^g@cvW(NzKFhv^>w6(OEX?5c=^IfuKEngtixis3T`6Ivs_lfxljoGX z2@ztn*s?lfr2-e*Pfl?{uCZuch?D!j8`b*d%b+~>GX7I5sjlB}gzCn?J9gfXmrA>H zHPxP=Ixi-X)oc5Q44rR3y!{r!NXq?*`n8nfEZxhj->aN@cGNh6+++R1LEHm{LuKAh zpI;{zx17Haue4oBIn&nqNOdkc^13*BQ;cKp&XP|lih7Yj<4oI?QZ@U@lgnO5vpHt> z6VsinqlC_Yyi@Vg6e4orzNzaD#Dr)k(X`A$`E)WTmc4)P z*pY1{ZZ_+>?JXSGM~;PP{E~_`_7^77f$QuXLd3I zy-f`4;)T`iPs2<4ls?M1&gzqhxk;nm9%tvK zY{@b_*%>m?K!$GR-aOauSc*G!L;M^|z2>MExFolG3aI|}l83`1q89pgzRt7AL8*yitG6GSjm zTj=Hd9WmG2wEg3R?!c;I$;=W?P_y96R3e(+F2XO)r18LAzD0IsNd$dl3lV(c^s$#l zY9u?xJNr;oOGjZ?zqa_PA9X19?q}nip#0hd-h0P&YVmj8DFo?z5H@}>Vz7Tdgsyw9 z;Gd5{Sa4+NK|zBIDGM4=P0H5&z%TpunZK*w{QHr;@8L*iftPWwcow&u@^Ch06nFNEB(!bRqq|Gq;M@`P?3|R` zQKtTj%?rzYH5+E)h+i5hpEglf?+rR1t!Tbs`Is$r_{LrEcG|q>V&-ELtXobMuYdDR z2GKZHQT640zu)Nd-gVnlu9FJm$^2}@f>Uif2}2~42KM(%nj1m3n;ej|@(y1kH&E=#SqR z+Thrnx=7s4_?A8XS(7I_n`E#;&0Z;mIN=wjr;~Kzebzwnn~Q6P+fnx;KUS#=P-@T; zQ0IK5P?@a>e@gY7!)0ho*RFoC%WST4Wi>9Ajk*5h@b!A>9$y}xsljC;Hlr(b=Vkib z@ynG$TQ>>W-RY4CX?3k5{ka-V$uMUrvZ%m82BFb_2;w9!`pWR|RF~|olkJ@hXX=My0FJWR3I+puGNWb4IUlAE zzUSlE`2E;|@d4W}QdMtwm!B^^r(Xxi8%CGCXekt`l zzJ1FXeX{0z(h!PesAKE42i?GY(y_?f?3;r+P8?0Qi&njl3`yxlj_y_$rH~7opHn{Q z$8#ZSrd|wv7hU9qb)>i56>Aq(zAvtcy~I&bNBoe4994Z5$By!lb0$7XHU&YK(usNE zK~3@N)l-y+ga zB~?&{Q~W|6qa|il)l=FOd~12@ zsoA@UM=(5+Z4ky`9LtND1H{Js0sj2PVQaY9>tP&u;(P^M-HF)$%MColGo@z#g$$a% zs{DRn@!1?1&8S zGe#yRCN&*%RW^e%Wwkjn$DJdj`fIcfHM`GETWBlHB>krrUQO1+g)5UP!IT0%>rkl5JRXVOJzTNMo zXDY6KTCn};v7(}4jmwq}>9eS}u=2eS5-wBlG7^mD~iDIN9E@G4-`&9@FX1 zZ%oY0p0l#DqWJFr`xmG2ndyjagnY)ww6O7dAoXbsol^Q^E*1uc;0D*7ve^BX)jo0L zql0MzQi#8!g{n37OV6XFY1Fi|82ZagN@x(s50HZ%u8jme|M)zJCuXSQJJ@VB+8q%~6n(E5a;HOiUzrczEs+6EpNTI<4WK zo}4Iuv6=n$^{emeH*YK_%Jd{8YF>4qC50!Zr72{19g#d05V*6WBq#SsNl9sas+QS# zYbwsHKT#AmBVPNGcuf25ogKGcE5PLLpgWIK&-idp z`>^RXNVHyGHTKuEUSIB*SXfANb91xIT`7%(W?pSK?nLM2(yD7}s+yV6-N?+$q;)Uqt+2JE$Vd1`S-!l9A<#j&4CUIUL4cXt{FDNPs z)hO3j0OP3X=*YsPIIr)48At0K&67Ed(QEjoko{`~zbegFRb_J+gtu@CqJ z1ch~Vi8(5aAzemH3=GP3TYLr8@xQN%g)S3<3vzM-Hn+BV2M3iH&&8KSo121Av5cxFeMmzwJb4mJF6bs=@OBTrD=z`gA&p?*=hrD{yqfrOc72aovn;2@>s&=r zGLT(ZKp=(Rd0hfb?i1)d-Q@1*zn`6zbV`2z?{`?s*A^!gE zJFUm@Nd_7k?_uaClkX1>oCJ?&963h_S#@uN(VaHNvA!p;_3SP6RK7iRXgXUjwsUeq zL8xhJGV8X&x5G%eG11V_+H0;Z&$C^3=A@OBi1M(A*+txJtgJ8*q(9zsjRTrl*XCV6 z^S&TXPfwSYmzR*2zw2?lU0NYjlvUo}ezY}>j@aGZ#myV@{)K3C*=oPT);`UF z>9%K-_2o&6F55f>K+v+isUyc2i~(DbRM<{o|s3c_xs zpCmCc@$1|ixx2f2_-A9VxwNdTm9meh=nZ|Cm2S&h5*%_tkpxyf1fsXM7jZRXNgY)% zT$PrZiu>R}SWywv-;D{IhSbytGfnQQ#2oD7vBTN$44v?5Fva;40{*l{`O+8hk=Df($21;;$r1T3LYNbJJ?9WHa}DbR@Uw& z_kRJW$2;>qGxd&9fR*3ANxwasG}o#!k;%^Z?5t6yi~I-$4UL+f9$onA4vNGVJQkK0Rgh_@hsv-M${k4g_s1B z9i^q!W1}tX9UQXYnDFq=PfjMKrltm%bQY->TMT82(nLvro1IN#)vcp^%nZmpJRBAO zSX+#aj?U!G8-)y?tET`v1W~_LvtZMt0oZ8>KlBa^DDo|b1T#=l`aWi1>HYO95#DKW zezf)E^)GgvYBMZ6JX2HCsI;_)BqSumlhx*AsrYe;iPGEK+enB7TR-tUdQHWp|HbBT zn%Y*!nD0fOPUw00%9*W#0#;ID;?Yn=_}|co|5twT|HTc7)~gR^#~mZ4LT64LvF_PX-e;sgmCQe7 z)u@ap7?u3sm%TPsh^gOml3IM$aev#k;U=QseWW-4owfY(#p8en;h*KkPP#iA^0QI* z8@%rz?5Si(Ux%D=f4N>~)|WWG>u&G6tD8gLK2&*&!)a3_R*+TvZ0)g0>VTNb6bshp zNDjJ)^RSO(qbYI{5A9Bl3Jz|tuFx<3F8x<`$S$?bIjit^!D1OxY6GugbLM3;mPuG| zEtSKk-M3rC0^Gmwx5lXaJ-kpOY!{GEBxVGlce(yyHJ+^%eo!j)b-3@o9?k67j99nU zL+tfX=aWo*gY8Rss;>!Zf>DkAU&%j;`4VlA71jraIlq1|dVeW%E?Dl1s@nqcRosUGZI|2Uxpu{b7BCm(so#v9xp9 zzl9u(9~(K?w`v0&u@c*WS6(yhB@r*PF~)y}((`3_Vy-$W+55$DA7v87e4;LP(D zRM8CcZ@{;MPY)OV^M2YT6lUY14pBW0>~*Gg42|yC2>%A7R0efCc%b{qJE?W6ZunFu zLTWwKUU?$30mb^cH@@uCw!TEM|16}8mJhCt{(EhjoMPx);}A$duceKSe5qorRniKb zR*ZuZRR}>zSY`gMbaUDQ3<*<$$#3Dp7p1!XGy2v8l=^^tR04~9mboLdf9>JU4CproXE3Aw66>`=HC`u*SQ zkH~AJHR)vq_>g9J>6SC_=Qj%T$n*c$gI_h6phW(qoif;l-x|4Yh5tP1JkG=-Q^Bv( zm?ccFm4uJHPmo)pj$E$G?c`3x4>&mSGezwI_{YNp4cRocRmV=dRM74RTO@b$Uh?E?}6QunclHyH6~w= zp+POyT`FNRBl`!XIG%%({k`exvtJpzya!xgdiXrc(b}3@X3mrN;@pX0T#oUpG3XCv2!X>ti4hV$FNP~Xm5w=`R^C0AaMQ8uL4>zzW0+}e!}g)@m1Nt4~On;n`oLp z|3)xhThXPWDS7ub=cAP73$1faj)6J3Ko%iQg~@caNI6d*r#-A&?6l z+WDzBK5?xX$UYFZS2mZ&zCtZ_u^6yOlUl0+T+2hyYjMjB|DV5(-%K@BZ_RtYAt-Ab z3{RIHnEM?H$})#8v%=;rTf9cT=RNW{6!;>Gd$u!q?)M(Zh-hKlbwMGW)fWwKAt_P? z-(b?b9OjSsNrt@5y?|2eFd9DY9y?d(LNIDO+Yoqh@iwVdNtlg+!54UINlA&JsVS

    eC#+jVxc_v{X2on?)BAiD_ufuMMdPPmFb%|vkMyuwYA)k zeUJ&Rx3rA;%*H0@dtl7X&G9!cB^~`#^Q$eXlAsNd+Fo7Hjmm8CJhll42%uzTEgLp% zYHC_oTJi_t*3s98X;i6Yc}Rc3L0F3%G9I z?l~fz-XkX`|5am2@I0I}_p=L!Mn(}qNj@jeqkl)JO+p@$DK`a<9e=3EDFa*Wfn=uw zGDNh0bPCBx4tH{P_B+Wu{e`pYy`t&8#l=NFmrX7IQzRGTc{7zWiic{LE0pg^!-zRvzudFvJbK$-wOmmX8x@5|%)AmIH>#kMhiem5_GJNI;l zlbPm4Ja~!^_WwJZ;`6xuNwGVI1_9Mq-Z;b3JL?FY2fykwta0Md4nGjFA(xlHWhf)#INRb_f#UAW7q@!vl^J#DWM@;ox!o~bV?P-Fqp8}!t1<#ze`!J2B*CO zBY6r0`i=GVi@>-@U*j1oe6RP>CT?Svt+-0Q|3N^K*L39&prB-!qR)#0CX*eVNlr{0 zy!`$8f|Tgt!|((HZ|%u3i~d33>$^bu7M%?ZDdSo7irNS{#sx$1OTz89|J}^vAB<1x z24gb{6&SR7Kg7nyW?(68-rjqUMTU!uo7vA))1If05^%`L%`FKDAe^TsGfdsd`A;#% z^T%+IOGrqsx)T;0jO%i+yV&9EAa$!&`?7&%D286iZg)Wx>q~Iu3c&{1D=iA%em5J& zXNkMCf@tS$TCb=6c(Uq7^nAJ_j9Bn4`w>e%8WR%}xC-uQW7Kpe@_v@A0BmZ$?H&($^TqrLGLl6s$AS7DxL; zWj&9!<->N9&+A=YoN+iuNz(|jv9i9etlXYU%E`$=0hZZr%~HQWYy3k+L)-7~hfj5O zLM@X!m76nU&(XRQFWaTspKPyAN#<%s4)*tVR=ny^(++&D*We^GqF`8}-p3?|n_6-I z3xz>K(%j$-Il^$V9w+QB&ENn02n#gSH|M#!yAB5WAnWfTD;uh~vw39qHk`xVVaL3^ zC7+9qe=Plj9#Q{Gf8-R`78CFuJ*VX0c#+g)jYZx5E$We}!|kc7+At2&Menla*mQ={ zor}|dzpBk6n2LuIeJ++LI0cd`KguSYpThB&))UrTlYWSx!N&mZy8Ba(jj@_EoZtI` z50FAxU!RprZ(6vGL^b~7(4bPfAO_MS-d^xe%?+yatDyUWIwGGgNYWEQq3Nt{W&h_J zUekUbGuBOhO{^kUug@XY*~X=7u9oq6>8w7h8_^W%f3S$*qjtbl)j zTLmR0D7&j?9OF@II>J643*&QV^{{#|v73({KmJdm<+fEjQDNA2bEer-Gj5DY4^pX> z{-j%wi>j%s-$0aSSX`^%$^t~<}C;TLgH zQPJ@D;dB=s4==L>DU?v4#SuRr=33XB>uZSXGK`}YGu z(h>B&&`SCdGYn(9xw(BE86iMA1SDlIb)S1qO@=YvL7r4+(MwCf+HV5`&owj%tE#FZ z)6&3NHkkzlw`pl<85kKw?d>^aWo4ChbTC6CZW*8-xd@S+S}`)Fdi#XZ+G|~9W%czzHg%3Kv+6gg_wlIvVk#-F}x*@?CVsy z*ZI+_Z;@2Dv9RvvH6Kk`vvY8?0oYc6CliyAS#L#f!#XQKOjO|Y=g0+?Yt0=Z;pch0 z{i&it+3f6h*9ZHH6MIlSvb+s&4M?NJV#ieEe6f zH4#$GU06VXmDJ)FkySbPEx<;@BH2~1{*I>LyhOb}WrKhLgoNqN?Xa!l2S);@^ zFc7uBzn|T9PEa1ysSkuKD$8bOC8n`nECw~%8`#X^QZMJv%JiFM}yYYTRj&lRyrE;){9bPGMD5G(x#tznOu9BP#U6 z2N|ZgXsyS2KtQOeJ+3d0d;9uA0SCoEg?sX5>Iq1lHFk?)+;8l+hKH|qrbo^klx?#= zer{1}^gL#L^Q+<=QXls4@Idi}CI0PC;%etqDU5|}3Y;j`D5ZY%=uuHY0dAf`@{_d)F*3)B&Rc~!+K(Ux_ z@d~swsw7@sUJfrC^u2K_U^Oo<58)dciU~?hW>eFHY^jKN#(5Cz_nsTcLyFXZ78|d* zxLW=6Wb=9;tENeIkE})+yk*X92`iP~SvGMTu;}FEgp!AckUHviR8&-W%Y0|2#7eE! z<8IHL=AhA0wZ*+@+g7Aj1?b7=b0rAky8YiFDxmd5pk8%+eltxPTUNArD8EdKajqy@{ke|tgJZN06&JH*BV4pIx zvc$|h0EvLG(i{sxslY!Z1jA;&rS#y4C->@`AQP1oaa!w>CSIENTgQ%v*+xk*?JWQu|Yyo@>5-%mW{Sb;XODDTD4a9%k&!G z11cIp937gN2$Guets2@r2So6qXHtwvT+W_rTzQ&J6vY{UmXX9&;fJ99z0c9@rmTlC@f^W+D~X* zfMq(gz6lHp$_9t$G9S2?2Zf9_fbrJLqnG~6M31$6fdMT7@d*C-@%h`gfxAz z_6;g@M2?eRg(suvtAA4OO@PeW-Um;^N|R zu(zi|#Aam7uY4Yh`qDyc8h0-)Qi1u)wV2%J?q074A%hw^WQiUDfq}!#p2sG6SP%Fr z+O(fOd{=dL3M%exL|0D_Zz8Y#Z;Ab*BSQTQK6^j3yTl?L@3FvCLYNpBcq{ks-HS|5 zCx7_VK_Zb54^NajDi}a?dh|Ksp=dCg1OvTo?&OG@Fhwjhj zTNQT9S*n4Qy#+iz+5gV=%EBTT7Vvw#^rhS7;RN?=4bL@O?P!5a^$o=8$IGEShwd;E z|97|0scC2=R{FC*Ht6i`?t7~WUgg)?D*Wu~WC<OSzD`ZF~G#|(i0(xM?F zfJK{UM}F>6J!n=~R3<8Kq@S{}oLQz1g;1?ZBUJsjdy)XqU%?c^!^52UqE>x_7*DNA zZAWQ*QUyMj|5%2Q+n+8(21Sh?-ubuw5Z`Vft{?#hkR(s!G!3oT)HLuKGkJP+bcC?- zcSBZ3Z{B40I&-3WHUGk5i^Cbg&coAPV>yD0k54Tx;PB^mx}dus3745gh3URsmHY&h z))pa!V|e@+A|HqM=`vB%$?p%zHX4n*pqL{GJ8|NT+WBttAIY@G_tYiddU5z7 zawoV$#HwbdI*nRNUU=(k>QhH{z>+^JD_M|I-p0m$|K$sBgY!n-S{_E9T*ksor5E4n zh)pN${MX*tJe*eIzZy)mKuCfv@|^gREF5%#!{t-K-~R{ z>;;fQGA=Jz@k+kEZ7hD zd;y<-LsG@(^fxjug*Ks6nIb*=ykj=kHKwh(st64&?cih=LzUF|nyvX~xAB_NzvJVc zXj-`n;~s3FHWXlGn}bmkNq*Puy9ljj4{k9rF)-xMPktVa#7t-B=SxsLWovJ5H+=Q# z29$gicnf8m+q^DkRymeWuN(#?HJ>D#mps}#JVeD?gxU|E+b-pt`)V3t^Y!Lr_22PQ zva0IpKuchsZWkvUkfT(k6pu|wDrW#QQc+Q<@H%%nIX@RyD%X3`*t?*wqaRrJhwKg0 z^<1+jDA!ozfSttLR`-yVmt!xetg^GSTiE}0gW4!^vc6LkL0DuwB??>RJAZm(q!kqI zrx%}nlmNj(LPW&3uMgcS#uefKQ>nP7Gz~tIv_YWhfCB^$bU@hbbF#ZwQB~CrQ;kYZ z4GRmq3zJ#eo^3=bOQAZYX;YF;o3o9)$c>4PzUkxRqrjWrMS5qukF*prc@oIarDbG9 z9UM4eD-gGC-9iRwdU`1{ZR&QQGrMD&2DOa6ydVtqX9%~3vy`jr>0tq~&D6a(r^;t` zrHPi!ZKp*|G;&<&7gbTgzqq(CG&38|IwmD0{SEp_#plo6IWjTq@Pe6E9|{Z%3}QjI zicp=B+*q&Q0#m~>XMID-hb)Z6Igj>gg%z#7M?`MVHOnDPyaQh3XJ+~$hTup&;)3#G z-k5N=owIYUda*|Bdb2`d z`zDD=No_xW;)6Ct$l9x{rWQae7oVw=@eFoQ1c*YV)0)bs?FPL1gajhMPO=Byg+)c} zP`kte>HrMBt+!WZ1>FpIS|YzQ)3cL>TL*uKZ$X(0348WCbIlsI!jjH6YmY6ww(D0Z zqof!9{tcdObQK4sV1ls7=Oi~P>n2i+Lxx$P;*Skl9<;Qyv{Pk5?GP|0HZBfhc|xIh zS`mV;R*eOo$HCusKm&|^cZNvI$yp!rbIx{(>iNeyUnV3clR_5%si+7OV%WF7zIH#< zJCuYU7MGV%GmrQVfx>e*uE-<1KNuKpUmyEi2XR}E-(D8!K18f*>*& z_r)?|`b4>|4m=Da8?I)VZX0llN;o2m zb9v50Z|>Z=(*eFo7Tapng?RyVrwgKdWPJR45ahnj&r@8VO|%A>0$Co0oZ`=)KMO#? z`2gZlwuOrd2B6e#{4+BRu&WD2fbtURz3@u<@$8c2bYvIG&c4gfL?X49KrXc zt*vk%l@byX3vf1wpeNMUZfzfhIyww)4W( zBL8Dyp{4(KPF_vNb$La_?t&NDCIg*TkN4hgO>u)0_s-Dv!cNt>yl@2h4wntPC9VsLG{(q)qdnw1du@IpsOt z*U!w%tm=kYsP)*!A&Ga+?G^_Ihugm&yd0nnNay}EGr+H{K>W`=JXe+%^@Z0#ok4N-UX#^2!FR6RiC{ zm(9a@cx7bd2Qt%3K63r*0Ws$Y$nlJq`{Fn?tL0>6@%!rC_Nd99y$uGW;?#GjUKb$i_c!)znfj$a%gL&P6{wGnn5%zpba{bGcsrB`+x@WeKvduG4?3 zf#+`E9Li~^cL*0i-UJ(T!$IQkIIsXIc;eEF6-TEQV9 zAcNsVf`fp5@f)t&gGBNb(+o{a0wBlY=1UQ$jxy{Dy$>yB$eNCe3lFke%;(zsEp#cp znNkED5!8`_{zuQAwP-uH9M5^yLG};YLMT}G5jFMAjjKBHz7YzQG=674HKwlo4DV3! zAne7yIA(ysD0#mT;A)UhpZtkYLV}CW<%Yqp7OzJ3Yow+UfI+YeG#8nPK7IOBY=5k` zw@_jF6L(#PHHRrh&hhav5kBU-cklXG^^2iH19M}2XQ%w=EQMbwE%@8WNQ}IK0wXVP zLU6G6#hw%?&ue1nWvcr8IWJc(K}ALe11~C);c~sW{9AjwA5ao`NMU${+;&A6$}1%p z@m>J=3#SlHhd^BbNq)`iNlvOYB2rRWfDUBm70}ddXv7);gRcb=>Eq5(;NprvBUhec z8dD4dZIMC_8VU+h@c1?~6q%ZqW;(9T6xUaiTWNWyt)tVYz&X(@^&(B8miLXFiwj+) z7M!>LG~L~#e9d(c#Xw74R92RExG@m}6}Y72mmeAUB zkDQ#9Mm8jPd%jf(0y`C89w!e^-fD)AJ{?J!B2uON>F=Se99ePWJq|_L=I`1*;HQDk zSeTeUogAlfSPPh!SUDbwf|TOV<#Dt#uLOZYO;vTIgcHP+=`Ea0ur^yRh4&t$DlG%~ zIXN|Jy06}R261gM3A9hCYq-Bb7;GeH-<@4#GxL7P66s@^d!6I(dG+v zXRAu{LGq--%Brd?xTC=Pfg>F10A6ZmDHA}y9PI2OCq?x2^_>>mQPnkyorqX2metAk*J%LmMcFVBxHfzkX~Tbs0)rjt(` zT4*xq))Jo?Ej zwDQzgPq5~W4{Aw$z0~EBkSJ}6O~e1QyiE1@@m;7ep3GlgP5h}MBqRhT<_9HKC@Tc6 zDqS}_ZxBL_)b#3^&=#ygVVoNXBh)9`LGu7zR(*wuYkbj8Sd%Rr?eGlvI379q$BGJe zNNApK9YQG%L*Q3;H(YWdYYLh|r5Njndd(j9VZ`9zU=bS|R-4&|v2| zU!Jv1Pm@78wW79GUFS56qpL2X_`L?2vwQlL2kp*=CX_#bSCYMTjyXOI=g9M_%lI;T beQT+2VD7__ygK~H8ib6bqC}aPq2K=j@f-2p literal 0 HcmV?d00001 From 8ae6174617b103b562a3156b8644798cc5aa27ee Mon Sep 17 00:00:00 2001 From: mathieu Date: Wed, 31 Jan 2024 16:35:31 +0100 Subject: [PATCH 2/4] entete --- .../maj_replication_logique.md | 80 +++++++++++++++++-- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/fr/atelier-maj-repli-logique/maj_replication_logique.md b/fr/atelier-maj-repli-logique/maj_replication_logique.md index edf8977..59e60b2 100644 --- a/fr/atelier-maj-repli-logique/maj_replication_logique.md +++ b/fr/atelier-maj-repli-logique/maj_replication_logique.md @@ -3,15 +3,20 @@ title: "Mise à jour majeure par réplication logique" subtitle : "Pour les versions de PostgreSQL supérieures à 10" licence : "PostgreSQL" author: "Mathieu RIBES" -reviewer: "" -date: "17 novembre 2020" +date: "février 2024" +keywords: +- postgres +- postgresql +- workshop +- replication logique +- mise à jour majeure -to: '' -customer: '' -address: '' -reference: '' -url: www.dalibo.com -revision: 1.2 +linkcolor: + +licence : PostgreSQL +author: Dalibo & Contributors +revision: 23.08 +url : http://dalibo.com/formations ## ## PDF Options @@ -29,14 +34,73 @@ links-as-notes: true ## Police plus petite dans un bloc de code code-blocks-fontsize: small +## Filtre : pandoc-latex-env = cadres de couleurs +## OBSOLETE voir pandoc-latex-admonition +latex-environment: + importantframe: [important] + warningframe: [warning] + tipframe: [tip] + noteframe: [note] + frshaded: [slide-content] + ## Filtre : pandoc-latex-admonition +## order of definition is important pandoc-latex-admonition: + - color: LightPink + classes: [important] + linewidth: 4 + - color: Khaki + classes: [warning] + linewidth: 4 + - color: DarkSeaGreen + classes: [tip] + linewidth: 4 + - color: Ivory + classes: [note] + linewidth: 4 - color: DodgerBlue classes: [slide-content] linewidth: 4 +# +# Reveal Options +# + +# Taille affichage +width: 1200 +height: 768 + +## beige/blood/moon/simple/solarized/black/league/night/serif/sky/white +theme: white + +## None - Fade - Slide - Convex - Concave - Zoom +transition: None + +transition-speed: fast + +# Barre de progression +progress: true + +# Affiche N° de slide +slideNumber: true + +# Le numero de slide apparait dans la barre d'adresse +history: true + +# Defilement des slides avec la roulette +mouseWheel: false + +# Annule la transformation uppercase de certains themes +title-transform : none + +# Cache l'auteur sur la première slide +# Mettre en commentaire pour désactiver +hide_author_in_slide: true + --- + + ## Au menu

    From f87548b1724598d1abffa56233ec22fc6e68c57a Mon Sep 17 00:00:00 2001 From: mathieu Date: Thu, 1 Feb 2024 17:38:27 +0100 Subject: [PATCH 3/4] mise en page --- .../maj_replication_logique.md | 654 ++++++++++-------- 1 file changed, 370 insertions(+), 284 deletions(-) diff --git a/fr/atelier-maj-repli-logique/maj_replication_logique.md b/fr/atelier-maj-repli-logique/maj_replication_logique.md index 59e60b2..e7c0b0d 100644 --- a/fr/atelier-maj-repli-logique/maj_replication_logique.md +++ b/fr/atelier-maj-repli-logique/maj_replication_logique.md @@ -1,15 +1,12 @@ --- title: "Mise à jour majeure par réplication logique" subtitle : "Pour les versions de PostgreSQL supérieures à 10" -licence : "PostgreSQL" -author: "Mathieu RIBES" -date: "février 2024" keywords: - postgres - postgresql - workshop -- replication logique - mise à jour majeure +- réplication logique linkcolor: @@ -18,20 +15,20 @@ author: Dalibo & Contributors revision: 23.08 url : http://dalibo.com/formations -## -## PDF Options -## +# +# PDF Options +# -## Sommaire -# toc: true +#toc: true ## Limiter la profondeur de la table des matières toc-depth: 4 -## Mettre les liens http en pieds de page +## Mettre les lien http en pieds de page links-as-notes: true ## Police plus petite dans un bloc de code + code-blocks-fontsize: small ## Filtre : pandoc-latex-env = cadres de couleurs @@ -99,51 +96,39 @@ hide_author_in_slide: true --- - - ## Au menu
    - - * Principes de la réplication logique - * Rappels sur les migrations de versions majeures - * Exemples d'utilisation - * Mise en place d'une mise à jour majeure +* Principes de la réplication logique +* Rappels sur les migrations de versions majeures +* Exemples d'utilisation +* Mise en place d'une mise à jour majeure
    -
    - -
    - ------ +--- ## Principes de la réplication logique
    - - * Fonctionnement - * Quelques termes - * Processus et paramètres - * Granularité et Type de réplication - * Limitations +* Fonctionnement +* Quelques termes +* Processus et paramètres +* Granularité et Type de réplication +* Limitations
    -
    - -
    +--- ------ ### Fonctionnement
    - - * Réplication logique avant la version 10 - * Non native - * Uniquement grâce à des outils externes par triggers (slony, bucardo,...) - * Réplication logique après la 10 - * Native - * Asymétrique - * Asynchrone / synchrone +* Réplication logique avant la version 10 + * Non native + * Uniquement grâce à des outils externes par triggers (slony, bucardo,...) +* Réplication logique après la 10 + * Native + * Asymétrique + * Asynchrone / synchrone
    @@ -152,25 +137,24 @@ elle réplique les résultats des ordres SQL exécutés sur la table publiée et l'applique sur la table cible. La table cible peut être modifiée 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. Cependant, il est possible de réaliser des réplications croisées où un ensemble de tables est répliqué de l'instance 1 vers l'instance 2 et un autre -ensemble de tables est répliqué de l'instance 2 vers l'instance 1. +ensemble de tables est répliqué de l'instance 2 vers l'instance 1. Comme la réplication physique, la réplication logique peut être configurée en asynchrone comme en synchrone, suivant le même paramétrage (`synchronous_commit`, `synchronous_standby_names`).
    +--- ------ ### Quels termes -
    - * Sur l'instance d'**origine** (ou **primaire**) - * Publication - * Sur l'instance de **destination** (ou **réplicat**) - * Abonnement +
    +* Sur l'instance d'**origine** (ou **primaire**) + * Publication +* Sur l'instance de **destination** (ou **réplicat**) + * Abonnement
    @@ -182,12 +166,12 @@ instances de destination indiquent leur intérêt sur ces modifications en s'abonnant à la publication. De ceci, il découle que : - * l'instance origine est l'instance où les écritures sur une table sont - enregistrées pour publication vers d'autres instances ; - * les instances intéressés par ces enregistrements sont les instances - destinations ; - * une instance origine doit proposer une publication des modifications ; - * les instances destinations intéressés doivent s'abonner à une publication. +* l'instance origine est l'instance où les écritures sur une table sont + enregistrées pour publication vers d'autres instances ; +* les instances intéressés par ces enregistrements sont les instances + destinations ; +* une instance origine doit proposer une publication des modifications ; +* les instances destinations intéressés doivent s'abonner à une publication. Dans un cluster de réplication, une instance peut avoir un rôle d'instance origine ou d'instance destination. Elle peut aussi avoir les deux rôles. Dans ce @@ -195,18 +179,17 @@ cas, elle sera origine pour certaines tables et destination pour d'autres. Elle ne peut pas être à la fois origine et destination pour la même table.
    ------ -### Les processus et les paramètres -
    +--- -Sur l'instance d'origine (primaire) +### Les processus et les paramètres +
    +* Sur l'instance d'origine (primaire) * Paramètre `wal_level` = logical * Processus `wal sender` (`max_wal_senders`) * Slot de réplication créé automatiquement (`max_replication_slots`) -Sur l'instance de destination (réplicat) - +* Sur l'instance de destination (réplicat) * Processus `logical replication worker` * Autorisation de connexion sur l'instance de publication
    @@ -223,19 +206,18 @@ défaut il est créé et supprimé automatiquement. La copie initiale des donné crée également des slots de réplication temporaires.
    ------ +--- + ### Granularité de la réplication logique
    - - * Par table - * publication pour toutes les tables - * publications pour des tables spécifiques - * Par opération - * insert, update, delete +* Par table + * publication pour toutes les tables + * publications pour des tables spécifiques +* Par opération + * insert, update, delete
    -
    La granularité de la réplication physique est simple : c'est l'instance et rien d'autre. @@ -251,54 +233,65 @@ réalisées. On peut très bien ne publier que les opérations d'insertion, de modification ou de suppression. Par défaut, tout est publié.
    ------ +--- ### Type de réplication logique -
    - - * Réplication complète - * `CREATE PUBLICATION bd1_publication FOR ALL TABLES;` - * Réplication partielle - - * `CREATE PUBLICATION bd1_publication FOR TABLE t1,t2,...;` - * Réplication croisée +
    +* Réplication complète + * `CREATE PUBLICATION bd1_publication FOR ALL TABLES;` +* Réplication partielle + * `CREATE PUBLICATION bd1_publication FOR TABLE t1,t2,...;` + * `CREATE PUBLICATION bd1_publication FOR TABLE t1 WHERE (c1 = 'xxx');` à partir de la V15 +* Réplication croisée
    +La réplication physique a le désavantage notamment de ne pouvoir répliquer que l'intégralité de l'instance. A contrario, la réplication logique peut répliquer de façon plus granulaire une ou plusieurs tables d'une base de données de l'instance. + +* Si l'on souhaite une réplication complète de l'instance, pour chaque base de données, il faudra publier l'intégralité de ses tables. -La réplication physique a le désavantage notamment de ne pouvoir répliquer que l'intégralité de l'instance. A contrario, la réplication logique peut répliquer de façon plus granulaire une ou plusieurs tables d'une base de données de l'instance. - * Si l'on souhaite une réplication complète de l'instance, pour chaque base de données, il faudra publier l'intégralité de ses tables. ```sql \c bd1 CREATE PUBLICATION bd1_publication FOR ALL TABLES; \c bd2 CREATE PUBLICATION bd2_publication FOR ALL TABLES; ``` - * Si l'on souhaite une réplication partielle de l'instance, il faudra choisir les objects à répliquer. + +* Si l'on souhaite une réplication partielle de l'instance, il faudra choisir les objects à répliquer. + ```sql \c bd1 CREATE PUBLICATION bd1_publication FOR TABLE t1,t2,...; \c bd2 CREATE PUBLICATION bd2_publication FOR t4; ``` - * Il est possible également de croiser les publications sur différentes tables, mais une table ne peut être à la fois publiée et abonnée. +* Si l'on souhaite une réplication partielle (conditionnelle) d'une table, il faudra ajouter la condition lors de la publication. + +```sql +\c bd1 +CREATE PUBLICATION bd1_publication FOR TABLE t1 WHERE (c1 = 'xxx'); +``` +* Il est possible également de croiser les publications sur différentes tables, mais une table ne peut être à la fois publiée et abonnée.
    ------ +--- ### Limitations de la réplication logique
    - * Pas de réplication des requêtes DDL (et `TRUNCATE` pour PostgreSQL < 11) - * Pas de réplication des valeurs des séquences - * Pas de réplication des LO (table système) - * Pas de réplication (automatique) des partitions (<13) - * Pas de réplication des vues, vues matérialisées, tables non journalisées - * Coût en CPU et I/O +* Pas de réplication des requêtes DDL (et `TRUNCATE` pour PostgreSQL < 11) +* Pas de réplication des valeurs des séquences +* Pas de réplication des LO (table système) +* Pas de réplication (automatique) des partitions (<13) +* Pas de réplication des vues, vues matérialisées, tables non journalisées +* Réplication déclenchée uniquement lors du COMMIT (< v14) +* Coût en CPU et I/O +
    +
    La réplication logique n'a pas que des atouts, elle a aussi ses propres limitations. @@ -315,51 +308,52 @@ des séquences sur les serveurs 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éplication 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. +Il faut que PostgreSQL sache opérer une correspondance entre les lignes des deux instances pour gérer correctement les opérations `UPDATE` et `DELETE`. +Pour cela, il est chaudement conseillé qu’il y ait une clé primaire sur chaque table répliquée. Sinon, il faut définir une clause `REPLICA IDENTITY` sur la table origine. Utiliser un index unique peut convenir : +```sql +ALTER TABLE nomtable REPLICA IDENTITY USING INDEX nomtable_col_idx ; +``` Pour répliquer une table partitionnée, il est nécessaire d'ajouter les partitions individuellement à la publication. En version 13 de PostgreSQL lorsqu'une table partitionnée est ajoutée à la réplication, toutes les partitions ou futures partitions sont publiées. -Enfin, la réplication logique a un coût en CPU (sur les deux instances -concernées) comme en écritures disques -relativement important : attention aux petites configurations. +Enfin, la réplication logique a un coût en CPU (sur les deux instances concernées) comme en écritures disques relativement important : attention aux petites configurations.
    ------ -## Rappels sur les migrations de versions majeures +--- + +## Rappels sur les migrations de versions majeures
    - - * pg_dump / pg_restore - * pg_upgrade mode normal - * pg_upgrade mode lien physique - * réplication logique +* pg_dump / pg_restore +* pg_upgrade mode normal +* pg_upgrade mode lien physique +* réplication logique
    ------ -
    +--- -| Outil | Coupure production | Retour arrière | Fragmentation | -| -------------------- | ---------------------------------------- | -------------- | ------------- | -| pg_dump / pg_restore | Elevé = sauvegarde + restauration | OUI | NON | -| pg_upgrade | Moyen = copie physique des données | OUI | OUI | -| pg_upgrade | Court = mise à jour directe des fichiers | NON | OUI | -| réplication logique | Court = mais préparation en amont | OUI | OUI | +
    +| Outil | Coupure production | Retour arrière | Fragmentation | +| ---------------------- | ------------------------------------------- | ----------------- | --------------- | +| pg_dump / pg_restore | Elevé = sauvegarde + restauration | OUI | NON | +| pg_upgrade | Moyen = copie physique des données | OUI | OUI | +| pg_upgrade | Court = mise à jour directe des fichiers | NON | OUI | +| réplication logique | Très Court = mais préparation en amont | OUI | OUI |
    -Il existe plusieurs méthodes pour mettre à jour une instance PostgreSQL vers une version supérieure. +Il existe plusieurs méthodes pour mettre à jour une instance PostgreSQL vers une version supérieure. **pg_dump/pg_restore** -La première méthode : utiliser `pg_dump` suivi de `pg_restore`. Cette méthode reste la plus sûre et à privilégier sur de petites volumétries. +La première méthode : utiliser `pg_dump` suivi de `pg_restore`. Cette méthode reste la plus sûre et à privilégier sur de petites volumétries. Les avantages sont : - * Une suppression totale de la fragmentation des tables et des index. - * La vérification de l'intégrité des données. - * L'affranchissement de saut de versions. - * La mise à jour granulaire. +* Une suppression totale de la fragmentation des tables et des index. +* La vérification de l'intégrité des données. +* L'affranchissement de saut de versions. +* La mise à jour granulaire. L' inconvénient majeur de cette méthode est sa lenteur d'exécution. L'arrêt de production durera le temps du début de la sauvegarde, jusqu'à la fin de la restauration. @@ -369,7 +363,7 @@ La deuxième méthode : utiliser `pg_upgrade`. `pg_upgrade` va récupérer la déclaration des objets sur l'ancienne instance et l'intégrer dans la nouvelle instance. Il va traiter la mise à jour de ces objets et copier les fichiers de données de l'ancienne instance vers la nouvelle. -L'avantage est la rapidité (elle dépend tout de même de la rapidité du réseau et d'écriture sur la nouvelle instance). +L'avantage est la rapidité (elle dépend tout de même de la rapidité du réseau et d'écriture sur la nouvelle instance). L'inconvénient majeur est que `pg_upgrade` conserve la fragmentation des tables et des index. Il est souvent conseillé de faire une réindexation après un `pg_upgrade`. @@ -379,19 +373,19 @@ Note importante : `pg_upgrade` n'est pas granulaire, la mise à jour est pour la **Réplication logique** -La troisième méthode : la réplication logique. +La troisième méthode : la réplication logique. Cette méthode a le très gros avantage de minimiser au maximum le temps de coupure de la production. Le principe est de répliquer l'intégralité des données, à chaud, de l'ancienne instance vers la nouvelle, puis au moment décidé, de basculer sur la nouvelle instance en quelques minutes.
    ------ -## Exemples d'utilisation +--- + +## Exemples d'utilisation ### 1 : Partage de bases
    - ![](medias/cas_repli_1.png)
    @@ -399,75 +393,75 @@ Le principe est de répliquer l'intégralité des données, à chaud, de l'ancie Quelques cas d'usage de migration avec la réplication logique que l'on ne peut pas notamment faire avec `pg_upgrade`. Premier cas : profiter de la mise à jour majeure pour partager les bases sur plusieurs instances. Par exemple 3 bases migrées sur 3 instances différentes pour respecter des exigences de cloisonnement client. -
    ------ + +--- ### 2 : Rassemblement de bases
    - ![](medias/cas_repli_2.png)
    Deuxième cas : profiter de la mise à jour majeure pour rassembler des bases sur une même instance. Processus inverse du premier cas, par exemple pour des questions de rationalisation de coût.
    ------ + +--- ### 3 : Migration échelonnée
    - -![](medias/cas_repli_3.png) +![](medias/cas_repli_3.png)
    -Troisième cas : la mise à jour majeure échelonnée. +Troisième cas : la mise à jour majeure échelonnée. C'est un cas souvent rencontré lorsqu'on a plusieurs bases de clients différents sur une même instance, mais ces clients n'ont pas les mêmes horaires de maintenance pour leurs bases de données. A ce moment là, on pourra migrer base après base dans des tranches horaires différentes sans impacter les bases entre elles.
    ------ -## Mise en place +--- + +## Mise en place
    - ![](medias/miseenplace_1.png)
    -Le principe est simple. +Le principe est simple. On dispose d'une instance de base de données contenant une ou plusieurs bases accédées par différentes applications. Cette instance est en version majeure inférieure à l'instance de destination. La première étape est la configuration de l'instance origine (primaire), afin de la préparer à la réplication logique.
    ------ +--- + ### Préparation de l'instance origine (primaire)
    +* `wal_level` = logical (attention redémarrage requis) +* Création de la publication + * `CREATE PUBLICATION ... FOR ALL TABLES`; - * `wal_level` = logical (attention redémarrage requis) - * Création de la publication - * `CREATE PUBLICATION ... FOR ALL TABLES`; - * Création de l'utilisateur pour la réplication - * Attribution des droits sur les objets répliqués - * `GRANT SELECT ON ALL TABLES IN SCHEMA public TO user_repli`; +* Création de l'utilisateur pour la réplication +* Attribution des droits sur les objets répliqués + * `GRANT SELECT ON ALL TABLES IN SCHEMA public TO user_repli`;
    L'instance origine (primaire) doit être préparée afin de pouvoir utiliser la réplication logique. Pour cela il faut tout d'abord vérifier et modifier si besoin le paramètre `wal_level`. Par défaut ce paramètre à la valeur `replica`. Cette valeur permet à PostgreSQL d'écrire dans les journaux de transactions `WAL` des informations nécessaires à la réplication physique. Mais ces informations ne sont pas suffisantes pour la réplication logique. Pour cela, La valeur du paramètre `wal_level` doit être `logical`. Attention le changement du paramètre `wal_level` implique un redémarrage de l'instance pour être pris en compte. - Autre paramètre à vérifier : `max_wal_senders`, par défaut ce paramètre a la valeur 10, donc souvent suffisant pour mettre en place la réplication logique. Attention le changement du paramètre `max_wal_senders` implique un redémarrage de l'instance pour être pris en compte. La réplication logique s'appuie également sur un slot de réplication afin de ne pas perdre d'informations lors d'une coupure longue de la réplication. De ce fait il est nécessaire de vérifier que le paramètre `max_replication_slots` soit également suffisant. Par défaut ce paramètre a la valeur 10. Attention le changement du paramètre `max_replication_slots` implique un redémarrage de l’instance pour être pris en compte. -Une fois les paramètres configurés, la publication des tables peut être initiée. +Une fois les paramètres configurés, la publication des tables peut être initiée. Voici la syntaxe : + ```sql CREATE PUBLICATION name [ FOR TABLE [ ONLY ] table_name [ * ] [, ...] @@ -475,9 +469,10 @@ CREATE PUBLICATION name [ WITH ( publication_parameter [= value] [, ... ] ) ] ``` -L'accès aux données publiées sur l'instance origine (primaire) se fait via un slot de réplication qui sera créé lors de l'abonnement du réplicat. Il faut pour cela créer un rôle (ou utilisateur) et les autorisations de connexion nécessaires pour ce rôle. +L'accès aux données publiées sur l'instance origine (primaire) se fait via un slot de réplication qui sera créé lors de l'abonnement du réplicat. Il faut pour cela créer un rôle (ou utilisateur) et les autorisations de connexion nécessaires pour ce rôle. + +Création du rôle : -Création du rôle : ```sql CREATE ROLE user_repli LOGIN REPLICATION; ``` @@ -493,10 +488,9 @@ N'oublions pas la configuration des autorisations au niveau du fichier `pg_hba.c ```sql host base_origine user_repli xxx.xxx.xxx.xxx/xx scram-sha-256 ``` -
    ------ +---
    ![](medias/miseenplace_2.png) @@ -506,59 +500,65 @@ host base_origine user_repli xxx.xxx.xxx.xxx/xx scram-sha L'instance destination (réplicat) est configurée comme une instance normale : en lecture/écriture. Elle est de version majeure supérieure à l'instance d'origine (primaire). Les données de la base à migrer de l'instance d'origine (primaire) sont répliquées de façon logique sur l'instance de destination (réplicat).
    ------ +--- + ### Réplication des schémas
    - - * Récupération et création des objets globaux (utilisateurs, tablespaces) - * utiliser `pg_dumpall -g` pour générer le script - * Récupération et création des objets des bases à répliquer - * utiliser `pg_dump --schema-only` pour générer le script +* Récupération et création des objets globaux (utilisateurs, tablespaces) + * utiliser `pg_dumpall -g` pour générer le script +* Récupération et création des objets des bases à répliquer + * utiliser `pg_dump --schema-only` pour générer le script
    -Avant de lancer la réplication logique entre les 2 instances, il faut dupliquer les objets globaux (utilisateurs, rôles, groupes, tablespaces, ...) sur l'instance de destination (réplicat). Il faut également dupliquer le schéma des bases de données à répliquer sur l'instance de destination. +Avant de lancer la réplication logique entre les 2 instances, il faut dupliquer les objets globaux (utilisateurs, rôles, groupes, tablespaces, ...) sur l'instance de destination (réplicat). Il faut également dupliquer le schéma des bases de données à répliquer sur l'instance de destination. Pour cela, sur l'instance origine (primaire), il suffit de récupérer tous les objets avec les utilitaires `pg_dumpall` ou `pg_dump`. -Exemple : +Exemple : + ```shell $ pg_dumpall -g > objets_globaux.sql Et pour chaque base : $ pg_dump -s ma_base > mabase.sql ``` -Ou plus simplement : + +Ou plus simplement : + ```shell $ pg_dumpall --schema-only > all.sql ```
    ------ +--- + ### Abonnement à la publication
    Sur l'instance destination (replicat) - * Création de l'abonnement - * `CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ...` - * Contrôle de la réplication - * `SELECT * FROM pg_subscription_rel` +* Création de l'abonnement + * `CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ...` +* Contrôle de la réplication + * `SELECT * FROM pg_subscription_rel`
    -Les 2 instances sont prêtes pour commencer la réplication logique des données. +Les 2 instances sont prêtes pour commencer la réplication logique des données. Pour chaque base de données à répliquer sur l'instance destination (réplicat), il faut créer un abonnement à la publication correspondante sur l'instance origine (primaire). -Voici un exemple complet : +Voici un exemple complet : + ```sql CREATE SUBSCRIPTION ma_subscription CONNEXION 'host=instance_origine port=5432 user=user_repli dbname=ma_base' PUBLICATIONma_publication; ``` -La création de l'abonnement crée automatiquement un slot de réplication sur l'instance origine (primaire). Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquées sur les tables du réplicat. -On pourrait créer l'abonnement sans copier les données initiales et copier les données initiales dans un second temps avec les commandes suivantes. + +La création de l'abonnement crée automatiquement un slot de réplication sur l'instance origine (primaire). Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquées sur les tables du réplicat. +On pourrait créer l'abonnement sans copier les données initiales et copier les données initiales dans un second temps avec les commandes suivantes. ```sql CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ... WITH copy_data(false); @@ -571,14 +571,13 @@ La réplication initiale peut-être longue suivant la volumétrie de la base à ```sqll SELECT * FROM pg_subscription_rel WHERE srsubstate <> 'r'; ``` -
    ------ +--- + ### La bascule sur l'instance répliquée
    - ![](medias/miseenplace_3.png)
    @@ -587,68 +586,68 @@ L'instance destination (réplicat) est maintenant la réplique logique (données Il reste 2 étapes avant de basculer les applications sur la nouvelle instance : - * Récupérer les paramètres des séquences car elles ne sont pas mises à jour par la réplication logique. Si on oublie cette étape, on aura des erreurs de duplication de clés (primaire notamment) lors de l’insertion de nouveaux enregistrements. - * Arrêter l'abonnement de la réplication logique pour éviter tout problème d'insertion ou de modification de données venant de la publication (sur l'instance origine (primaire)). - +* Récupérer les paramètres des séquences car elles ne sont pas mises à jour par la réplication logique. Si on oublie cette étape, on aura des erreurs de duplication de clés (primaire notamment) lors de l’insertion de nouveaux enregistrements. +* Arrêter l'abonnement de la réplication logique pour éviter tout problème d'insertion ou de modification de données venant de la publication (sur l'instance origine (primaire)).
    ------ +---
    - - * Sur l'instance origine (primaire) - * Arrêt des connexions applicatives (par le `pg_hba.conf` par exemple) - * Récupération des paramètres des séquences - * Ne pas oublier : les séquences ne sont pas répliquées ! - * Création d'un script de génération des séquences - * Sur l'instance destination (réplicat) - * Modification des paramètres des séquences - * Rejeu du script généré - * Suppression de l'abonnement - * `DROP SUBSCRIPTION ...` +* Sur l'instance origine (primaire) + * Arrêt des connexions applicatives (par le `pg_hba.conf` par exemple) + * Récupération des paramètres des séquences + * Ne pas oublier : les séquences ne sont pas répliquées ! + * Création d'un script de génération des séquences + +* Sur l'instance destination (réplicat) + * Modification des paramètres des séquences + * Rejeu du script généré + * Suppression de l'abonnement + * `DROP SUBSCRIPTION ...`
    -La réplication intiale étant terminée, les 2 instances sont maintenant une copie conforme au niveaux des données dans les tables. +La réplication intiale étant terminée, les 2 instances sont maintenant une copie conforme au niveaux des données dans les tables. -Pour effectuer la bascule de la production sur la nouvelle instance de version supérieure, il reste 3 actions à effectuer. Ces actions sont très rapides et sont effectuées pendant la coupure de production. +Pour effectuer la bascule de la production sur la nouvelle instance de version supérieure, il reste 3 actions à effectuer. Ces actions sont très rapides et sont effectuées pendant la coupure de production. - * Action 1 : Mettre l'instance orgine (primaire) en maintenance. Par exemple en empéchant toute connexion des applications en modifiant les règles dans le fichier `pg_hba.conf`. - * Action 2 : Récupérer les paramètres des séquences sur l'instance orgine (primaire) et les appliquer immédiatement sur l'instance destination (réplicat). - * Action 3 : Supprimer l'abonnement pour éviter toute copie de données intempestives de l'instance origine (primaire), si elle devait être alimentée par une application. +* Action 1 : Mettre l'instance orgine (primaire) en maintenance. Par exemple en empéchant toute connexion des applications en modifiant les règles dans le fichier `pg_hba.conf`. +* Action 2 : Récupérer les paramètres des séquences sur l'instance orgine (primaire) et les appliquer immédiatement sur l'instance destination (réplicat). +* Action 3 : Supprimer l'abonnement pour éviter toute copie de données intempestives de l'instance origine (primaire), si elle devait être alimentée par une application. Pour récupérer les séquences un petit script permet de lister et de préparer les ordres SQL. + ```sql SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' || last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' -FROM pg_class c +FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind='S' \gexec ```
    ------ -## Supervision +--- -
    +## Supervision - * Contrôle de la réplication initiale - * `SELECT * FROM pg_subscription_rel` - * Contrôle de la réplication - * `SELECT * FROM pg_stat_replication` - * Contrôle de l'abonnement - * `SELECT * FROM pg_stat_subscription` +
    +* Contrôle de la réplication initiale + * `SELECT * FROM pg_subscription_rel` +* Contrôle de la réplication + * `SELECT * FROM pg_stat_replication` +* Contrôle de l'abonnement + * `SELECT * FROM pg_stat_subscription`
    -Comme vu précédemment la vue `pg_subscription_rel` permet de connaître l'état de chaque relation répliquée lors de la création d'un abonnement ou la modification d'un abonnement. +Comme vu précédemment la vue `pg_subscription_rel` permet de connaître l'état de chaque relation répliquée lors de la création d'un abonnement ou la modification d'un abonnement. -La vue `pg_stat_replication` permet de contrôler le bon déroulement de la réplication logique et notamment permet d'indiquer un éventuel retard dans la réplication. +La vue `pg_stat_replication` permet de contrôler le bon déroulement de la réplication logique et notamment permet d'indiquer un éventuel retard dans la réplication. L’état des abonnements est disponible sur l'instance destination à partir de la vue `pg_stat_subscription` : -```sql +```sql b1=# SELECT * FROM pg_stat_subscription; -[ RECORD 1 ]---------+------------------------------ subid | 16573 @@ -662,28 +661,28 @@ latest_end_lsn | 0/168A748 latest_end_time | 2017-12-20 10:36:13.315798+01 ```
    ------ -\newpage -## Atelier (Enoncé) +--- +## Atelier (Enoncé)
    - +
    -**But :** Migrer une instance de PostgreSQL de la version 11 à la version 13 grâce à la réplication logique native de PostgreSQL. -Dans le TP : l'instance PostgreSQL en version 11 sera appelée **instance primaire** et l'instance PostgreSQL en version 13 sera appelée **instance répliquée**. +**But :** Migrer une instance de PostgreSQL de la version 13 à la version 16 grâce à la réplication logique native de PostgreSQL.
    -### Installation des binaires PostgreSQL +Dans le TP : l'instance PostgreSQL en version 13 sera appelée **instance primaire** et l'instance PostgreSQL en version 16 sera appelée **instance répliquée**. + +### Installation des binaires PostgreSQL
    -**But** : Installer les versions 11 et 13 de PostgreSQL +**But** : Installer les versions 13 et 16 de PostgreSQL
    + **Installation** -> Installer les paquets de PostgreSQL11 et de PostgreSQL13 . -> Installer les paquets `wget` pour télécharger les exemples. +> Installer les paquets de PostgreSQL13 et de PostgreSQL16 . +> Installer les paquets `wget` pour télécharger les exemples. **Création des instances** @@ -692,67 +691,64 @@ Dans le TP : l'instance PostgreSQL en version 11 sera appelée **instance primai ### Installation et configuration du primaire
    -**But :** Configurer et peupler l’instance primaire (v11). +**But :** Configurer et peupler l’instance primaire (v13).
    -> Démarrer l'instance PostgreSQL primaire (v11) (via la commande `pg_ctl`). + +> Démarrer l'instance PostgreSQL primaire (v13) (via la commande `pg_ctl`). > Télécharger et restaurer les bases exemples **cave** et **magasin** > Liens de téléchargement : https://dali.bo/tp_cave et https://dali.bo/tp_magasin - - ### Mise en réplication logique des bases de l'instance primaire +
    -**But : ** Préparer l'instance primaire (v11) pour qu'elle accepte la réplication logique et préparer les scripts de création des bases et objets à répliquer. +**But : ** Préparer l'instance primaire (v13) pour qu'elle accepte la réplication logique et préparer les scripts de création des bases et objets à répliquer.
    -> Configurer l'instance primaire (v11) pour la préparer à la réplication logique. -> Configurer l'instance répliquée (v13) pour qu'elle écoute sur le port 5433. +> Configurer l'instance primaire (v13) pour la préparer à la réplication logique. -> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v11). +> Configurer l'instance répliquée (v16) pour qu'elle écoute sur le port 5433. -> Créer les bases et objets globaux sur l'instance répliquée (v13). +> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v13). -> Mettre en place la publication de toutes les tables des bases **cave** et **magasin**. - -> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v13). +> Créer les bases et objets globaux sur l'instance répliquée (v16). +> Mettre en place la publication de toutes les tables des bases **cave** et **magasin**. +> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v16). ### Réplication des bases sur l’instance répliquée +
    **But :** Configurer la réplication sur l'instance répliquée et lancer la réplication initiale des données.
    + > Mettre en place les abonnements aux publications des bases **cave** et **magasin**. > Surveiller le bon déroulement de la réplication initiale. - - ### "Promotion" de l'instance répliquée +
    **But :** Finaliser la bascule des instances.
    -> Mettre à jour les séquences de l'instance répliquée (v13). - -> Nettoyer les abonnements de l'instance répliquée (v13) . -> Nettoyer les publications (si besoin) de l’instance primaire (v11). +> Mettre à jour les séquences de l'instance répliquée (v16). -Pour aller plus loin +> Nettoyer les abonnements de l'instance répliquée (v16) . -On peut mettre en place une SWITCHOVER des 2 instances, qui permet de pouvoir faire une retour arrière sur l’instance sans perdre les données crées sur la nouvelle instance. +> Nettoyer les publications (si besoin) de l’instance primaire (v13). -Pour cela, avant de .... +Pour aller plus loin +On peut mettre en place une SWITCHOVER des 2 instances, qui permet de pouvoir faire une retour arrière sur l’instance sans perdre les données crées sur la nouvelle instance. +Pour cela, avant de ....
    ------ -\newpage +--- ## Atelier (solutions) -
    ### Installation des binaires PostgreSQL @@ -767,23 +763,29 @@ Les installations des paquets et l’initialisation des instances se fait sous l $ sudo -i ``` -> Installer les paquets de PostgreSQL11 et de PostgreSQL13 . +> Installer les paquets de PostgreSQL13 et de PostgreSQL13 . Il faut tout d'abord installer les dépôts communautaires. + ```shell -$ yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/ \ -EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm +$ dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms\ +/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm +$ dnf -qy module disable postgresql ``` -On peut maintenant installer les dernières versions des paquets pour les versions majeures 11 et 13 de PostgreSQL, via la commande `yum` sous Centos (ici dans le TP) ou `apt` sous Debian. + +On peut maintenant installer les dernières versions des paquets pour les versions majeures 13 et 16 de PostgreSQL, via la commande `dnf` sous RockyLinux (ici dans le TP) ou `apt` sous Debian. ```shell -$ yum install -y postgresql11-server postgresql13-server +$ dnf install -y postgresql13-server postgresql13-contrib +$ dnf install -y postgresql13-llvmjit +$ dnf install -y postgresql16-server postgresql16-contrib +$ dnf install -y postgresql16-llvmjit ``` -> Installer les paquets `wget` pour télécharger les exemples. +> Installer les paquets `wget` pour télécharger les exemples. ```shell -$ yum install -y wget +$ dnf install -y wget ``` **Création des instances** @@ -795,40 +797,50 @@ Pour activer les sommes de contrôle, on utilise la variable `PGSETUP_INITDB_OPT Rappel : pour les versions de PostgreSQL inférieures à 12, l'activation des sommes de contrôle se fait à l'initialisation de l'instance. A partir de la version 12, elles peuvent être activées sur l’instance arrêtée par la commande : `pg_checksum --enable $PGDATA`. ```shell -$ export PGSETUP_INITDB_OPTIONS="--data-checksums" -``` -Création de l’instance en version 11. -```shell -$ /usr/pgsql-11/bin/postgresql-11-setup initdb +$ export PGSETUP_INITDB_OPTIONS='--data-checksums --lc-messages=C' ``` + Création de l’instance en version 13. + ```shell $ /usr/pgsql-13/bin/postgresql-13-setup initdb ``` -### Installation et configuration de l’instance en version 11 à migrer +Création de l’instance en version 16. + +```shell +$ /usr/pgsql-16/bin/postgresql-16-setup initdb +``` + +### Installation et configuration de l’instance en version 13 à migrer La suite du TP se fera sous l'utilisateur système `postgres`. + ```shell $ sudo -iu postgres ``` -> Démarrer l'instance PostgreSQL primaire (v11) (via la commande `pg_ctl`). +> Démarrer l'instance PostgreSQL primaire (v13) (via la commande `pg_ctl`). + ```shell -$ /usr/pgsql-11/bin/pg_ctl start -D /var/lib/pgsql/11/data/ +$ /usr/pgsql-13/bin/pg_ctl start -D /var/lib/pgsql/13/data/ ``` + > Télécharger et restaurer les bases exemples **cave** et **magasin** > Liens de téléchargement : https://dali.bo/tp_cave et https://dali.bo/tp_magasin On utilise l'utilitaire `wget` pour télécharger les dumps des bases.. + ```shell $ wget https://dali.bo/tp_cave -O ~/tp_cave.dump $ wget https://dali.bo/tp_magasin -O ~/tp_magasin.dump ``` -La restauration des dumps sur l'instance primaire (v11) se fait via la commande `pg_restore`. + +La restauration des dumps sur l'instance primaire (v13) se fait via la commande `pg_restore`. On crée d'abord les utilisateurs **caviste** et **magasinier** qui seront propriétaires des bases, puis on crée les bases **cave** et **magasin**, et enfin on restaure les dumps dans leurs bases respectives. -Pour la base **cave** : +Pour la base **cave** : + ```shell $ psql -c "SET password_encryption = 'scram-sha-256'; \ CREATE ROLE caviste LOGIN PASSWORD 'caviste';" @@ -837,6 +849,7 @@ $ pg_restore -d cave tp_cave.dump ``` Pour la base **magasin** : + ```shell $ psql -c "SET password_encryption = 'scram-sha-256'; \ CREATE ROLE magasinier LOGIN PASSWORD 'magasinier';" @@ -844,28 +857,42 @@ $ psql -c "CREATE DATABASE magasin OWNER magasinier;" $ pg_restore -d magasin tp_magasin.dump ``` -**Notre instance PostgreSQL version 11 est prête.** +Génération d'un base avec un peu de volume + +```shell +$ createdb pgbench +$ /usr/pgsql-13/bin/pgbench -i -s 500 pgbench +``` + +**Notre instance PostgreSQL version 13 est prête.** ### Mise en réplication logique des bases de l'instance -> Configurer l'instance primaire (v11) pour la préparer à la réplication logique. +> Configurer l'instance primaire (v13) pour la préparer à la réplication logique. + +Le paramètre `wal_level` de l'instance primaire (v13) est : `replica`. Les `WAL` contiennent des informations pour la réplication physique, mais pas assez d'informations pour la réplication logique. Il faut donc élever la valeur de `wal_level` à `logical`. -Le paramètre `wal_level` de l'instance primaire (v11) est : `replica`. Les `WAL` contiennent des informations pour la réplication physique, mais pas assez d'informations pour la réplication logique. Il faut donc élever la valeur de `wal_level` à `logical`. ```shell $ psql -c "SHOW wal_level"; wal_level ----------- replica ``` + Le paramètre est modifier via la commande SQL `ALTER SYSTEM`. On peut également le modifier dans le fichier `postgresql.conf` + ```shell $ psql -c "ALTER SYSTEM SET wal_level TO 'logical';" ``` + Le changement de ce paramètre induit un redémarrage de l'instance pour être pris en compte. + ```shell -$ /usr/pgsql-11/bin/pg_ctl restart -D /var/lib/pgsql/11/data/ +$ /usr/pgsql-13/bin/pg_ctl restart -D /var/lib/pgsql/13/data/ ``` + On peut vérifier le bon paramétrage une fois l'instance redémarrée. + ```shell $ psql -c "SHOW wal_level"; wal_level @@ -873,31 +900,36 @@ $ psql -c "SHOW wal_level"; logical ``` -> Configurer l'instance répliquée (v13) pour qu'elle écoute sur le port 5433. +> Configurer l'instance répliquée (v16) pour qu'elle écoute sur le port 5433. -Éditer le fichier de configuration `/var/lib/pgsql/13/data/postgresql.conf` et modifier le numéro de port (ne pas oublier de dé-commenter la ligne). +Éditer le fichier de configuration `/var/lib/pgsql/16/data/postgresql.conf` et modifier le numéro de port (ne pas oublier de dé-commenter la ligne). -Ou utiliser `sed` comme suit : +Ou utiliser `sed` comme suit : ```shell -$ sed -i "s/#port = 5432/port = 5433/" /var/lib/pgsql/13/data/postgresql.conf +$ sed -i "s/#port = 5432/port = 5433/" /var/lib/pgsql/16/data/postgresql.conf ``` -Démarrer l'instance répliquée (v13). + +Démarrer l'instance répliquée (v16). + ```shell -$ /usr/pgsql-13/bin/pg_ctl start -D /var/lib/pgsql/13/data/ +$ /usr/pgsql-16/bin/pg_ctl start -D /var/lib/pgsql/16/data/ ``` -> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v11). +> Récupérer le schéma des bases et les objets globaux de l'instance primaire (v13). On utilise l'utilitaire `pg_dumpall` avec l'option `--schema-only` qui va générer l'intégralité des schémas des bases, des utilisateurs, et des tablespaces de l'instance. Le script généré est au format SQL. + ```shell $ pg_dumpall --schema-only > ~/schema_replication_logique.sql ``` + Modifier le fichier si besoin notamment pour corriger les chemins des tablespaces qui seront peut-être différents sur la nouvelle instance. -> Créer les bases et objets globaux sur l'instance répliquée (v13). +> Créer les bases et objets globaux sur l'instance répliquée (v16). On importe le script généré ci-dessus sur l'instance répliquée. + ```shell $ psql -p5433 -f ~/schema_replication_logique.sql ``` @@ -905,16 +937,20 @@ $ psql -p5433 -f ~/schema_replication_logique.sql > Mettre en place la publication de toutes les tables des bases **cave** et **magasin**. Pour initialiser la réplication logique, il faut tout d'abord créer une publication pour toutes les tables de chaque base de l'instance que l'ont souhaite répliquer. On utilise l'ordre SQL `CREATE PUBLICATION`. + ```shell $ psql -d cave -c "CREATE PUBLICATION maj_cave_publication FOR ALL TABLES;" $ psql -d magasin -c "CREATE PUBLICATION maj_magasin_publication FOR ALL TABLES;" + +$ psql -d pgbench -c "CREATE PUBLICATION maj_pgbench_publication FOR ALL TABLES;" ``` -> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v13) +> Configurer la sécurité pour accepter les connexions de réplication de l’instance répliquée (v16) + +L'instance répliquée (v16) va se connecter à l'instance primaire (v13) à l'aide d'un slot de réplication. Pour cela il faut donner les droits de connexions entre les 2 instances. +On va tout d'abord créer un utilisateur pour cette réplication. -L'instance répliquée (v13) va se connecter à l'instance primaire (v11) à l'aide d'un slot de réplication. Pour cela il faut donner les droits de connexions entre les 2 instances. -On va tout d'abord créer un utilisateur pour cette réplication. ```shell $ psql -c "SET password_encryption ='scram-sha-256'; \ CREATE ROLE repliusr LOGIN REPLICATION SUPERUSER PASSWORD 'repliusr';" @@ -929,18 +965,20 @@ GRANT SELECT ON ALL TABLES IN SCHEMA public TO repliusr; *A répéter pour tous les schémas de toutes les bases à répliquer.* -Éditer le fichier de configuration de la sécurité `/var/lib/pgsql/11/data/pg_hba.conf` et ajouter les lignes suivantes en début de fichier. +Éditer le fichier de configuration de la sécurité `/var/lib/pgsql/13/data/pg_hba.conf` et ajouter les lignes suivantes en début de fichier. ```ini host all repliusr 127.0.0.1/32 scram-sha-256 host all repliusr ::1/128 scram-sha-256 ``` + Ne pas oublier de recharger la configuration, action nécessaire après toute modfication du fichier `pg_hba.conf`. + ```shell $ psql -c "select pg_reload_conf();" ``` -Sur le serveur hébergeant l'instance répliquée (v13), il faut également stocker les informations de connexions dans le fichier `.pgpass` pour que le processus de réplication puisse s'authentifier sans demander de mot de passe. +Sur le serveur hébergeant l'instance répliquée (v16), il faut également stocker les informations de connexions dans le fichier `.pgpass` pour que le processus de réplication puisse s'authentifier sans demander de mot de passe. Dans notre TP, c'est le même serveur qui héberge les 2 instances. ```shell @@ -948,27 +986,40 @@ $ echo "localhost:5432:*:repliusr:repliusr" >> ~/.pgpass $ chmod 600 ~/.pgpass ``` -### Réplication des bases sur l’instance répliquée (v13) +### Réplication des bases sur l’instance répliquée (v16) > Mettre en place les abonnements aux publications des bases **cave** et **magasin**. -Pour finaliser la réplication logique, il faut maintenant abonner notre réplicat (v13) aux publications de notre instance primaire (v11). On utilise l'ordre SQL `CREATE SUBSCRIPTION` avec les indications de connexion à l'instance primaire, ainsi que le nom de la publication à laquelle on veut s'abonner. +Pour finaliser la réplication logique, il faut maintenant abonner notre réplicat (v16) aux publications de notre instance primaire (v13). On utilise l'ordre SQL `CREATE SUBSCRIPTION` avec les indications de connexion à l'instance primaire, ainsi que le nom de la publication à laquelle on veut s'abonner. Pour la base **cave** : + ```shell $ psql -p5433 -d cave -c "CREATE SUBSCRIPTION maj_cave_subscription \ CONNECTION 'host=localhost port=5432 user=repliusr dbname=cave' \ PUBLICATION maj_cave_publication" ``` + Pour la base **magasin** : + ```shell $ psql -p5433 -d magasin -c "CREATE SUBSCRIPTION maj_magasin_subscription \ CONNECTION 'host=localhost port=5432 user=repliusr dbname=magasin' \ -PUBLICATION maj_magasin_publication" +PUBLICATION maj_magasin_publication \ +WITH (enabled=false)" +``` + +Pour la base **pgbench** : + +```shell +$ psql -p5433 -d pgbench -c "CREATE SUBSCRIPTION maj_pgbench_subscription \ +CONNECTION 'host=localhost port=5432 user=repliusr dbname=pgbench' \ +PUBLICATION maj_pgbench_publication" ``` -Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquée sur les tables du réplicat. -On pourrait créer l'abonnement sans copier les données initiales et copier les données initiales dans un second temps avec les commandes suivantes. +Une fois l'abonnement créé, les données initiales des bases commencent immédiatement à être répliquée sur les tables du réplicat. +On pourrait créer l'abonnement sans copier les données initiales et dans ucopier les données initialesn second temps avec les commandes suivantes. + ```sql CREATE SUBSCRIPTION ... CONNECTION ... PUBLICATION ... WITH copy_data(false); -- puis @@ -977,7 +1028,15 @@ ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH copy_data(true); > Surveiller le bon déroulement de la réplication initiale. -Afin de vérifier si la réplication initiale est bien terminée, la fonction suivante ne doit renvoyer aucune ligne. +La réplication sur la base magasin est désactivée, activons la maintenant. + +```shell +$ psql -p5433 -d magasin \ +-c "ALTER SUBSCRIPTION maj_magasin_subscription ENABLE;" +``` + +Afin de vérifier si la réplication initiale est bien terminée, la fonction suivante ne doit renvoyer aucune ligne. + ```shell $ psql -p5433 -d magasin \ -c "SELECT * FROM pg_subscription_rel WHERE srsubstate <> 'r';" @@ -985,58 +1044,85 @@ $ psql -p5433 -d magasin \ ### "Promotion" de l'instance répliquée ->Mettre à jour les séquences de l'instance répliquée (v13). +> Mettre à jour les séquences de l'instance répliquée (v16). -La réplication logique ne réplique pas l'état des séquences. Si des enregistrementes ont été insérés dans l'instance primaire (v11) après avoir exporté le schéma (voir plus haut), alors les numéros des séquences entre le primaire et le réplicat ne sont plus en phase. -Pour cela avant d'ouvrir les connexions à l'applicatif, il est impératif de mettre à jour les séquences sur l'instance répliquée (v13). +La réplication logique ne réplique pas l'état des séquences. Si des enregistrementes ont été insérés dans l'instance primaire (v13) après avoir exporté le schéma (voir plus haut), alors les numéros des séquences entre le primaire et le réplicat ne sont plus en phase. +Pour cela avant d'ouvrir les connexions à l'applicatif, il est impératif de mettre à jour les séquences sur l'instance répliquée (v16). -Script de récupération des séquences sur le primaire (v11). +Script de récupération des séquences sur le primaire (v13). Pour la base **cave**. + ```shell $ psql cave -t -o ~/maj_sequences_cave.sql ``` + ```sql SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' || last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' -FROM pg_class c +FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind='S' \gexec +exit; ``` + Pour la base **magasin**. + ```shell $ psql magasin -t -o ~/maj_sequences_magasin.sql ``` + +```sql +SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' +|| last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' +FROM pg_class c + INNER JOIN pg_namespace n + ON c.relnamespace = n.oid +WHERE c.relkind='S' \gexec +exit; +``` +Pour la base **pgbench**. + +```shell +$ psql pgbench -t -o ~/maj_sequences_pgbench.sql +``` + ```sql SELECT 'SELECT ''SELECT setval(''''' || n.nspname || '.' || c.relname || ''''','' || last_value ||'');'' FROM "' || n.nspname || '"."' || c.relname || '";' -FROM pg_class c +FROM pg_class c INNER JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relkind='S' \gexec +exit; ``` -Les séquences sont à réinitialiser sur l'instance répliquée (v13), afin d'éviter tout risque d'erreur du type `duplicated key` lors des opérations d'ajout d'enregistrements dans les tables. +Les séquences sont à réinitialiser sur l'instance répliquée (v16), afin d'éviter tout risque d'erreur du type `duplicated key` lors des opérations d'ajout d'enregistrements dans les tables. + ```shell $ psql -p5433 cave -f ~/maj_sequences_cave.sql $ psql -p5433 magasin -f ~/maj_sequences_magasin.sql +$ psql -p5433 pgbench -f ~/maj_sequences_pgbench.sql ``` -> Nettoyer les abonnements de l'instance répliquée (v13) . +> Nettoyer les abonnements de l'instance répliquée (v16) . + +Penser à supprimer la subscription surtout si l'ancienne production se trouverait redémarrée. -Penser à supprimer la subscription surtout si l'ancienne production se trouverait redémarrée. ```shell $ psql -p5433 cave -c "DROP SUBSCRIPTION maj_cave_subscription;" $ psql -p5433 magasin -c "DROP SUBSCRIPTION maj_magasin_subscription;" +$ psql -p5433 pgbench -c "DROP SUBSCRIPTION maj_pgbench_subscription;" ``` -> Nettoyer les publications (si besoin) de l’instance primaire (v11). +> Nettoyer les publications (si besoin) de l’instance primaire (v13). + +Les publications peuvent être supprimées sur l'ancien si elles ne servent plus : attention si vous avez d'autres abonnés sur ces publications, elle ne doit pas être supprimée. -Les publications peuvent être supprimées sur l'ancien si elles ne servent plus : attention si vous avez d'autres abonnés sur ces publications, elle ne doit pas être supprimée (un. ```shell $ psql cave -c "DROP PUBLICATION maj_cave_publication;" $ psql magasin -c "DROP PUBLICATION maj_magasin_publication;" +$ psql pgbench -c "DROP PUBLICATION maj_pgbench_publication;" ``` -
    From 11925218559739f61e8461699cf81f50f18f7293 Mon Sep 17 00:00:00 2001 From: mathieu Date: Fri, 2 Feb 2024 14:52:42 +0100 Subject: [PATCH 4/4] =?UTF-8?q?derni=C3=A8re=20modif?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maj_replication_logique.md | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/fr/atelier-maj-repli-logique/maj_replication_logique.md b/fr/atelier-maj-repli-logique/maj_replication_logique.md index e7c0b0d..a2eb36e 100644 --- a/fr/atelier-maj-repli-logique/maj_replication_logique.md +++ b/fr/atelier-maj-repli-logique/maj_replication_logique.md @@ -333,12 +333,40 @@ Enfin, la réplication logique a un coût en CPU (sur les deux instances concern ---
    -| Outil | Coupure production | Retour arrière | Fragmentation | -| ---------------------- | ------------------------------------------- | ----------------- | --------------- | -| pg_dump / pg_restore | Elevé = sauvegarde + restauration | OUI | NON | -| pg_upgrade | Moyen = copie physique des données | OUI | OUI | -| pg_upgrade | Court = mise à jour directe des fichiers | NON | OUI | -| réplication logique | Très Court = mais préparation en amont | OUI | OUI | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OutilCoupure productionRetour arrièreFragmentation
    pg_dump / pg_restoreÉlevé = sauvegarde + restaurationOUINON
    pg_upgradeMoyen = copie physique des donnéesOUIOUI
    pg_upgradeCourt = mise à jour directe des fichiersNONOUI
    réplication logiqueTrès Court = mais préparation en amontOUIOUI
    +