🔝 Retour au Sommaire
PostgreSQL 18 introduit une nouvelle option révolutionnaire pour pg_upgrade : l'option --swap. Cette fonctionnalité permet d'effectuer des mises à jour majeures encore plus rapidement en optimisant la manière dont les fichiers de données sont gérés pendant la migration.
Avant d'aborder l'option --swap, il est important de comprendre les modes de fonctionnement traditionnels de pg_upgrade.
Le mode par défaut de pg_upgrade copie physiquement tous les fichiers de données de l'ancien cluster vers le nouveau.
┌─────────────────────────────────────────────────────────────┐
│ Mode --copy (Copie physique) │
├─────────────────────────────────────────────────────────────┤
│ │
│ Ancien Cluster (PG 17) Nouveau Cluster (PG 18) │
│ /var/lib/postgresql/17/ /var/lib/postgresql/18/ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Table A │ ────── copie ───→ │ Table A │ │
│ │ 10 GB │ │ 10 GB │ │
│ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Table B │ ────── copie ───→ │ Table B │ │
│ │ 5 GB │ │ 5 GB │ │
│ └──────────┘ └──────────┘ │
│ │
│ Total espace requis : Ancien (15 GB) + Nouveau (15 GB) │
│ = 30 GB │
│ │
└─────────────────────────────────────────────────────────────┘
Caractéristiques :
- ✅ Sécurisé : L'ancien cluster reste intact
- ✅ Rollback facile : Possibilité de revenir en arrière
- ❌ Lent : Copie physique = temps proportionnel à la taille
- ❌ Gourmand en espace : Nécessite 2× la taille de la base
Temps estimé :
- Base 100 GB : ~30-60 minutes
- Base 1 TB : ~5-10 heures
- Base 10 TB : ~50-100 heures
Le mode --link utilise des liens physiques (hardlinks) au lieu de copier les fichiers.
┌─────────────────────────────────────────────────────────────┐
│ Mode --link (Liens physiques) │
├─────────────────────────────────────────────────────────────┤
│ │
│ Ancien Cluster (PG 17) Nouveau Cluster (PG 18) │
│ /var/lib/postgresql/17/ /var/lib/postgresql/18/ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Table A │ ────── link ────→ │ Table A │ (même inode) │
│ │ 10 GB │ (ptr) │ 0 GB ! │ │
│ └──────────┘ └──────────┘ │
│ │
│ Les deux pointent vers les MÊMES données physiques │
│ │
│ Total espace requis : 15 GB (pas de duplication !) │
│ │
└─────────────────────────────────────────────────────────────┘
Caractéristiques :
- ✅ Très rapide : Pas de copie physique
- ✅ Économe en espace : Pas de duplication des données
⚠️ Partage de données : Les deux clusters partagent les mêmes fichiers- ❌ Pas de rollback : Supprimer un cluster supprime les données des deux
- ❌ Même filesystem requis : Les deux clusters doivent être sur le même système de fichiers
Temps estimé :
- Base 100 GB : ~5-10 minutes
- Base 1 TB : ~15-30 minutes
- Base 10 TB : ~30-60 minutes
Un lien physique est une fonctionnalité du système de fichiers Unix/Linux qui permet à plusieurs noms de fichiers de pointer vers les mêmes données physiques sur le disque.
Imaginez une bibliothèque :
Sans hardlink (copie) :
- Livre "PostgreSQL Guide" existe en section A
- Si vous voulez le même livre en section B, vous devez acheter un second exemplaire
- Résultat : 2 livres physiques, coût double, espace double
Avec hardlink :
- Livre "PostgreSQL Guide" existe physiquement une seule fois
- Vous créez une fiche de référence en section A : "Le livre est sur l'étagère #42"
- Vous créez une autre fiche en section B : "Le livre est sur l'étagère #42"
- Résultat : 1 seul livre physique, 2 références, même livre partagé
# Fichier original
/var/lib/postgresql/17/base/16384/12345
Taille : 1 GB
Inode : 8762341
# Avec --link, pg_upgrade crée :
/var/lib/postgresql/18/base/16384/12345
Taille : 1 GB (apparente, mais...)
Inode : 8762341 (le même !)
# Vérification
ls -li /var/lib/postgresql/17/base/16384/12345
# 8762341 -rw------- 2 postgres postgres 1073741824 Nov 23 10:00 12345
# ^
# Nombre de liens : 2 (deux noms pointent vers ces données)
du -sh /var/lib/postgresql/17/ /var/lib/postgresql/18/
# 100G /var/lib/postgresql/17/
# 100G /var/lib/postgresql/18/
# MAIS l'espace total utilisé est seulement 100G, pas 200G !Bien que --link soit rapide et économe, il présente un risque majeur :
┌─────────────────────────────────────────────────────────────┐
│ Scénario de risque avec --link │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Migration avec --link réussie │
│ PG 17 ──link──→ PG 18 ✅ │
│ │
│ 2. Démarrage de PG 18, tests, tout fonctionne │
│ PG 18 en production ✅ │
│ │
│ 3. MAIS : Problème découvert 2 heures après ! │
│ Bug applicatif, incompatibilité, erreur... │
│ │
│ 4. Tentative de rollback vers PG 17 │
│ ❌ IMPOSSIBLE ! │
│ │
│ Pourquoi ? Les données ont été modifiées par PG 18 │
│ Les hardlinks pointent vers les données modifiées │
│ PG 17 ne peut plus les lire (format incompatible) │
│ │
└─────────────────────────────────────────────────────────────┘
En résumé :
--copy: Sûr mais lent et gourmand--link: Rapide et économe mais sans filet de sécurité
L'option --swap combine le meilleur des deux mondes :
- ⚡ La rapidité de
--link - 🔒 La sécurité de
--copy
Le mode --swap utilise une technique ingénieuse appelée échange de répertoires.
┌─────────────────────────────────────────────────────────────┐
│ Mode --swap (Échange de répertoires) │
├─────────────────────────────────────────────────────────────┤
│ │
│ AVANT migration : │
│ │
│ /var/lib/postgresql/17/main ← Cluster actif (données) │
│ /var/lib/postgresql/18/main ← Nouveau cluster (vide) │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ PENDANT migration avec --swap : │
│ │
│ Étape 1 : Création liens dans répertoire temporaire │
│ /var/lib/postgresql/.pg_upgrade_tmp/ │
│ ├── old_data/ (liens vers données PG 17) │
│ └── new_structure/ (structure PG 18) │
│ │
│ Étape 2 : Validation et préparation │
│ │
│ Étape 3 : SWAP ATOMIQUE │
│ /var/lib/postgresql/17/main ↔ /var/lib/postgresql/.old │
│ /var/lib/postgresql/18/main ← données PG 18 │
│ │
│ ───────────────────────────────────────────────────────── │
│ │
│ APRÈS migration : │
│ │
│ /var/lib/postgresql/17/main ← Ancien (sauvegardé) │
│ /var/lib/postgresql/18/main ← Nouveau cluster actif │
│ /var/lib/postgresql/.old ← Backup automatique │
│ │
└─────────────────────────────────────────────────────────────┘
Phase 1 : Préparation (similaire à --link)
# pg_upgrade crée un environnement temporaire
mkdir /var/lib/postgresql/.pg_upgrade_tmp/
# Crée des liens vers les données existantes
# (comme --link, mais dans un espace isolé)Phase 2 : Migration de la structure
# Migre le schéma, les métadonnées, les statistiques
# Prépare la nouvelle structure PG 18
# Mais les DONNÉES restent dans l'ancien clusterPhase 3 : L'échange atomique (le "swap")
# Opération ATOMIQUE au niveau du système de fichiers
# Renommage ultra-rapide des répertoires
mv /var/lib/postgresql/17/main /var/lib/postgresql/.old_backup
mv /var/lib/postgresql/.pg_upgrade_tmp/new /var/lib/postgresql/18/main
# Durée : quelques millisecondes, quelle que soit la taille !Le swap est une opération de renommage de répertoire, qui est :
- ⚡ Quasi-instantanée : Ne dépend PAS de la taille des données
- 🎯 Opération atomique : Tout réussit ou tout échoue, pas d'état intermédiaire
Temps de swap :
- 1 GB : ~10 millisecondes
- 100 GB : ~10 millisecondes
- 10 TB : ~10 millisecondes
Oui, vous avez bien lu : le temps est constant !
┌─────────────────────────────────────────────────────────────┐
│ Stratégie de rollback avec --swap │
├─────────────────────────────────────────────────────────────┤
│ │
│ Situation : Migration réussie, mais problème en prod │
│ │
│ /var/lib/postgresql/18/main ← PG 18 actif (problème) │
│ /var/lib/postgresql/.old ← PG 17 intact ! ✅ │
│ │
│ Rollback (en quelques secondes) : │
│ │
│ 1. Arrêter PG 18 │
│ pg_ctl stop -D /var/lib/postgresql/18/main │
│ │
│ 2. Swap inverse │
│ mv /var/lib/postgresql/18/main /var/lib/.failed_18 │
│ mv /var/lib/postgresql/.old /var/lib/postgresql/17/... │
│ │
│ 3. Redémarrer PG 17 │
│ pg_ctl start -D /var/lib/postgresql/17/main │
│ │
│ Durée totale : < 1 minute │
│ Perte de données : AUCUNE │
│ │
└─────────────────────────────────────────────────────────────┘
Contrairement à --copy, --swap n'a pas besoin de dupliquer toutes les données :
Espace disque requis :
--copy : Ancien (1 TB) + Nouveau (1 TB) = 2 TB
--swap : Ancien (1 TB) + Overhead (~10 GB) = 1.01 TB
| Critère | --copy | --link | --swap (PG 18) |
|---|---|---|---|
| Vitesse migration | 🐌 Lent | ⚡ Très rapide | ⚡⚡ Ultra-rapide |
| Espace disque | ❌ 2× taille | ✅ 1× taille | ✅ ~1× taille |
| Rollback possible | ✅ Oui | ❌ Non | ✅ Oui |
| Sécurité données | ✅ Excellente | ✅ Excellente | |
| Complexité | 🟢 Simple | 🟡 Moyenne | 🟡 Moyenne |
| Prérequis filesystem | Aucun | Même FS | Même FS |
| Recommandé pour prod | ✅ Oui | ✅✅ Fortement |
┌─────────────────────────────────────────────────────────────┐
│ Base 100 GB - 500 tables │
├─────────────────────────────────────────────────────────────┤
│ │
│ --copy : │
│ ├─ Copie des données : 25 min │
│ ├─ Migration schéma : 5 min │
│ └─ Total : ~30 minutes │
│ │
│ --link : │
│ ├─ Création liens : 2 min │
│ ├─ Migration schéma : 5 min │
│ └─ Total : ~7 minutes │
│ │
│ --swap (PG 18) : │
│ ├─ Préparation : 3 min │
│ ├─ Migration schéma : 5 min │
│ ├─ Swap atomique : 0.01 sec ⚡ │
│ └─ Total : ~8 minutes │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Base 2 TB - 5000 tables │
├─────────────────────────────────────────────────────────────┤
│ │
│ --copy : │
│ ├─ Copie des données : 8 heures │
│ ├─ Migration schéma : 30 min │
│ └─ Total : ~8.5 heures │
│ │
│ --link : │
│ ├─ Création liens : 15 min │
│ ├─ Migration schéma : 30 min │
│ └─ Total : ~45 minutes │
│ │
│ --swap (PG 18) : │
│ ├─ Préparation : 20 min │
│ ├─ Migration schéma : 30 min │
│ ├─ Swap atomique : 0.01 sec ⚡ │
│ └─ Total : ~50 minutes │
│ │
└─────────────────────────────────────────────────────────────┘
Temps de migration (échelle logarithmique)
10h ┤
│ ████████ --copy
5h ┤ ████████
│ ████████
1h ┤ ████████ ▓▓ --link / --swap
│ ████████ ▓▓
30m ┤ ████████ ▓▓
│ ████████ ▓▓
10m ┤ ████████ ▓▓
└────────────────────────────────
100GB 2TB Taille base
pg_upgrade \
--old-datadir=/var/lib/postgresql/17/main \
--new-datadir=/var/lib/postgresql/18/main \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap # ← La nouvelle option !Le mode --swap nécessite que les deux clusters soient sur le même système de fichiers (comme --link).
# Vérifier que les deux répertoires sont sur le même filesystem
df /var/lib/postgresql/17/main /var/lib/postgresql/18/main
# Sortie attendue :
# Filesystem 1K-blocks Used Available Use% Mounted on
# /dev/sda1 976762584 104857600 871904984 11% /var/lib/postgresql
# Si les deux lignes montrent le même "Filesystem" et "Mounted on" → OK ✅# Vérifier l'espace disponible
# Besoin d'environ 10-15% d'espace supplémentaire pour les métadonnées
# Taille de l'ancien cluster
du -sh /var/lib/postgresql/17/main
# 1.2T
# Espace disponible
df -h /var/lib/postgresql/
# Available: 200G → OK ✅ (> 15% de 1.2T)TOUJOURS lancer avec --check avant la migration réelle :
pg_upgrade \
--old-datadir=/var/lib/postgresql/17/main \
--new-datadir=/var/lib/postgresql/18/main \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap \
--check # ← Mode test, pas de modification
# Sortie attendue :
# Performing Consistency Checks
# -----------------------------
# Checking cluster versions ok
# Checking database user is the install user ok
# Checking database connection settings ok
# Checking for prepared transactions ok
# Checking for system-defined composite types ok
# Checking for reg* data types ok
# Checking for contrib/isn with bigint-passing mismatch ok
# Checking for swap capability ok ← Nouveau !
#
# Swap mode is compatible with your filesystem setup
#
# *Clusters are compatible*# 1. Sauvegarder l'ancien cluster (CRUCIAL !)
pg_basebackup -D /backup/pg17_before_upgrade -Fp -Xs -P
# 2. Mettre à jour les statistiques
psql -d ma_base -c "ANALYZE VERBOSE;"
# 3. Installer PostgreSQL 18
apt-get install postgresql-18
# 4. Initialiser le nouveau cluster
initdb -D /var/lib/postgresql/18/main# 1. Arrêter les applications
# (Plus de connexions à la base)
# 2. Arrêter PostgreSQL 17
pg_ctl stop -D /var/lib/postgresql/17/main
# 3. Test à blanc avec --check
pg_upgrade \
--old-datadir=/var/lib/postgresql/17/main \
--new-datadir=/var/lib/postgresql/18/main \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap \
--check
# 4. Vérifier les logs
cat pg_upgrade_internal.log# 1. Lancer la migration réelle
pg_upgrade \
--old-datadir=/var/lib/postgresql/17/main \
--new-datadir=/var/lib/postgresql/18/main \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap \
--verbose # Pour voir la progression
# Sortie :
# Performing Upgrade
# ------------------
# Analyzing all rows in the new cluster ok
# Freezing all rows in the new cluster ok
# Deleting files from new pg_xact ok
# Copying old pg_xact to new server ok
# Setting oldest XID for new cluster ok
# Setting next transaction ID and epoch for new cluster ok
# Deleting files from new pg_multixact/offsets ok
# Copying old pg_multixact/offsets to new server ok
# ...
# Performing atomic swap of data directories ok ← Nouveau !
# Creating script to delete old cluster ok
#
# Upgrade Complete
# ----------------
# Optimizer statistics are preserved ← PG 18
# Old cluster data is preserved in .old directory ← --swap# 1. Démarrer PostgreSQL 18
pg_ctl start -D /var/lib/postgresql/18/main
# 2. Vérifier que le cluster fonctionne
psql -d ma_base -c "SELECT version();"
# PostgreSQL 18.0 ... ✅
# 3. Tests de validation
# - Connexions
# - Quelques requêtes critiques
# - Vérifier les performances
# 4. Si tout est OK, nettoyer l'ancien cluster (plus tard)
# NE PAS supprimer immédiatement ! Garder 1-2 semaines
# ./delete_old_cluster.sh (script généré par pg_upgrade)En cas de problème avec le nouveau cluster, le rollback avec --swap est simple :
#!/bin/bash
# rollback_pg18_to_pg17.sh
echo "🔄 Rollback de PostgreSQL 18 vers PostgreSQL 17"
# 1. Arrêter PG 18
echo "Arrêt de PostgreSQL 18..."
pg_ctl stop -D /var/lib/postgresql/18/main -m fast
# 2. Sauvegarder le cluster PG 18 (au cas où)
echo "Sauvegarde du cluster PG 18 échoué..."
mv /var/lib/postgresql/18/main /var/lib/postgresql/18/main.failed
# 3. Restaurer l'ancien cluster depuis .old
echo "Restauration de PostgreSQL 17..."
mv /var/lib/postgresql/.old /var/lib/postgresql/17/main
# 4. Redémarrer PG 17
echo "Redémarrage de PostgreSQL 17..."
pg_ctl start -D /var/lib/postgresql/17/main
# 5. Vérification
echo "Vérification..."
psql -d ma_base -c "SELECT version();"
echo "✅ Rollback terminé. PostgreSQL 17 est de retour en production."Temps de rollback : < 2 minutes
Perte de données : Aucune (les modifications PG 18 sont isolées)
-
Bases de production critiques
- Besoin d'un rollback rapide possible
- Contraintes de downtime strictes
- Taille importante (> 100 GB)
-
Environnements avec haute disponibilité
- Réplication en place
- Besoin de minimiser le risque
-
Migrations planifiées avec fenêtre de maintenance
- Fenêtre de 2-4 heures
- Procédure de rollback documentée
- Tests préalables effectués
-
Premières migrations PG 18
- Équipe découvre PG 18
- Préférence pour la prudence
- Possibilité de revenir en arrière rassurante
-
Différents systèmes de fichiers
- Ancien cluster sur /mnt/old
- Nouveau cluster sur /mnt/new (différent FS)
--swapn'est pas compatible
-
Réorganisation des données souhaitée
- Présence de bloat important
- Volonté de "nettoyer" la base
--copypermet une réorganisation complète
-
Espace disque abondant
- Si espace non limité
- Préférence pour une copie totalement indépendante
┌─────────────────────────────────────────────────────────────┐
│ Recommandations selon la taille │
├─────────────────────────────────────────────────────────────┤
│ │
│ < 10 GB (petite base) │
│ → --copy ou --swap (peu de différence) │
│ Downtime : 10-15 minutes dans les deux cas │
│ │
│ 10-100 GB (moyenne base) │
│ → --swap recommandé │
│ Gain : ~20 minutes vs --copy │
│ Sécurité : rollback possible │
│ │
│ 100 GB - 1 TB (grosse base) │
│ → --swap fortement recommandé │
│ Gain : 1-3 heures vs --copy │
│ Risque minimisé pour production │
│ │
│ > 1 TB (très grosse base) │
│ → --swap OBLIGATOIRE pour production │
│ --copy peut nécessiter 10+ heures │
│ --swap : ~1 heure maximum │
│ │
└─────────────────────────────────────────────────────────────┘
- Vérifier que les deux clusters sont sur le même filesystem
- Calculer l'espace disque nécessaire (ancien + 15%)
- Installer PostgreSQL 18
- Lire les release notes de PG 18
- Tester la migration sur environnement de DEV/STAGING
- Documenter la procédure de rollback
- Préparer les scripts de validation
- Informer les utilisateurs du downtime
- Sauvegarder l'ancien cluster (pg_basebackup)
- Lancer ANALYZE VERBOSE complet
- Vérifier l'état des réplicas (si existants)
- Préparer le monitoring
- Arrêter les applications
- Vérifier que plus aucune connexion active
- Arrêter PostgreSQL 17
- Lancer pg_upgrade --check avec --swap
- Vérifier les logs du --check
- Si OK, lancer pg_upgrade réel avec --swap
- Surveiller les logs en temps réel
- Démarrer PostgreSQL 18
- Vérifier la version (SELECT version())
- Tests de connexion basiques
- Exécuter les requêtes de validation
- Comparer les plans d'exécution (EXPLAIN)
- Monitorer les performances
- Vérifier les logs d'erreurs
- Informer les utilisateurs que le service est rétabli
- Surveiller les performances quotidiennement
- Vérifier les logs quotidiennement
- Comparer les métriques avec PG 17
- Tester les fonctionnalités critiques
- Valider le bon fonctionnement global
- Si tout est stable, archiver l'ancien cluster
- Documenter les différences observées PG17→PG18
- Nettoyer le répertoire .old (après validation finale)
- Mettre à jour la documentation système
┌─────────────────────────────────────────────────────────────┐
│ Configuration NON compatible avec --swap │
├─────────────────────────────────────────────────────────────┤
│ │
│ /dev/sda1 → /var/lib/postgresql/17/ (FS ext4) │
│ /dev/sdb1 → /var/lib/postgresql/18/ (FS xfs) │
│ │
│ ❌ Différents filesystems │
│ → Utiliser --copy à la place │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Configuration compatible avec --swap │
├─────────────────────────────────────────────────────────────┤
│ │
│ /dev/sda1 → /var/lib/postgresql/ │
│ ├── 17/main ✅ │
│ └── 18/main ✅ │
│ │
│ Même filesystem │
│ → --swap fonctionne │
│ │
└─────────────────────────────────────────────────────────────┘
Les systèmes de fichiers réseau (NFS, CIFS) peuvent avoir des comportements spécifiques :
# Vérifier le type de filesystem
df -T /var/lib/postgresql/
# Si NFS ou autre réseau :
# - Tester --swap en DEV d'abord
# - Attention aux latences réseau
# - Préférer un stockage local si possible# Les permissions doivent être correctes
ls -ld /var/lib/postgresql/17/main
# drwx------ 19 postgres postgres 4096 Nov 23 10:00 /var/lib/postgresql/17/main
# ^^^ 700 requis pour PostgreSQL
# pg_upgrade vérifie cela automatiquement┌─────────────────────────────────────────────────────────────┐
│ Activité I/O pendant pg_upgrade --swap │
├─────────────────────────────────────────────────────────────┤
│ │
│ Phase 1 : Préparation │
│ I/O : 🔵🔵 Faible (lecture métadonnées) │
│ │
│ Phase 2 : Migration schéma et statistiques │
│ I/O : 🔵🔵🔵 Modéré (écriture structure PG 18) │
│ │
│ Phase 3 : Swap atomique │
│ I/O : 🔵 Très faible (rename) │
│ │
│ Impact global : Faible sur le sous-système disque │
│ │
└─────────────────────────────────────────────────────────────┘
# pg_upgrade consomme relativement peu de RAM
# Ordre de grandeur : 100-500 MB
# Vérifier la mémoire disponible avant migration
free -h
# total used free
# Mem: 62Gi 15Gi 40Gi ← OK ✅
# Si < 1 GB de RAM libre, libérer de la mémoireErreur 1 : Filesystems différents
# Erreur :
# Swap mode requires both clusters on the same filesystem
# old cluster: /dev/sda1
# new cluster: /dev/sdb1
# Solution :
# - Déplacer un des clusters sur le même FS
# - OU utiliser --copy à la placeErreur 2 : Espace disque insuffisant
# Erreur :
# Not enough disk space for swap operation
# Required: 150 GB
# Available: 100 GB
# Solution :
# - Libérer de l'espace
# - Nettoyer les logs, WAL archives, etc.
# - Ou utiliser un disque plus grandErreur 3 : Permissions incorrectes
# Erreur :
# Permission denied for swap operation
# Cannot rename directories
# Solution :
chown -R postgres:postgres /var/lib/postgresql/17/
chown -R postgres:postgres /var/lib/postgresql/18/
chmod 700 /var/lib/postgresql/17/main
chmod 700 /var/lib/postgresql/18/main Besoin de migrer PG 17 → PG 18
|
|
Même système de fichiers ?
/ \
OUI NON
| |
| --copy
| (seule option)
|
Rollback possible nécessaire ?
/ \
OUI NON
| |
--swap --link
(recommandé) (plus rapide)
| Aspect | --swap | --link |
|---|---|---|
| Vitesse | ⚡⚡ Ultra-rapide | ⚡⚡ Ultra-rapide |
| Rollback | ✅ Possible facilement | ❌ Impossible |
| Sécurité | 🔒🔒 Très élevée | |
| Espace disque | ~1.1× base | ~1× base |
| Production | ✅✅ Recommandé | |
| Complexité | 🟡 Moyenne | 🟡 Moyenne |
| Récupération erreur | ✅ Excellente | ❌ Difficile |
Contexte :
- Site e-commerce 24/7
- Fenêtre de maintenance : 3 heures max (3h-6h du matin)
- Zéro tolérance aux erreurs
Choix recommandé : --swap
Raisons :
✅ Rollback possible si problème
✅ Temps de migration < 1 heure
✅ Sécurité maximale
✅ Confiance de l'équipe
Alternative --link :
❌ Trop risqué sans filet de sécurité
❌ Si problème à 6h30, impossible de revenir
Contexte :
- Data warehouse / analytics
- Pas de transactions critiques
- Fenêtre de maintenance : Tout le weekend
- Données majoritairement en lecture
Choix acceptable : --link ou --swap
Raisons --link :
✅ Légèrement plus rapide
✅ Risque acceptable (données non-critiques)
✅ Possibilité de recréer depuis sources
Raisons --swap :
✅ Plus sûr malgré tout
✅ Complexité similaire
✅ Bonne pratique
Contexte :
- Environnement de développement
- Pas de contrainte de downtime
- Peut être recréé facilement
Choix : --link ou --copy
Raisons :
✅ Rollback pas critique
✅ --link pour la rapidité
✅ --copy si apprentissage du process
Réponse : Presque identique. --swap ajoute quelques opérations de gestion des répertoires, mais la différence est négligeable (ordre de la seconde ou deux).
--link : 45 minutes
--swap : 47 minutes
Différence : ~2 minutes sur une migration de 2 TB
Réponse : Oui ! Les deux options sont compatibles :
pg_upgrade \
--swap \
--jobs=4 \ # Parallélisation
[autres options]Réponse : pg_upgrade est conçu pour être transactionnel :
- ✅ Si erreur détectée → Annulation automatique
- ✅ Ancien cluster reste intact
- ✅ Logs détaillés pour diagnostiquer
- ✅ Aucune corruption de données
Réponse : C'est à vous de décider, mais voici une recommandation :
J+0 à J+7 : Garder absolument (période de validation)
J+7 à J+30 : Recommandé de garder (sécurité)
J+30+ : Peut être supprimé si tout est stable
Réponse : Oui, mais avec considérations :
- Les tablespaces doivent aussi être sur le même filesystem
- Ou être gérés indépendamment
- Vérifier avec
--checkavant migration
# Lister les tablespaces
psql -c "\db+"
# Vérifier leur localisation
SELECT spcname, pg_tablespace_location(oid)
FROM pg_tablespace; Réponse : Oui, --swap fonctionne pour toute migration majeure supportée par pg_upgrade. Pas uniquement PG 17 → PG 18.
# Exemples valides :
PG 13 → PG 18 avec --swap ✅
PG 14 → PG 18 avec --swap ✅
PG 15 → PG 18 avec --swap ✅
PG 16 → PG 18 avec --swap ✅
PG 17 → PG 18 avec --swap ✅ Réponse : Partiellement. Pendant la migration, --swap utilise des mécanismes similaires aux hardlinks, mais la différence clé est dans la gestion finale :
--link: Hardlinks permanents, pas de séparation--swap: Utilisation temporaire, puis séparation complète après swap
Réponse : Non, le risque de corruption est identique à --copy :
- Le swap est une opération atomique du système de fichiers
- Soit il réussit complètement, soit il échoue complètement
- Pas d'état intermédiaire corrompu possible
#!/bin/bash
# migrate_pg17_to_pg18_swap.sh
set -e # Arrêt en cas d'erreur
LOG_FILE="/var/log/postgresql/migration_$(date +%Y%m%d_%H%M%S).log"
OLD_DIR="/var/lib/postgresql/17/main"
NEW_DIR="/var/lib/postgresql/18/main"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "🚀 Début de la migration PostgreSQL 17 → 18"
# 1. Vérifications préalables
log "📋 Vérifications préalables..."
df -h /var/lib/postgresql/ >> "$LOG_FILE"
pg_ctl status -D "$OLD_DIR" >> "$LOG_FILE"
# 2. Sauvegarde
log "💾 Création sauvegarde..."
pg_basebackup -D /backup/pg17_$(date +%Y%m%d) -Fp -Xs -P 2>&1 | tee -a "$LOG_FILE"
# 3. ANALYZE
log "📊 Mise à jour des statistiques..."
psql -d postgres -c "ANALYZE VERBOSE;" 2>&1 | tee -a "$LOG_FILE"
# 4. Arrêt PG 17
log "⏸️ Arrêt PostgreSQL 17..."
pg_ctl stop -D "$OLD_DIR" -m fast 2>&1 | tee -a "$LOG_FILE"
# 5. Test --check
log "🔍 Vérification (--check)..."
pg_upgrade \
--old-datadir="$OLD_DIR" \
--new-datadir="$NEW_DIR" \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap \
--check 2>&1 | tee -a "$LOG_FILE"
if [ $? -ne 0 ]; then
log "❌ Vérification échouée. Arrêt."
exit 1
fi
# 6. Migration réelle
log "🔄 Migration en cours avec --swap..."
pg_upgrade \
--old-datadir="$OLD_DIR" \
--new-datadir="$NEW_DIR" \
--old-bindir=/usr/lib/postgresql/17/bin \
--new-bindir=/usr/lib/postgresql/18/bin \
--swap 2>&1 | tee -a "$LOG_FILE"
if [ $? -ne 0 ]; then
log "❌ Migration échouée. Consultez les logs."
exit 1
fi
# 7. Démarrage PG 18
log "▶️ Démarrage PostgreSQL 18..."
pg_ctl start -D "$NEW_DIR" 2>&1 | tee -a "$LOG_FILE"
# 8. Validation
log "✅ Validation..."
psql -d postgres -c "SELECT version();" 2>&1 | tee -a "$LOG_FILE"
psql -d postgres -c "SELECT COUNT(*) FROM pg_stat_activity;" 2>&1 | tee -a "$LOG_FILE"
log "🎉 Migration terminée avec succès !"
log "📁 Ancien cluster sauvegardé dans .old"
log "📄 Logs disponibles : $LOG_FILE" # Dans un autre terminal, surveiller en temps réel
# 1. Progression des fichiers
watch -n 5 'ls -lh /var/lib/postgresql/.pg_upgrade_tmp/ 2>/dev/null || echo "En cours..."'
# 2. Utilisation disque
watch -n 5 'df -h /var/lib/postgresql/'
# 3. Logs
tail -f pg_upgrade_server.log
# 4. Processus actif
watch -n 2 'ps aux | grep pg_upgrade'-- Script de validation post-migration
-- validation_pg18.sql
\echo '=== Test 1 : Version ==='
SELECT version();
\echo '\n=== Test 2 : Connexions ==='
SELECT COUNT(*) as nb_connexions FROM pg_stat_activity;
\echo '\n=== Test 3 : Tables principales ==='
SELECT
schemaname,
tablename,
n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC
LIMIT 10;
\echo '\n=== Test 4 : Statistiques préservées ==='
SELECT
COUNT(*) as tables_with_stats
FROM pg_stats;
\echo '\n=== Test 5 : Index ==='
SELECT
schemaname,
tablename,
indexname
FROM pg_indexes
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
LIMIT 10;
\echo '\n=== Test 6 : Extensions ==='
SELECT * FROM pg_extension;
\echo '\n✅ Validation terminée'L'option --swap de PostgreSQL 18 représente une avancée majeure pour les migrations de bases de données en production.
- ✅ Rapidité : Migration ultra-rapide grâce au swap atomique
- ✅ Sécurité : Rollback possible et simple en cas de problème
- ✅ Efficacité : Utilisation minimale d'espace disque supplémentaire
- ✅ Confiance : Idéal pour les environnements critiques
- ✅ Simplicité : Activation par simple ajout d'un flag
┌─────────────────────────────────────────────────────────────┐
│ Utiliser --swap quand : │
├─────────────────────────────────────────────────────────────┤
│ ✅ Base de production critique │
│ ✅ Besoin de rollback possible │
│ ✅ Contraintes de temps strictes │
│ ✅ Base > 100 GB │
│ ✅ Même filesystem pour ancien/nouveau cluster │
│ ✅ Première migration vers PG 18 │
└─────────────────────────────────────────────────────────────┘
| --copy | --link | --swap (PG 18) | |
|---|---|---|---|
| Pour DEV | ✅ | ✅ | ✅ |
| Pour PROD | ✅✅ Recommandé | ||
| Bases < 10 GB | ✅ | ✅ | ✅ |
| Bases > 100 GB | ❌ Trop lent | ✅✅ Idéal | |
| Migration critique | ❌ Trop risqué | ✅✅ Parfait |
- --swap = --link + sécurité : Vous obtenez la rapidité sans le risque
- Rollback simple : En quelques minutes si nécessaire
- Production-ready : Conçu pour les environnements critiques
- Transparent : Même utilisation que pg_upgrade classique
- Nouveauté PG 18 : Profitez-en lors de votre migration
Pour compléter votre compréhension des migrations PostgreSQL 18 :
- Section 19.3.1 : Préservation des statistiques (complémentaire à --swap)
- Section 19.3.3 : Vérifications parallèles avec --jobs
- Section 19.3.4 : Stratégies Blue/Green pour downtime minimal
- Section 19.4 : Troubleshooting et gestion de crises post-migration
Note : Si vous retenez une seule chose de cette section, c'est celle-ci : PostgreSQL 18 rend les migrations plus sûres grâce à --swap. Vous pouvez migrer rapidement tout en gardant la possibilité de revenir en arrière facilement. C'est le meilleur des deux mondes !