PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Mise à niveau de votre base de données vers PostgreSQL version 10 - Ce que vous devez savoir

Alors que de plus en plus de publications sur PostgreSQL 11 apparaissent sur le Web, vous pouvez vous sentir obsolète lorsque vous utilisez PostgreSQL 9. Bien que la version de PostgreSQL 10 n'ait eu lieu qu'il y a quelques mois à peine, les gens parlent déjà de la prochaine version. Les choses bougent, vous ne voulez donc pas être laissé pour compte. Dans ce blog, nous discuterons de ce que vous devez savoir pour passer à la dernière version, Postgres 10.

Options de mise à niveau

La première chose que vous devez savoir avant de commencer est qu'il existe plusieurs façons de procéder à la mise à niveau :

  1. Traditionnel pg_dumpall(pg_dump) / pg_restore(psql)
  2. Pg_upgrade traditionnel
  3. Réplication basée sur des déclencheurs (Slony, auto-écrit)
  4. Utiliser la réplication pglogical

Pourquoi y a-t-il une telle variété ? Car chacun a une histoire différente, nécessitant des efforts différents pour se mettre en place et offrant des services différents. Regardons de plus près chacun d'eux.

Dump/Restauration traditionnel

pg_dump t > /tmp/f
psql -p 5433 -f /tmp/f

Le vidage/restauration traditionnel prend le plus de temps à se terminer et pourtant, c'est souvent un choix populaire pour ceux qui peuvent se permettre le temps d'arrêt. Tout d'abord, c'est aussi simple que d'effectuer une sauvegarde logique et de la restaurer dans une nouvelle version supérieure de la base de données. Vous pourriez dire que ce n'est pas vraiment une mise à niveau, car vous "importez" vos données dans une "nouvelle structure". En conséquence, vous vous retrouverez avec deux configurations - une ancienne (version inférieure) et la nouvelle mise à niveau. Si le processus de restauration se termine sans erreur, vous y êtes à peu près. Sinon, vous devez modifier l'ancien cluster existant pour éliminer les erreurs et recommencer le processus.

Si vous utilisez psql pour l'importation, vous devrez peut-être également créer vous-même des scripts de préchargement à exécuter sur la nouvelle configuration avant la migration. Par exemple, vous voudriez pg_dumpall -g pour obtenir une liste des rôles nécessaires à préparer dans la nouvelle configuration, ou inversement, exécutez pg_dump -x pour ignorer les autorisations de l'ancienne. Ce processus est assez simple sur de petites bases de données, la complexité augmente avec la taille et la complexité de votre structure de base de données et dépend des fonctionnalités que vous avez configurées. Fondamentalement, pour que cette méthode réussisse, vous devez continuer à essayer et à corriger jusqu'à ce que la mise à niveau soit réussie.

Les avantages de l'utilisation de cette méthode incluent...

  • Bien que vous puissiez passer beaucoup de temps avec une sauvegarde que vous avez effectuée, la charge sur l'ancien serveur est aussi faible qu'une seule sauvegarde.
  • Cette méthode est principalement une séquence de sauvegarde-restauration (potentiellement avec des sorts, des chansons et des percussions)
  • Cette méthode est la méthode de mise à niveau la plus ancienne et a été vérifiée par de NOMBREUSES personnes

Lorsque vous terminez enfin la mise à niveau, vous devez soit arrêter l'ancien serveur, soit accepter une perte de données (ou bien rejouer le DML qui s'est produit sur l'ancien serveur lors de la restauration d'une sauvegarde sur le nouveau serveur). Et le temps passé à le faire est relatif à la taille de votre base de données.

Vous pouvez, bien sûr, commencer "à utiliser" une nouvelle base de données avant la fin de la restauration (en particulier avant que tous les index ne soient construits - souvent, le plus de temps que cela prend est pour les index). Mais néanmoins, de tels temps d'arrêt sont souvent inacceptables.

pg_upgrade traditionnel

MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/initdb -D tl0 >/tmp/suppressing_to_save_screen_space_read_it

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
MacBook-Air:~ vao$ /usr/local/Cellar/postgresql/10.2/bin/pg_upgrade -b /usr/local/Cellar/postgresql/9.5.3/bin -B /usr/local/Cellar/postgresql/10.2/bin -d t -D tl0 | tail
Creating script to delete old cluster                        ok

Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
    ./analyze_new_cluster.sh

Running this script will delete the old cluster’s data files:
    ./delete_old_cluster.sh

Le pg_upgrade traditionnel a été créé pour raccourcir le temps nécessaire à la mise à niveau vers une version majeure. Selon le nombre de relations que vous avez, cela peut prendre quelques minutes (des secondes dans des cas ridicules, comme une base de données de table et des heures dans les "cas opposés"), en particulier avec l'argument --link.

La séquence de préparation diffère légèrement de la première méthode de mise à niveau. Afin de modéliser la mise à niveau et ainsi de vérifier si c'est possible, vous devez construire une réplication en continu ou récupérer un serveur de secours à partir des WAL. Pourquoi est-ce si compliqué ? Vous voulez être sûr de tester la mise à niveau sur une base de données aussi proche que vous l'aviez à l'origine. La réplication "binaire" ou PITR va nous aider ici. Après avoir terminé la récupération et recovery_target_action =promouvoir (PITR) ou promu l'esclave nouvellement construit (pg_ctl promouvoir ou placer un fichier déclencheur) (réplication en continu), vous pouvez alors essayer d'exécuter pg_upgrade. Vérifier le pg_upgrade_internal.log vous donnera une idée si le processus a réussi ou non. De plus, vous avez la même approche d'essai et de correction que la méthode précédente. Vous enregistrez les actions effectuées sur la base de données de test dans un script, jusqu'à ce que vous la pg_upgradiez avec succès. De plus, vous pouvez détruire les tests dont vous n'avez plus besoin base de données mise à niveau, exécutez le script enregistré pour préparer la base de données d'origine pour effectuer la mise à niveau.

Les avantages de l'utilisation de cette méthode incluent…

  • Temps d'arrêt plus court que la sauvegarde/restauration logique
  • Un processus soigné :pg_upgrade met à niveau la base de données d'origine avec les données et la structure existantes
  • A été beaucoup utilisé dans le passé et serait toujours la préférence pour la plupart des DBA exécutant une version inférieure à 9.4 (ce qui permet d'utiliser pglogical)

Les inconvénients de l'utilisation de cette méthode incluent…

  • Nécessite un temps d'arrêt

Réplication basée sur des déclencheurs

En supposant que la version 10 se trouve sur le port 5433 et que la même table est préparée :

db=# create server upgrade_to_10 foreign data wrapper postgres_fdw options (port '5433', dbname 'dbl0');
CREATE SERVER
Time: 9.135 ms
db=# create user mapping for vao SERVER upgrade_to_10 options (user 'vao');
CREATE USER MAPPING
Time: 8.741 ms
db=# create foreign table rl0 (pk int, t text) server upgrade_to_10 options (table_name 'r');
CREATE FOREIGN TABLE
Time: 9.358 ms

Il s'agit d'un fn() extrêmement simpliste et d'un déclencheur pour une réplication logique très basique. Une telle approche est si primitive qu'elle ne fonctionnera pas avec des clés étrangères, mais le code est court :

db=# create or replace function tf() returns trigger as $$
begin
 if TG_0P = 'INSERT' then
   insert into r10 select NEW.*;
 elseif TG_0P = 'UPDATE' then
   delete from rl0 where pk = NEW.pk;
   insert into rl0 select NEW.*;
 elseif TG_0P = 'DELETE' then
   delete from rl0 where pk = OLD.pk;
 end if;
return case when TG_0P in ('INSERT','UPDATE') then NEW else OLD end;
end;
SS language plpgsql;
CREATE FUNCTION
Time: 8.531 ms
db=# create trigger t before insert or update or delete on r for each row execute procedure tf(); CREATE TRIGGER
Time: 8.813 ms

Exemple :

db=# insert into r(t) select chr(g) from generate_series(70,75) g;
INSERT 0 6
Time: 12.621 ms
db=# update r set t = 'updated' where pk=2;
UPDATE 1
Time: 10.398 ms
db=# delete from r where pk=1;
DELETE 1
Time: 9.634 ms
db=# select * from r;
 pk |    t
----+---------
  3 | H
  4 | I
  5 | J
  6 | K
  2 | updated
(5 rows)

Time: 9.026 ms
db=# select * from rl0;
 pk |    t
----+---------
  3 | H
  4 | I
  5 | J
  6 | K
  2 | updated
(5 rows)

Time: 1.201 ms

Enfin, vérifions que nous répliquons vers une autre base de données :

db=# select *,current_setting('port') from dblink('upgrade.to.lO','select setting from pg_settings where name=$$port$$') as t(setting_10 text);
 setting_10 | currerrt.setting
------------+------------------
 5433       | 5432
(l row)

Time: 23.633 ms

J'appellerais cette méthode la plus exotique. À la fois pour le fait qu'avec la réplication en continu et plus tard avec pglogical, l'utilisation de la réplication basée sur les déclencheurs devient moins populaire. Il a une charge plus élevée sur le maître, une complexité accrue lors de la configuration et un manque de documentation bien structurée. Il n'y a pas de préparation (en tant que telle) du processus ici, car vous voulez simplement configurer Slony sur différentes versions majeures.

Les avantages de l'utilisation de cette méthode incluent…

  • Aucune sauvegarde n'est nécessaire et aucun temps d'arrêt n'est requis (surtout si vous êtes derrière un pgbouncer ou un haproxy).

Les inconvénients de l'utilisation de cette méthode incluent…

  • Grande complexité de la configuration
  • Manque de documentation structurée
  • Pas très populaire :moins de cas d'utilisateurs à étudier (et à partager)

Dans le même ordre d'idées, la réplication de déclencheur auto-écrite est un autre moyen possible de mise à niveau. Bien que l'idée soit la même (vous créez une nouvelle base de données de version supérieure et configurez des déclencheurs sur la version inférieure pour lui envoyer des données modifiées), la configuration auto-écrite sera claire pour vous. Vous n'aurez pas besoin d'assistance et utiliserez donc potentiellement moins de ressources lors de son exécution. Bien sûr, pour la même raison, vous vous retrouverez probablement avec certaines fonctionnalités manquantes ou ne fonctionnant pas comme prévu. Si vous avez plusieurs tables à déplacer vers de nouvelles versions, une telle option vous prendra probablement moins de temps et, si elle est bien faite, consommera peut-être moins de ressources. En prime, vous pouvez combiner certaines transformations ETL avec la mise à niveau, en passant à une nouvelle version sans temps d'arrêt.

Téléchargez le livre blanc aujourd'hui PostgreSQL Management &Automation with ClusterControlDécouvrez ce que vous devez savoir pour déployer, surveiller, gérer et faire évoluer PostgreSQLTélécharger le livre blanc

Réplication logique avec pglogical

C'est une nouvelle façon très prometteuse de mettre à jour Postgres. L'idée est de mettre en place une réplication logique entre différentes versions majeures et d'avoir littéralement une base de données parallèle, de version supérieure (ou inférieure) exécutant les mêmes données. Lorsque vous êtes prêt, il vous suffit de basculer les connexions avec votre application de l'ancienne à la nouvelle.

Les avantages de l'utilisation de cette méthode incluent…

  • En principe, aucun temps d'arrêt
  • Fonctionnalité extrêmement prometteuse, beaucoup moins d'efforts que la réplication basée sur des déclencheurs

Les inconvénients de l'utilisation de cette méthode incluent…

  • Toujours très complexe à configurer (en particulier pour les anciennes versions)
  • Manque de documentation structurée
  • Pas très populaire :moins de cas d'utilisateurs à étudier (et à partager)

Les migrations de versions majeures basées sur les déclencheurs et sur la réplication pglogical peuvent être utilisées pour rétrograder la version (jusqu'à une valeur raisonnable bien sûr, par exemple, pglogical n'est disponible qu'à partir de la version 9.4 et la réplication du déclencheur devient de plus en plus difficile à configurer comme la version que vous voulez rétrograder pour vieillir).

Actions à entreprendre avant la mise à niveau

  • Effectuer une sauvegarde
  • Assurez-vous qu'il y a suffisamment d'espace disque
  • Vérifiez vos extensions (il est important que tous les modules externes soient également compatibles binaires, bien que cela ne puisse pas être vérifié par pg_upgrade)
  • Assurez-vous d'utiliser les mêmes datcollate et datctype et ainsi de suite (vérifiez pg_database) sur la nouvelle base de données
  • Vérifiez (DDL + Drop) les vues, les fonctions, les extensions et les types qui pourraient interrompre la mise à niveau
  • Utilisez --check avant vraiment pg_upgrade

Actions à entreprendre après la mise à niveau

  • Consultez pg_upgrade_server.log (si vous avez utilisé pg_upgrade)
  • Exécuter l'analyse sur les bases de données mises à jour (facultatif, comme cela serait fait par autovacuum, mais vous pouvez choisir quelles relations doivent être analysées en premier si vous le faites vous-même)
  • Préchauffer les pages populaires (facultatif, mais peut améliorer les performances au début)

Conclusion

Voici quelques notes générales qu'il est bon de connaître avant de décider de passer à PostgreSQL version 10…

  • pg_sequences ont été introduits, modifiant le comportement de SELECT * FROM sequence_name auparavant populaire - désormais uniquement last_value | log_cnt | is_called sont renvoyés, vous cachant les "propriétés initiales" (ajustez tout code qui repose sur un changement de comportement)
  • pg_basebackup diffuse les WAL par défaut. Après la mise à niveau, vous devrez peut-être modifier vos scripts (option -x supprimée)
  • Toutes les actions pg_ctl sont en attente d'achèvement. Auparavant, vous deviez ajouter -w pour éviter d'essayer de vous connecter à la base de données juste après le démarrage de pg_ctl. Ainsi, si vous souhaitez toujours utiliser le démarrage ou l'arrêt "asynchrone", vous devez le marquer explicitement avec -W. Vous devrez peut-être ajuster vos scripts pour qu'ils se comportent comme prévu.
  • Tous les scripts d'archivage des WAL ou de surveillance/contrôle de la réplication en continu ou du PITR doivent être revus, pour les ajuster aux noms xlog modifiés. Par exemple. select * from pg_is_xlog_replay_paused() ne vous montrera plus l'état de la relecture des WAL esclaves - vous devez utiliser select * from pg_is_wal_replay_paused() à la place. Aussi cp /blah/pg_xlog/* doit être remplacé par /blah/pg_wal/* et ainsi de suite pour toutes les occurrences de pg_xlog. La raison d'un changement aussi massif et non compatible avec les versions antérieures est de résoudre le cas où un débutant supprime les journaux à écriture anticipée pour "nettoyer de l'espace" en supprimant les journaux et perd la base de données.
  • Ajuster les scripts à l'aide de pg_stat_replication pour les nouveaux noms (emplacement changé en lsn)
  • Ajustez les requêtes avec des fonctions de renvoi définies si nécessaire
  • Si vous utilisiez pglogical comme extension avant la version 10, vous devrez peut-être ajuster la valeur changeante de pg_hba.conf entre les "colonnes"
  • Ajustez les scripts pour un nouveau nom de pg_log qui est log, donc quelque chose comme find /pg_data/pg_log/postgresql-*  -mmin +$((60*48)) -type f -exec bash /blah/moveto.s3 .sh {} \; travaillerait. Bien sûr, vous pouvez créer un lien symbolique à la place, mais il faudrait prendre des mesures pour trouver les journaux à l'emplacement par défaut. Un autre petit changement aux valeurs par défaut est log_line_prefix - si votre expression régulière dépendait d'un certain format, vous devez l'ajuster.
  • Si vous utilisiez encore des mots de passe non chiffrés dans vos bases de données Postgres, cette version complète le supprime. Il est donc temps de régler les choses pour ceux qui comptaient sur --unencrypted...
  • Le reste des modifications incompatibles avec les versions précédentes sont soit trop récentes pour être référencées dans beaucoup de code (min_parallel_relation_size), soit trop anciennes (tsearch2 externe), soit trop exotiques (suppression de la prise en charge des horodatages à virgule flottante dans la construction), donc nous les sauterons. Bien sûr, ils sont répertoriés sur la page de publication.
  • Comme c'était le cas avec les versions 9.5 à 9.6, vous devrez peut-être ajuster vos scripts pour interroger pg_stat_activity (une nouvelle colonne et de nouvelles valeurs possibles)
  • Si vous enregistriez/analysiez la sortie verbeuse du vide, vous devrez peut-être ajuster votre code
  • Vous voudrez peut-être également jeter un œil à la nouvelle mise en œuvre du partitionnement :vous voudrez peut-être refactoriser votre "ensemble" existant pour vous conformer aux nouvelles "normes"
  • vérifier la chronologie (sera réinitialisée pour la nouvelle base de données si vous pg_upgrade)

En dehors de ces étapes que vous devez connaître pour passer à la version 10, de nombreux éléments font de cette version une version très attendue. Veuillez lire la section sur les changements dans les notes de version ou le blog depesz.