Skip to content

Latest commit

 

History

History
1244 lines (974 loc) · 48.7 KB

File metadata and controls

1244 lines (974 loc) · 48.7 KB

🔝 Retour au Sommaire

19.3.2. Nouveauté PG 18 : Option --swap pour upgrade rapide

Introduction

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.

Rappel : Comment fonctionne pg_upgrade ?

Avant d'aborder l'option --swap, il est important de comprendre les modes de fonctionnement traditionnels de pg_upgrade.

Les deux modes classiques

1. Mode --copy (copie physique)

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

2. Mode --link (liens physiques)

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

Qu'est-ce qu'un lien physique (hardlink) ?

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.

Analogie simple

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é

Exemple technique

# 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 !

Le problème avec --link

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é

La révolution --swap dans PostgreSQL 18

Concept et motivation

L'option --swap combine le meilleur des deux mondes :

  • ⚡ La rapidité de --link
  • 🔒 La sécurité de --copy

Comment ça fonctionne ?

Le mode --swap utilise une technique ingénieuse appelée échange de répertoires.

Principe de base

┌─────────────────────────────────────────────────────────────┐
│  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          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Les étapes détaillées

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 cluster

Phase 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 !

Pourquoi c'est révolutionnaire ?

1. Rapidité

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 !

2. Sécurité

┌─────────────────────────────────────────────────────────────┐
│  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                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3. Efficacité d'espace

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

Comparaison des trois modes

Tableau récapitulatif

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 ⚠️ Risqué ✅ Excellente
Complexité 🟢 Simple 🟡 Moyenne 🟡 Moyenne
Prérequis filesystem Aucun Même FS Même FS
Recommandé pour prod ✅ Oui ⚠️ Avec précaution ✅✅ Fortement

Comparaison détaillée des temps

Scénario 1 : Base de 100 GB

┌─────────────────────────────────────────────────────────────┐
│  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                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Scénario 2 : Base de 2 TB

┌─────────────────────────────────────────────────────────────┐
│  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                                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Graphique des temps de migration

Temps de migration (échelle logarithmique)

10h  ┤
     │  ████████                           --copy
 5h  ┤  ████████
     │  ████████
 1h  ┤  ████████  ▓▓                       --link / --swap
     │  ████████  ▓▓
30m  ┤  ████████  ▓▓
     │  ████████  ▓▓
10m  ┤  ████████  ▓▓
     └────────────────────────────────
        100GB    2TB    Taille base

Utilisation pratique de --swap

Syntaxe de la commande

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 !

Prérequis et vérifications

1. Vérifier le système de fichiers

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 ✅

2. Vérifier l'espace disque

# 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)

3. Mode vérification d'abord

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*

Procédure complète de migration avec --swap

Étape 1 : Préparation (1 jour avant)

# 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

Étape 2 : Vérification (30 minutes avant)

# 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

Étape 3 : Migration (fenêtre de maintenance)

# 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

Étape 4 : Post-migration

# 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)

Script de rollback (si nécessaire)

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)

Cas d'usage et recommandations

Quand utiliser --swap ?

✅ Cas idéaux pour --swap

  1. Bases de production critiques

    • Besoin d'un rollback rapide possible
    • Contraintes de downtime strictes
    • Taille importante (> 100 GB)
  2. Environnements avec haute disponibilité

    • Réplication en place
    • Besoin de minimiser le risque
  3. 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
  4. Premières migrations PG 18

    • Équipe découvre PG 18
    • Préférence pour la prudence
    • Possibilité de revenir en arrière rassurante

⚠️ Cas où --copy peut être préférable

  1. Différents systèmes de fichiers

    • Ancien cluster sur /mnt/old
    • Nouveau cluster sur /mnt/new (différent FS)
    • --swap n'est pas compatible
  2. Réorganisation des données souhaitée

    • Présence de bloat important
    • Volonté de "nettoyer" la base
    • --copy permet une réorganisation complète
  3. Espace disque abondant

    • Si espace non limité
    • Préférence pour une copie totalement indépendante

Recommandations par taille de base

┌─────────────────────────────────────────────────────────────┐
│  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                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Checklist de migration avec --swap

Avant migration (J-7 à J-1)

  • 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

Avant migration (J-Day, H-1)

  • 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

Pendant migration (Fenêtre de maintenance)

  • 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

Après migration (H+1 à H+4)

  • 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

Après migration (J+1 à J+7)

  • 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

Après migration (J+7 à J+30)

  • 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

Limitations et considérations

Limitations techniques

1. Contrainte du système de fichiers

┌─────────────────────────────────────────────────────────────┐
│  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                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2. Systèmes de fichiers réseau

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

3. Droits et permissions

# 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

Considérations de performance

Impact I/O pendant la migration

┌─────────────────────────────────────────────────────────────┐
│  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          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Utilisation mémoire

# 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émoire

Gestion des erreurs

Erreurs possibles avec --swap

Erreur 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 place

Erreur 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 grand

Erreur 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  

Comparaison avec --link : Quand choisir quoi ?

Arbre de décision

                    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)

Tableau de comparaison --swap vs --link

Aspect --swap --link
Vitesse ⚡⚡ Ultra-rapide ⚡⚡ Ultra-rapide
Rollback ✅ Possible facilement ❌ Impossible
Sécurité 🔒🔒 Très élevée ⚠️ Risqué
Espace disque ~1.1× base ~1× base
Production ✅✅ Recommandé ⚠️ Déconseillé
Complexité 🟡 Moyenne 🟡 Moyenne
Récupération erreur ✅ Excellente ❌ Difficile

Cas pratiques

Cas 1 : Base critique e-commerce (500 GB)

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

Cas 2 : Base analytics (3 TB, lecture seule)

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

Cas 3 : Dev/Test (50 GB)

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

Questions fréquentes (FAQ)

Q1 : --swap est-il plus lent que --link ?

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

Q2 : Puis-je utiliser --swap ET --jobs en même temps ?

Réponse : Oui ! Les deux options sont compatibles :

pg_upgrade \
  --swap \
  --jobs=4 \  # Parallélisation
  [autres options]

Q3 : Que se passe-t-il si la migration échoue avec --swap ?

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

Q4 : Combien de temps puis-je garder le répertoire .old ?

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  

Q5 : --swap fonctionne-t-il avec les tablespaces ?

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 --check avant migration
# Lister les tablespaces
psql -c "\db+"

# Vérifier leur localisation
SELECT spcname, pg_tablespace_location(oid)  
FROM pg_tablespace;  

Q6 : Puis-je utiliser --swap pour migrer de PG 16 vers PG 18 ?

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 ✅  

Q7 : --swap utilise-t-il des hardlinks comme --link ?

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

Q8 : Y a-t-il un risque de corruption avec --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

Bonnes pratiques avancées

1. Automatisation avec scripts

Script de migration complet

#!/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"  

2. Monitoring pendant la migration

# 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'

3. Tests post-migration

-- 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'

Conclusion

L'option --swap de PostgreSQL 18 représente une avancée majeure pour les migrations de bases de données en production.

Récapitulatif des avantages

  • 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

Cas d'usage recommandé

┌─────────────────────────────────────────────────────────────┐
│  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                           │
└─────────────────────────────────────────────────────────────┘

Comparaison finale

--copy --link --swap (PG 18)
Pour DEV
Pour PROD ⚠️ Lent ⚠️ Risqué ✅✅ Recommandé
Bases < 10 GB
Bases > 100 GB ❌ Trop lent ⚠️ Sans filet ✅✅ Idéal
Migration critique ⚠️ Downtime long ❌ Trop risqué ✅✅ Parfait

Points clés à retenir

  1. --swap = --link + sécurité : Vous obtenez la rapidité sans le risque
  2. Rollback simple : En quelques minutes si nécessaire
  3. Production-ready : Conçu pour les environnements critiques
  4. Transparent : Même utilisation que pg_upgrade classique
  5. Nouveauté PG 18 : Profitez-en lors de votre migration

Prochaines sections recommandées

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 !

⏭️ Nouveauté PG 18 : Vérifications parallèles (--jobs)