pg_upgrade (auparavant appelé pg_migrator) permet la mise à jour des fichiers de données d'une version majeure de PostgreSQL™ vers une autre version majeure sans nécessiter la partie sauvegarde/restauration typiquement requise pour les mises à jour majeures, par exemple de la version 8.4.7 à la version majeure courante de PostgreSQL™. Cet outil n'est pas utile pour les mises à jour mineures, par exemple pour une migration de la 9.0.1 à la 9.0.4.
Les versions majeures de PostgreSQL ajoutent régulièrement de nouvelles fonctionnalités qui modifient la composition des tables systèmes. Par contre, le format de stockage des données change rarement. pg_upgrade utilise cette information pour réaliser des mises à jour rapides en créant les nouvelles tables systèmes et en réutilisant les anciens fichiers de données utilisateurs. Si une version majeure future change le format des données d'une façon qui rend l'ancien format illisible, pg_upgrade ne sera pas utilisable pour ces mises à jour. (La communauté tente d'éviter ce type de situation.)
pg_upgrade fait de son mieux pour s'assurer que les clusters, ancien et nouveau, soient compatibles binairement, c'est-à-dire en vérificant les paramètres de temps modifiables à la compilation, en incluant les binaires 32/64 bits. Il est important que tout module externe soit aussi compatible binairement, bien que cela ne soit pas vérifié par pg_upgrade.
pg_upgrade supporte la mise à jour de version 8.3.X et ultérieures vers la dernière version majeure de PostgreSQL™, ceci incluant les versions intermédiaires (snapshots) et les versions alpha.
pg_upgrade accepte les arguments suivant en ligne de commande :
indique le répertoire des exécutables de l'ancienne instance ; variable d'environnement OLDBINDIR
indique le répertoire des exécutables de la nouvelle instance ; variable d'environnement NEWBINDIR
vérifie seulement les instances, ne modifie pas les données
indique le répertoire des données de l'ancienne instance ; variable d'environnement OLDDATADIR
indique le répertoire des données de la nouvelle instance ; variable d'environnement NEWDATADIR
active les traces de débogage
enregistre les traces de débogage dans un fichier
utilise des liens plutôt que de copier les fichiers vers la nouvelle instance
trace l'activité de la session dans un fichier
indique le numéro de port de l'ancienne instance ; variable d'environnement PGPORT
indique le numéro de port de la nouvelle instance ; variable d'environnement PGPORT
superutilisateur de l'instance ;variable d'environnement PGUSER
active la sortie verbeuse
affiche la version puis quitte
affiche l'aide puis quitte
Si nécessaire, déplacez l'ancienne instance
Si vous utilisez un répertoire d'installation spécifique à la version, par exemple /opt/PostgreSQL/8.4, vous n'avez pas besoin de déplacer l'ancien répertoire de l'instance. Les installeurs one-click utilisent tous des répertoires d'installation spécifiques à la version.
Si votre répertoire d'installation n'est pas spécifique à la version, par exemple /usr/local/pgsql, il est nécessaire de déplacer le répertoire d'installation actuelle de PostgreSQL pour qu'il n'interfère pas avec la nouvelle installation de PostgreSQL™. Une fois que le serveur actuel PostgreSQL™ est arrêté, il est bon de renommer le répertoire d'installation de PostgreSQL ; en supposant que l'ancien répertoire est /usr/local/pgsql, vous pouvez saisir ceci :
mv /usr/local/pgsql /usr/local/pgsql.old
pour renommer le répertoire.
Pour une installation par les sources, construisez la nouvelle version
Construisez la nouvelle version de PostgreSQL avec des options de compilation compatibles avec l'ancienne instance. pg_upgrade utilisera pg_controldata pour vérifier que tous les paramètres sont compatibles avant de lancer la mise à jour.
Installez les nouveaux exécutables de PostgreSQL
Installez les nouveaux exécutables du serveur ainsi que les fichiers de support. Vous pouvez utiliser les même numéros de port, habituellement le 5432, car l'ancienne et la nouvelle instance ne seront pas exécutées en même temps.
Pour les installations à partir des sources, si vous préférez installer le nouveau serveur dans un emplacement particulier, utilisez le mot clé prefix :
gmake prefix=/usr/local/pgsql.new install
Installez pg_upgrade et pg_upgrade_support
Installez l'exécutable pg_upgrade et la bibliothèque pg_upgrade_support dans la nouvelle instance PostgreSQL
Initialisez la nouvelle instance PostgreSQL
Initialisez la nouvelle instance avec initdb. Encore une fois, utilisez des options d'initdb qui correspondent à celles de l'ancienne instance. Beaucoup d'installeurs font cette étape automatiquement. Il n'est pas nécessaire de démarrer la nouvelle instance.
Installez les fichiers objets partagés personnalisés (ou DLL)
Installez tous fichiers objets partagés personnalisés (ou DLL) utilisés par l'ancien cluster dans le nouveau cluster, par exemple pgcrypto.so, qu'ils proviennent des modules contrib ou de toute autre source. N'installez pas les définitions du schéma, par exemple pgcrypto.sql, car elles seront aussi mises à jour à partir de l'ancien cluster.
Ajustez l'authentification
pg_upgrade se connectera à l'ancien et au nouveau serveurs plusieurs fois. Vous devez donc configurer l'authentification à trust dans pg_hba.conf ou, si vous utilisez l'authentification md5, configurez un fichier ~/.pgpass (voir Section 31.14, « Fichier de mots de passe » pour les détails) pour éviter d'avoir à saisir de façon répétée le mot de passe.
Arrêtez les deux serveurs
Assurez-vous que les deux serveurs de bases de données sont stoppés. Pour cela, vous pouvez utiliser la commande suivante sous Unix :
pg_ctl -D /opt/PostgreSQL/8.4 stop pg_ctl -D /opt/PostgreSQL/9.0 stop
et la commande suivante sous Windows (en utilisant les bons noms de service) :
NET STOP postgresql-8.4 NET STOP postgresql-9.0
ou encore :
NET STOP pgsql-8.3 (PostgreSQL™ 8.3 et antérieurs
utilisent un autre nom de service)
Exécutez pg_upgrade
Exécutez toujours le binaire pg_upgrade dans le nouveau serveur, pas l'ancien. pg_upgrade nécessite de spécifier les repértoires de l'instance (PGDATA) et des exécutables pour l'ancienne et la nouvelle instances (bin). Vous pouvez aussi indiquer des valeurs pour l'utilisateur et le port, et si vous voulez que les données soient ajoutées par lien ou par copie (cette dernière étant la valeur par défaut).
Si vous utilisez les liens, la mise à jour sera bien plus rapide (pas de copie de données), mais vous ne serez plus capable d'accéder à votre ancienne instance une fois que vous aurez démarré la nouvelle instance après la mise à jour. Le mode des liens nécessite aussi que les répertoires des données de l'ancienne et de la nouvelle instances soient situés sur le même système de fichiers. Voir pg_upgrade --help pour une liste complète des options.
Pour les utilisateurs Windows, vous devez être connecté avec un compte administrateur, puis lancé un shell en tant qu'utilisateur postgres et configuré la variable PATH correctement :
RUNAS /USER:postgres "CMD.EXE" SET PATH=%PATH%;C:\Program Files\PostgreSQL\9.0\bin;
Enfin, vous lancez pg_upgrade avec les noms des répertoires entre guillemets doubles, par exemple :
pg_upgrade.exe --old-datadir "C:/Program Files/PostgreSQL/8.4/data" --new-datadir "C:/Program Files/PostgreSQL/9.0/data" --old-bindir "C:/Program Files/PostgreSQL/8.4/bin" --new-bindir "C:/Program Files/PostgreSQL/9.0/bin"
Une fois lancé, pg_upgrade vérifiera que les deux instances sont compatibles puis lancera la mise à jour. vous pouvez utiliser pg_upgrade --check pour ne faire que les vérifications, même si l'ancienne installation est en cours d'exécution. pg_upgrade --check indiquera aussi tout ajustement manuel que vous devrez faire après la mise à jour. pg_upgrade réclame des droits en écriture dans le répertoire courant.
Évidemment, personne ne doit accéder aux instances pendant la mise à jour. Pensez à utiliser un numéro de port différent de celui par défaut (par exemple 50432) pour l'ancienne et la nouvelle instance pour éviter des connexions clients inattendues lors de la mise à jour.
Si une erreur survient lors de la restauration du schéma de la base de données, pg_upgrade quittera et vous devrez retourner sur l'ancienne instance comme indiqué dans Étape 14. Pour essayer de nouveau pg_upgrade, vous aurez besoin de modifier l'ancienne instance pour que la restauration du schéma par pg_upgrade réussisse. Si le problème est dû à un module contrib, vous pourriez avoir besoin de désinstaller le module contrib à partir de l'ancienne instance et de l'installer sur la nouvelle après la mise à jour en espérant que le module n'est pas utilisé pour stocker des données de l'utilisateur.
Restaurez pg_hba.conf
Si vous avez modifié pg_hba.conf pour utiliser trust, restaurez-le à sa configuration d'origine.
Traitement post-mise à jour
Si un traitement post-mise à jour est requis, pg_upgrade lancera des avertissements à la fin de son travail. Il générera aussi des fichiers de script à exécuter par l'administrateur. Les fichiers de script se connecteront à chaque base de données pour réaliser un traitement post-mise à jour. Chaque script doit être exécuté avec la commande suivante :
psql --username postgres --file script.sql postgres
Ces scripts peuvent être exécutés dans n'importe quel ordre et peuvent être supprimés une fois qu'ils ont été exécutés.
En général, il n'est pas prudent d'accéder aux tables référencées dans les scripts de reconstruction tant que ses scripts n'ont pas été exécutés entièrement ; le faire malgré tout pourrait amener des résultats incorrects ou des contre-performances. Les tables non référencées dans les scripts de reconstruction peuvent être utilisées immédiatement.
Statistiques
Comme les statistiques de l'optimiseur ne sont pas transférées par pg_upgrade, il vous sera demandé d'exécuter une commande pour regénérer les informations statistiques à la fin de la mise à jour.
Supprimez l'ancienne instance
Une fois que vous être satisfait par la mise à jour, vous pouvez supprimer les répertoires de données de l'ancienne instance en exécutant le script mentionné à la fin de pg_upgrade. Vous devrez supprimer manuellement les anciens répertoires d'installation, par exemple bin, share.
Retourner sur l'ancienne instance
Si, après avoir exécuté pg_upgrade, vous souhaitez retourner à l'ancienne instance, il existe plusieurs options.
Si vous avez exécuté pg_upgrade avec l'option --check, aucune modification n'a eu lieu sur l'ancienne instance, donc vous pouvez la réutiliser immédiatement.
Si vous avez exécuté pg_upgrade avec l'option --link, les fichiers de données sont partagés entre l'ancienne et la nouvelle instances. Si vous avez démarré la nouvelle instance, le nouveau serveur a écrit dans les fichiers partagés et il est du coup dangereux d'utiliser l'ancienne instance.
Si vous avez exécuté pg_upgrade sans l'option --link ou si vous n'avez pas lancé le nouveau serveur, l'ancienne instance n'a pas été modifiée mais un suffixe .old a été ajouté au fichier $PGDATA/global/pg_control et peut-être aux répertoires des tablespaces. Pour réutiliser l'ancienne instance, supprimez le suffixe .old du fichier $PGDATA/global/pg_control. De plus, si vous mettez à jour d'une version 8.4 ou antérieure, supprimez les répertoires des tablespaces créés par l'outil de mise à jour et supprimez le suffixe .old du nom des répertoires des tablespaces ; après cela, vous pouvez redémarré l'ancienne instance.
La mise à jour à partir de PostgreSQL 8.3 comporte quelques restrictions supplémentaires. Par exemple, pg_upgrade ne fonctionnera pas pour une mise à jour à partir d'une 8.3 si une colonne utilisateur est définie comme :
le type de données tsquery
le type de données name et qu'il ne s'agit pas de la première colonne
Vous devez supprimer ce type de colonnes et les mettre à jour manuellement.
pg_upgrade ne fonctionnera pas si le module contrib ltree est installé dans une base de données.
pg_upgrade nécessitera une reconstruction de la table si :
une colonne utilisateur est de type tsvector
pg_upgrade nécessitera un réindexage si :
un index est de type hash ou GIN
un index utilise bpchar_pattern_ops
De plus, le format de stockage des dates et heures par défaut a changé vers l'entier après l'arrivée de PostgreSQL™ 8.3. pg_upgrade vérifiera que le format de stockage utilisé sur l'ancienne instance correspond à celui utilisé sur la nouvelle instance. Assurez-vous que votre nouvelle instance est construite avec le drapeau de configuration --disable-integer-datetimes.
Pour les utilisateurs Windows, notez que, dû à une configuration différente sur ce paramètre par l'installeur one-click et l'installeur MSI, il est seulement possible de mettre à jour une version 8.3 provenant de l'installeur one-click vers la version 8.4 ou ultérieure de l'installeur one-click. Il n'est pas possible de mettre à jour un répertoire des données créé par l'installeur MSI à un répertoire de données créé par l'installeur one-click.
pg_upgrade n'offre pas le support de la mise à jour de bases de données contenant ces types de données référençant les OID systèmes : regproc, regprocedure, regoper, regoperator, regconfig et regdictionary. (regtype peut être mis à jour.)
Tout échec, reconstruction, réindexage sera indiqué par pg_upgrade si ils affectent votre installation ; les scripts post-mise à jour pour reconstruire les tables et index seront automatiquement générés.
Pour un test en déploiement, créez une copie du schéma de l'ancienne instance, insérez des données au hasard et faites un test de mise à jour là-dessus.
Si vous voulez utiliser le mode des liens et que vous ne voulez pas que votre ancienne instance soit modifiée quand vous lancez la nouvelle instance, faites une copie de l'ancienne instance et mettez-la à jour avec le mode des liens. Pour obtenir une copie valide de l'ancienne instance, utilisez rsync pour créer une copie sale de l'ancienne instance et exécutez rsync de nouveau après arrêt de l'ancienne instance pour mettre à jour la copie avec toutes les modifications ultérieures.