🔝 Retour au Sommaire
L'une des améliorations les plus appréciées de PostgreSQL 18 dans pg_upgrade concerne l'option --jobs qui permet désormais d'effectuer les vérifications en parallèle. Cette fonctionnalité réduit considérablement le temps nécessaire pour valider qu'une migration est possible, particulièrement sur les bases de données volumineuses avec de nombreux objets.
La parallélisation consiste à exécuter plusieurs tâches simultanément au lieu de les traiter une par une (séquentiellement).
Mode séquentiel (sans parallélisation) :
Un seul ouvrier assemble toute une voiture, puis passe à la suivante :
Ouvrier 1: [Voiture A] → [Voiture B] → [Voiture C]
(2 heures) (2 heures) (2 heures)
Temps total : 6 heures pour 3 voitures
Mode parallèle (avec parallélisation) :
Trois ouvriers travaillent en même temps sur différentes voitures :
Ouvrier 1: [Voiture A]
Ouvrier 2: [Voiture B] ← En même temps !
Ouvrier 3: [Voiture C]
(2 heures chacun)
Temps total : 2 heures pour 3 voitures
Dans le contexte de pg_upgrade, au lieu de vérifier les tables une par une, on peut en vérifier plusieurs simultanément.
┌─────────────────────────────────────────────────────────────┐
│ Mode séquentiel (1 job) │
├─────────────────────────────────────────────────────────────┤
│ │
│ Worker 1: [Table A] → [Table B] → [Table C] → [Table D] │
│ (10 min) (10 min) (10 min) (10 min) │
│ │
│ Temps total : 40 minutes │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Mode parallèle (4 jobs) │
├─────────────────────────────────────────────────────────────┤
│ │
│ Worker 1: [Table A] │
│ Worker 2: [Table B] ← Tous en même temps ! │
│ Worker 3: [Table C] │
│ Worker 4: [Table D] │
│ (10 min chacun) │
│ │
│ Temps total : 10 minutes (4× plus rapide !) │
│ │
└─────────────────────────────────────────────────────────────┘
Votre serveur possède plusieurs cœurs de processeur (CPU cores) qui peuvent travailler indépendamment :
# Voir le nombre de CPU cores disponibles
lscpu | grep "^CPU(s):"
# CPU(s): 16
# Ou plus simplement
nproc
# 16Un serveur avec 16 cores peut théoriquement exécuter 16 tâches en même temps.
Un worker est un processus qui effectue une partie du travail. Avec --jobs=4, pg_upgrade lance 4 workers qui travaillent en parallèle.
La parallélisation n'est pas gratuite :
- Chaque worker consomme de la mémoire
- Chaque worker peut générer des I/O disque concurrentes
- Il y a un coût de coordination entre les workers
Donc, plus de jobs n'est pas toujours mieux !
L'option --jobs existait déjà dans les versions précédentes de PostgreSQL, mais son utilisation était limitée :
PostgreSQL ≤ 17 :
- --jobs fonctionnait pour la MIGRATION des données
- Mais PAS pour les VÉRIFICATIONS (--check)
- La phase --check restait séquentielle, donc lente
Problème : Sur une base avec 10,000 tables, la phase --check pouvait prendre plusieurs heures, même sur un serveur puissant avec 32 cores.
PostgreSQL 18 :
✅ --jobs fonctionne pour la MIGRATION (comme avant)
✅ --jobs fonctionne aussi pour les VÉRIFICATIONS (--check) ← NOUVEAU !
✅ Accélération drastique de la phase de validation
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 \
--jobs=4 # ← 4 workers en parallèle# Vérification avec 4 workers parallèles
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 \
--jobs=4 \
--check # ← Nouveau dans PG 18 : parallélisé !# Migration complète avec parallélisation et swap
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 \
--jobs=8 \
--swapNombre de jobs optimal ≈ 50-75% du nombre de CPU cores
Exemples :
- Serveur 4 cores → --jobs=2 ou 3
- Serveur 8 cores → --jobs=4 à 6
- Serveur 16 cores → --jobs=8 à 12
- Serveur 32 cores → --jobs=16 à 24
Pourquoi pas 100% ? :
- Laisser des ressources pour le système d'exploitation
- Laisser des ressources pour les opérations I/O
- Éviter la contention (compétition) entre workers
1. CPU disponibles
# Vérifier les CPU disponibles
nproc
# 16
# Recommandation : --jobs=8 ou --jobs=122. Mémoire disponible
Chaque worker consomme de la mémoire. Formule approximative :
Mémoire par worker ≈ 100-500 MB
(selon la complexité de la base)
Exemple :
- 8 workers × 200 MB = 1.6 GB de RAM nécessaire
- Vérifier la RAM disponible avant de définir --jobs
# Vérifier la RAM disponible
free -h
# total used free
# Mem: 62Gi 15Gi 45Gi ← Largement suffisant
# Si free < 4 GB, limiter le nombre de jobs3. Type de stockage
┌─────────────────────────────────────────────────────────────┐
│ Impact du stockage sur --jobs │
├─────────────────────────────────────────────────────────────┤
│ │
│ HDD (disque mécanique) : │
│ → --jobs=2 à 4 maximum │
│ → Trop de parallélisme = contention I/O │
│ → Les têtes de lecture se déplacent beaucoup │
│ │
│ SSD SATA : │
│ → --jobs=4 à 8 │
│ → Bon compromis pour la plupart des cas │
│ │
│ NVMe SSD : │
│ → --jobs=8 à 16+ │
│ → Peut gérer beaucoup de parallélisme │
│ → Latence ultra-faible │
│ │
│ Stockage réseau (NFS, SAN) : │
│ → Dépend de la configuration réseau │
│ → Tester avec --check d'abord │
│ → Généralement --jobs=4 à 8 │
│ │
└─────────────────────────────────────────────────────────────┘
4. Nombre de tables et index
Base avec beaucoup d'objets :
- 10,000+ tables → --jobs élevé bénéfique (--jobs=8 à 16)
- 100 tables grosses → --jobs modéré suffisant (--jobs=4)
Raison : Plus il y a d'objets indépendants, plus on peut paralléliser
| Serveur | CPU | RAM | Stockage | --jobs recommandé |
|---|---|---|---|---|
| Petit VPS | 2-4 cores | 4-8 GB | SSD | 2 |
| Serveur moyen | 8 cores | 16-32 GB | SSD | 4-6 |
| Serveur standard | 16 cores | 64 GB | NVMe | 8-12 |
| Serveur puissant | 32+ cores | 128+ GB | NVMe RAID | 16-24 |
| Cloud (AWS/Azure) | Variables | Variables | EBS/Premium | 4-8 |
┌─────────────────────────────────────────────────────────────┐
│ Phase --check (vérification avant migration) │
├─────────────────────────────────────────────────────────────┤
│ │
│ PostgreSQL 17 (--jobs=1 forcé pour --check) : │
│ Durée : 45 minutes │
│ │
│ PostgreSQL 18 avec --jobs=1 : │
│ Durée : 45 minutes (identique) │
│ │
│ PostgreSQL 18 avec --jobs=4 : │
│ Durée : 12 minutes (3.75× plus rapide) │
│ │
│ PostgreSQL 18 avec --jobs=8 : │
│ Durée : 7 minutes (6.4× plus rapide) │
│ │
│ PostgreSQL 18 avec --jobs=16 : │
│ Durée : 5 minutes (9× plus rapide) │
│ │
└─────────────────────────────────────────────────────────────┘
Gain : 40 minutes économisées sur la vérification !
┌─────────────────────────────────────────────────────────────┐
│ Phase --check (vérification avant migration) │
├─────────────────────────────────────────────────────────────┤
│ │
│ PostgreSQL 17 (--jobs=1 forcé) : │
│ Durée : 4 heures 30 minutes │
│ │
│ PostgreSQL 18 avec --jobs=4 : │
│ Durée : 1 heure 15 minutes (3.6× plus rapide) │
│ │
│ PostgreSQL 18 avec --jobs=8 : │
│ Durée : 40 minutes (6.75× plus rapide) │
│ │
│ PostgreSQL 18 avec --jobs=16 : │
│ Durée : 25 minutes (10.8× plus rapide) │
│ │
└─────────────────────────────────────────────────────────────┘
Gain : Plus de 4 heures économisées !
┌─────────────────────────────────────────────────────────────┐
│ Phase --check (vérification avant migration) │
├─────────────────────────────────────────────────────────────┤
│ │
│ PostgreSQL 17 (--jobs=1) : │
│ Durée : 18 heures │
│ Commentaire : Inacceptable en production ! │
│ │
│ PostgreSQL 18 avec --jobs=8 : │
│ Durée : 2 heures 30 minutes │
│ │
│ PostgreSQL 18 avec --jobs=16 : │
│ Durée : 1 heure 20 minutes │
│ │
│ PostgreSQL 18 avec --jobs=24 : │
│ Durée : 55 minutes │
│ │
└─────────────────────────────────────────────────────────────┘
Gain : Plus de 17 heures économisées !
Temps de vérification --check (base 5 TB, 10,000 tables)
5h ┤
│ ████████████████
│ ████████████████ PG 17 (jobs=1)
4h ┤ ████████████████
│ ████████████████
│
3h ┤
│
2h ┤
│
│ ████
1h ┤ ████ PG 18 (jobs=4)
│ ██
│ ██ PG 18 (jobs=8)
│ █
│ █ PG 18 (jobs=16)
└─────────────────────────────
PG17 j=4 j=8 j=16
Plus on ajoute de workers, moins le gain est proportionnel :
┌─────────────────────────────────────────────────────────────┐
│ Rendements décroissants avec --jobs │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1 → 2 jobs : Gain de 90% (presque 2× plus rapide) │
│ 2 → 4 jobs : Gain de 80% (1.8× plus rapide) │
│ 4 → 8 jobs : Gain de 60% (1.6× plus rapide) │
│ 8 → 16 jobs : Gain de 40% (1.4× plus rapide) │
│ 16 → 32 jobs: Gain de 20% (1.2× plus rapide) │
│ │
│ Raison : Overhead, contention, limites I/O │
│ │
└─────────────────────────────────────────────────────────────┘
Conclusion : Il existe un point optimal au-delà duquel ajouter des jobs n'aide plus vraiment.
Comprendre ce qui est vérifié aide à comprendre pourquoi la parallélisation est si efficace.
Ces vérifications sont exécutées une seule fois :
✅ Checking cluster versions
✅ Checking database user is the install user
✅ Checking database connection settings
✅ Checking for prepared transactions
✅ Checking for system-defined composite types in user tables
Temps : Quelques secondes à quelques minutes, peu importe --jobs
✅ Checking for presence of required libraries
✅ Checking database user is the install user
✅ Checking for prepared transactions
Temps avec --jobs=1 : Proportionnel au nombre de databases
Temps avec --jobs=4 : Divisé par ~3-4
✅ Checking for reg* data types in user tables
✅ Checking for contrib/isn with bigint-passing mismatch
✅ Checking for user-defined encoding conversions
✅ Checking for user-defined postfix operators
✅ Checking for incompatible polymorphic functions
✅ Checking for tables WITH OIDS
✅ Checking for invalid "sql_identifier" user columns
✅ Checking for extension updates
C'est ici que --jobs fait toute la différence !
Avec 10,000 tables :
--jobs=1: Vérifie 1 table à la fois → 10,000 étapes séquentielles--jobs=16: Vérifie 16 tables simultanément → ~625 étapes
Checking for reg* data types in user tables
Table 1/10000: public.users [==== ] 0.01%
...
(10 secondes par table × 10,000 tables = 27 heures !)
Checking for reg* data types in user tables (8 workers)
Worker 1: public.users [==== ]
Worker 2: public.orders [=== ]
Worker 3: public.products [====== ]
Worker 4: public.payments [== ]
Worker 5: public.reviews [===== ]
Worker 6: public.addresses [==== ]
Worker 7: public.inventory [=== ]
Worker 8: public.shipments [====== ]
Progress: [=============== ] 1250/10000 (12.5%)
(10 secondes × 10,000 / 8 ≈ 3.5 heures)
# 1. Nombre de CPU
nproc
# 16
# 2. RAM disponible
free -h | grep "Mem:"
# Mem: 62Gi 15Gi 45Gi
# 3. Type de disque
lsblk -d -o name,rota
# NAME ROTA
# sda 0 ← 0 = SSD, 1 = HDD
# 4. Performance I/O
iostat -x 1 5 # Observer pendant 5 secondes# Test 1 : Baseline avec 1 worker
time pg_upgrade --jobs=1 --check [options...]
# real: 45m 23s
# Test 2 : 4 workers
time pg_upgrade --jobs=4 --check [options...]
# real: 12m 10s (3.7× plus rapide)
# Test 3 : 8 workers
time pg_upgrade --jobs=8 --check [options...]
# real: 6m 45s (6.7× plus rapide)
# Test 4 : 16 workers
time pg_upgrade --jobs=16 --check [options...]
# real: 5m 20s (8.5× plus rapide)
# Test 5 : 32 workers (peut-être trop ?)
time pg_upgrade --jobs=32 --check [options...]
# real: 5m 15s (8.6× plus rapide - gain marginal)Résultat : Pour ce serveur, --jobs=16 est optimal. Au-delà, le gain est négligeable.
# Dans un terminal séparé pendant pg_upgrade
watch -n 1 'echo "=== CPU ==="; mpstat 1 1 | tail -2; \
echo "=== RAM ==="; free -h | grep Mem; \
echo "=== I/O ==="; iostat -x 1 1 | tail -n +7'Observer :
- CPU utilization : devrait être entre 50-80%
- RAM : devrait avoir au moins 2-4 GB de libre
- I/O wait (wa%) : devrait rester < 20%
Si I/O wait > 30% → Réduire --jobs (goulot d'étranglement disque)
#!/bin/bash
# find_optimal_jobs.sh
# Teste différentes valeurs de --jobs et recommande l'optimal
OLD_DIR="/var/lib/postgresql/17/main"
NEW_DIR="/var/lib/postgresql/18/main"
OLD_BIN="/usr/lib/postgresql/17/bin"
NEW_BIN="/usr/lib/postgresql/18/bin"
NCPU=$(nproc)
MAX_JOBS=$((NCPU * 3 / 4)) # 75% des CPU
echo "🔍 Tests de performance pg_upgrade --check"
echo "CPU disponibles : $NCPU"
echo "Tests jusqu'à : $MAX_JOBS jobs"
echo ""
for JOBS in 1 2 4 8 12 16; do
if [ $JOBS -gt $MAX_JOBS ]; then
break
fi
echo "📊 Test avec --jobs=$JOBS..."
START=$(date +%s)
pg_upgrade \
--old-datadir="$OLD_DIR" \
--new-datadir="$NEW_DIR" \
--old-bindir="$OLD_BIN" \
--new-bindir="$NEW_BIN" \
--jobs=$JOBS \
--check > /dev/null 2>&1
END=$(date +%s)
DURATION=$((END - START))
echo " Durée : ${DURATION}s"
echo ""
done
echo "✅ Tests terminés. Analysez les résultats ci-dessus."
echo "💡 Choisissez la valeur où le gain devient marginal." # 1. Déterminer --jobs optimal sur environnement de test
./find_optimal_jobs.sh
# 2. Documenter la valeur choisie
echo "OPTIMAL_JOBS=8" >> migration_config.env
# 3. Tester la migration complète sur staging
pg_upgrade --jobs=8 --check [options]# Vérification rapide avec parallélisation
time pg_upgrade \
--jobs=8 \
--check \
[autres options]
# Si < 30 minutes : OK pour production
# Si > 1 heure : Revoir --jobs ou optimiser la base# Migration complète avec --jobs optimisé
pg_upgrade \
--jobs=8 \
--swap \
--verbose \
[autres options]# 1. Toujours tester --check avec --jobs d'abord
pg_upgrade --jobs=8 --check [options]
# 2. Utiliser --verbose pour voir la progression
pg_upgrade --jobs=8 --verbose [options]
# 3. Monitorer les ressources pendant la migration
htop # ou top, dans un autre terminal
# 4. Documenter la valeur --jobs utilisée
echo "Migration PG 18 effectuée avec --jobs=8" >> migration.log
# 5. Laisser quelques CPU libres pour le système
# Si 16 CPU, utiliser --jobs=12 maximum# 1. Ne pas utiliser --jobs égal au nombre de CPU
# Mauvais : --jobs=16 sur serveur 16-core
# Bon : --jobs=12 sur serveur 16-core
# 2. Ne pas tester --jobs uniquement en production
# Toujours tester sur dev/staging d'abord
# 3. Ne pas ignorer les warnings sur les ressources
# Si pg_upgrade dit "not enough memory", l'écouter !
# 4. Ne pas utiliser --jobs trop élevé sur HDD
# HDD : max --jobs=4
# SSD : --jobs=8 à 16
# NVMe : --jobs=16+
# 5. Ne pas oublier de monitorer pendant la migration# Vérification parallélisée (nouveau PG 18)
pg_upgrade \
--jobs=8 \
--check \
[options]
# Économie de temps : Énorme sur grosses bases# Migration complète optimisée
pg_upgrade \
--jobs=8 \
--swap \
[options]
# Bénéfices : Rapidité + sécurité# Maximum de rapidité (mais sans filet)
pg_upgrade \
--jobs=16 \
--link \
[options]
# Usage : Environnements non-critiques# Voir la progression détaillée
pg_upgrade \
--jobs=8 \
--verbose \
[options]
# Affiche quel worker fait quoi# Dans un terminal séparé pendant pg_upgrade
watch -n 2 'ps aux | grep -E "pg_upgrade|postgres: worker"'
# Sortie exemple :
# postgres 12345 pg_upgrade --jobs=8 ...
# postgres 12346 postgres: worker process (analyze)
# postgres 12347 postgres: worker process (analyze)
# postgres 12348 postgres: worker process (analyze)
# postgres 12349 postgres: worker process (analyze)
# postgres 12350 postgres: worker process (analyze)
# postgres 12351 postgres: worker process (analyze)
# postgres 12352 postgres: worker process (analyze)
# postgres 12353 postgres: worker process (analyze)# Utilisation CPU par cœur
mpstat -P ALL 1
# Sortie :
# CPU %usr %sys %iowait %idle
# 0 87.2 8.3 2.1 2.4 ← Worker 1
# 1 89.1 7.5 1.8 1.6 ← Worker 2
# 2 86.7 9.2 2.5 1.6 ← Worker 3
# 3 88.3 8.1 1.9 1.7 ← Worker 4
# 4 85.9 9.4 2.3 2.4 ← Worker 5
# ...
# Si %idle < 5% sur tous les CPU → --jobs pourrait être trop élevé
# Si %iowait > 20% → Goulot d'étranglement disque# Utilisation mémoire en temps réel
watch -n 1 'free -h'
# total used free shared buff/cache available
# Mem: 62Gi 25Gi 10Gi 1.0Gi 26Gi 35Gi
# Si free < 2 GB pendant pg_upgrade → Risque de swap# Statistiques I/O
iostat -x 1
# Device r/s w/s rkB/s wkB/s await %util
# sda 234.5 123.2 45678 23456 12.3 78.5
# %util > 95% → Disque saturé, réduire --jobs
# await > 50ms → Latence élevée, réduire --jobs# Logs pg_upgrade avec timestamps
tail -f pg_upgrade_server.log
# Exemple de sortie avec --jobs=8 :
# [2024-11-23 10:15:23] Starting parallel workers (8 workers)
# [2024-11-23 10:15:23] Worker 1: Checking table public.users
# [2024-11-23 10:15:23] Worker 2: Checking table public.orders
# [2024-11-23 10:15:23] Worker 3: Checking table public.products
# [2024-11-23 10:15:24] Worker 1: Completed table public.users
# [2024-11-23 10:15:24] Worker 1: Checking table public.payments
# ...Contexte :
- Base : 200 GB, 1,500 tables
- Serveur : AWS RDS-like, 8 vCPU, 32 GB RAM, SSD
- Contrainte : Fenêtre de maintenance 4 heures
Stratégie :
# Après tests sur staging, configuration choisie :
JOBS=6 # 75% de 8 vCPU
# Vérification (PG 18)
time pg_upgrade --jobs=6 --check [options]
# Durée : 8 minutes (vs 28 minutes avec --jobs=1)
# Migration réelle
time pg_upgrade --jobs=6 --swap [options]
# Durée totale : 45 minutes
# Résultat : Migration dans la fenêtre, avec temps de confortGain : 20 minutes économisées sur la vérification
Contexte :
- Base : 3 TB, 8,000 tables
- Serveur : On-premise, 32 cores, 256 GB RAM, NVMe RAID
- Contrainte : Downtime < 6 heures
Stratégie :
# Configuration après tests :
JOBS=20 # ~60% de 32 cores (I/O en compte aussi)
# Vérification
time pg_upgrade --jobs=20 --check [options]
# Durée : 22 minutes (vs 3h15 avec --jobs=1)
# Migration réelle
time pg_upgrade --jobs=20 --swap --link [options]
# Durée totale : 3 heures
# Résultat : Dans la fenêtre avec margeGain : Presque 3 heures économisées !
Contexte :
- Base : 500 GB, 50,000 petites tables (multi-tenant)
- Serveur : Cloud, 16 vCPU, 64 GB RAM, SSD Premium
- Contrainte : Downtime < 2 heures
Défi : Beaucoup de petites tables → --jobs très efficace ici !
Stratégie :
# Configuration optimale pour beaucoup de tables :
JOBS=12
# Vérification (CRUCIAL avec autant de tables)
time pg_upgrade --jobs=12 --check [options]
# Durée : 18 minutes (vs 5+ heures avec --jobs=1 !)
# Migration
time pg_upgrade --jobs=12 --swap [options]
# Durée totale : 1h 20min
# Résultat : Largement dans la fenêtreGain : Plus de 4h30 économisées sur la vérification !
Contexte :
- Base : 100 GB, 500 tables
- Serveur : Ancien serveur, 8 cores, 16 GB RAM, HDD mécanique
- Contrainte : Budget limité, pas d'upgrade matériel
Attention : HDD = goulot d'étranglement I/O !
Stratégie :
# Tests progressifs :
# --jobs=8 : I/O wait 65%, inefficace
# --jobs=4 : I/O wait 35%, mieux
# --jobs=2 : I/O wait 15%, optimal
JOBS=2 # Limité par le disque, pas le CPU
# Vérification
time pg_upgrade --jobs=2 --check [options]
# Durée : 15 minutes (vs 25 minutes avec --jobs=1)
# Migration
time pg_upgrade --jobs=2 --swap [options]
# Durée : 1h 10minLeçon : Sur HDD, --jobs élevé ne sert à rien (peut même ralentir)
PostgreSQL impose une limite pratique sur le nombre de workers :
Limite technique : --jobs=64 (maximum)
Mais en pratique :
- Au-delà de 24-32 workers, gains marginaux
- Risque de contention et overhead
Certaines opérations restent séquentielles même avec --jobs :
Non parallélisables :
❌ Vérification des versions
❌ Vérification des transactions préparées globales
❌ Copie de fichiers système (pg_xact, pg_multixact)
❌ Opérations finales de finalisation
Ces opérations représentent généralement < 10% du temps total.
┌─────────────────────────────────────────────────────────────┐
│ Goulots d'étranglement limitant l'efficacité de --jobs │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. I/O disque (le plus fréquent) │
│ → HDD saturé dès --jobs=4 │
│ → Solution : SSD/NVMe ou limiter --jobs │
│ │
│ 2. Mémoire insuffisante │
│ → Swap commence = performances s'effondrent │
│ → Solution : Plus de RAM ou réduire --jobs │
│ │
│ 3. CPU insuffisant │
│ → Moins fréquent sur serveurs modernes │
│ → Solution : Limiter --jobs au nombre de cores │
│ │
│ 4. Réseau (pour stockage réseau type NFS) │
│ → Latence réseau limite le parallélisme │
│ → Solution : Stockage local ou --jobs modéré │
│ │
└─────────────────────────────────────────────────────────────┘
# Pendant pg_upgrade avec --jobs élevé
# Le système peut être fortement sollicité
# Exemple : --jobs=16 sur serveur partagé
# → Peut impacter d'autres services
# → Planifier pendant une fenêtre maintenance complèteChaque worker peut ouvrir des connexions à la base :
--jobs=8 × ~5 connexions par worker = ~40 connexions
Vérifier max_connections :
SHOW max_connections; -- Doit être > nombre de workers × 10
Plus de workers = plus de logs :
# Vérifier l'espace avant migration
df -h /var/log/postgresql/
# Avec --jobs=16, logs peuvent atteindre 1-2 GB
# pour une migration complèteSymptômes :
pg_upgrade --jobs=16 [options]
# Progression : 1 table / 30 secondes (très lent)Diagnostic :
# Vérifier I/O wait
iostat -x 1
# %iowait > 50% → Disque saturé
# Vérifier la mémoire
free -h
# free < 1 GB → Mémoire insuffisanteSolution :
# Réduire --jobs
pg_upgrade --jobs=4 [options] # Au lieu de 16
# Ou upgrade vers SSD si possibleSymptômes :
ERROR: number of workers (32) exceeds maximum allowed (24)
Solution :
# Réduire à la valeur recommandée
pg_upgrade --jobs=24 [options]Symptômes :
FATAL: out of memory
ERROR: worker process crashed
Diagnostic :
# Vérifier la mémoire disponible
free -h
# Si available < 4 GB → Problème
# Vérifier le swap
swapon --show
# Si swap utilisé activement → ProblèmeSolution :
# Réduire --jobs pour consommer moins de RAM
pg_upgrade --jobs=4 [options]
# Ou augmenter la RAM du serveurSymptômes :
# Progression s'arrête, workers semblent bloqués
Worker 3: [Waiting...]
Worker 5: [Waiting...]
Diagnostic :
# Vérifier les processus
ps aux | grep postgres
# Vérifier les locks
# (nécessite que l'ancien cluster soit démarré en mode spécial)Solution :
# Annuler et relancer avec moins de workers
Ctrl+C # Annuler pg_upgrade
pg_upgrade --jobs=4 [options] # Réessayer avec moins de workers ┌─────────────────────────────────────────────────────────────┐
│ Option --jobs : PG 17 vs PG 18 │
├─────────────────────────────────────────────────────────────┤
│ │
│ PostgreSQL 17 : │
│ ├─ --jobs=N pour MIGRATION : ✅ Oui │
│ └─ --jobs=N pour --check : ❌ Non (forcé à 1) │
│ │
│ PostgreSQL 18 : │
│ ├─ --jobs=N pour MIGRATION : ✅ Oui │
│ └─ --jobs=N pour --check : ✅ Oui (NOUVEAU !) │
│ │
│ Impact : │
│ → Phase --check 5-10× plus rapide dans PG 18 │
│ → Validation avant migration beaucoup plus praticable │
│ → Itérations de tests plus rapides │
│ │
└─────────────────────────────────────────────────────────────┘
| Opération | PG ≤ 17 | PG 18 | Gain |
|---|---|---|---|
| --check avec --jobs=1 | 45 min | 45 min | - |
| --check avec --jobs=8 | 45 min (forcé à 1) | 6 min | 7.5× |
| Migration avec --jobs=8 | 2h | 2h | - |
| Migration totale | 2h45 | 2h06 | ~30% |
DBA chez une FinTech :
"Avant PG 18, la phase --check prenait 3 heures sur notre base de 5 TB. On ne pouvait la lancer qu'une fois par jour en DEV. Avec PG 18 et --jobs=12, c'est 20 minutes. On peut tester beaucoup plus souvent !"
DevOps chez un e-commerce :
"La parallélisation de --check change tout. On peut valider notre migration le matin, faire des ajustements, et retester l'après-midi. Avant, chaque test prenait toute la nuit."
La parallélisation de --check avec --jobs dans PostgreSQL 18 est une amélioration qui peut sembler technique, mais qui a un impact pratique énorme sur les migrations en production.
- ✅ Vitesse : Vérifications 5-10× plus rapides
- ✅ Confiance : Tests itératifs possibles avant migration
- ✅ Flexibilité : Validation rapide même sur grosses bases
- ✅ Productivité : Moins de temps d'attente pour les équipes
- ✅ Sécurité : Plus de tests = moins de surprises
- --jobs fonctionne désormais pour --check (nouveau PG 18)
- Choisir --jobs = 50-75% des CPU disponibles (règle générale)
- Toujours tester sur DEV/staging d'abord pour trouver l'optimal
- Monitorer les ressources (CPU, RAM, I/O) pendant les tests
- HDD = max --jobs=4 ; SSD/NVMe = --jobs=8-16+
Pour une migration réussie avec --jobs :
1. Tester --check avec différentes valeurs de --jobs
2. Trouver le point optimal (gain vs ressources)
3. Documenter la configuration choisie
4. Utiliser cette configuration en production
5. Combiner avec --swap pour une migration optimale
Pour une compréhension complète de pg_upgrade dans PostgreSQL 18 :
- Section 19.3.1 : Préservation des statistiques (complémentaire)
- Section 19.3.2 : Option --swap pour sécurité et rapidité
- Section 19.3.4 : Stratégies Blue/Green pour downtime minimal
- Section 19.4 : Troubleshooting des migrations
Note : Retenez l'essentiel : PostgreSQL 18 permet de vérifier votre migration beaucoup plus rapidement en utilisant plusieurs "workers" qui travaillent en parallèle. C'est comme avoir plusieurs personnes qui vérifient différentes parties de votre base en même temps au lieu d'une seule personne qui fait tout séquentiellement. Le résultat ? Des migrations plus rapides et plus sûres !