TL;DR : La plupart des migrations d'Oracle vers PostgreSQL n'échouent pas à cause des outils — elles échouent à cause des étapes négligées.
Cette liste de contrôle couvre toutes les phases, de l'évaluation préalable à la mise en production : les pièges liés aux types de données qui causent une perte de données silencieuse, les différences de séquence et de NULL qui dégradent les applications après la mise en service, les étapes de test qui sont supprimées lorsque les délais sont dépassés, et les décisions de mise en production qui déterminent si vous pouvez revenir en arrière en cas de problème.
La migration d'Oracle vers PostgreSQL semblait simple sur le papier.
Le schéma était simple — cinquante tables, pas de partitionnement, PL/SQL léger.
L'équipe a exécuté ora2pg, les données ont été chargées proprement, les décomptes de lignes correspondaient.
Ils ont lancé en direct un samedi matin.
Lundi, la file d'attente du support était pleine.
Chaque horodatage du système affichait minuit.
Les colonnes Oracle DATE avaient été mappées à des colonnes PostgreSQL DATE – qui ne stockent que la date.
Deux ans de données temporelles, silencieusement écartés.
Aucune erreur.
Aucun avertissement.
Cette seule erreur — une mauvaise valeur par défaut dans la configuration de la migration — est évitable.
Il en va de même pour tous les autres modes de défaillance de cette liste.
Table des matières
Quelle est la cause la plus fréquente des échecs de migration d'Oracle vers PostgreSQL ?
La cause la plus fréquente n'est pas la complexité technique — ce sont des hypothèses non vérifiées.
Les équipes supposent que PostgreSQL gère les types de données, la sémantique NULL et la syntaxe SQL de la même manière qu'Oracle.
Ça ne le fait pas.
Les différences sont suffisamment petites pour passer inaperçues pendant le développement et suffisamment grandes pour casser la production.
La liste de contrôle ci-dessous est établie à partir de ces types de défaillance.
Chaque objet existe parce que quelqu'un a sauté et a payé plus tard.
Phase 1 : Évaluation préalable à la migration
L'évaluation devrait couvrir cinq domaines : les fonctionnalités spécifiques à Oracle utilisées, chaque colonne DATE qui doit être mappée à TIMESTAMP, l'utilisation des chaînes vides par rapport à NULL dans l'application, un décompte complet des objets PL/SQL, et une recherche de SQL de dialecte Oracle dans la base de code.
Si vous négligez l'un de ces points, vous découvrirez la lacune au milieu du projet, à un moment où il est coûteux d'y remédier.
La phase d'évaluation détermine la portée et le coût de tout ce qui suit.
L'ignorer est le moyen le plus rapide de dépasser le budget et de manquer la date de mise en production.
Auditer les fonctionnalités spécifiques à Oracle utilisées
Vérifiez le partitionnement, Advanced Queuing, le rafraîchissement rapide des vues matérialisées, Oracle Text et Workspace Manager.
Chacune de ces questions nécessite une décision architecturale — pas seulement un changement de syntaxe.
Certains ont des équivalents PostgreSQL.
Certains nécessitent une refonte.
Identifiez-les avant le début du projet, pas une fois la conversion de schéma achevée à 80%.
Mapper chaque colonne Oracle DATE — toujours en TIMESTAMP
Oracle DATE stock à la fois la date et l'heure.
Le type de données DATE de PostgreSQL ne stocke que la date.
La mise en correspondance d'Oracle DATE avec PostgreSQL DATE ignore silencieusement le composant temporel de chaque valeur de cette colonne.
Il n'y a pas d'erreur ni d'avertissement — les données se chargent proprement et le temps a disparu.
Chaque colonne Oracle DATE doit être mappée à TIMESTAMP dans PostgreSQL dans la configuration ora2pg, sans exception.
Audit de l'utilisation de la chaîne vide vs NULL
Oracle traite une chaîne vide ('') comme NULL.
PostgreSQL les traite comme des valeurs distinctes.
Une application qui insère '' s'attendre à un NULL se comportera différemment après la migration.
Interroger le schéma source pour les colonnes avec des contraintes NOT NULL et vérifier le code de l'application pour les insertions de chaînes vides avant le début de la migration.
Compter et catégoriser tous les objets PL/SQL
Exécuter le rapport d'évaluation ora2pgora2pg -t SHOW_REPORT) pour obtenir une estimation du nombre d'objets et du coût de migration.
Enregistrez le nombre de procédures stockées, fonctions, packages, déclencheurs et corps de package.
C'est le principal moteur des efforts et des coûts de migration.
Un schéma sans PL/SQL et sans fonctionnalités spécifiques à Oracle peut être migré en quelques jours.
Un schéma avec cinquante procédures stockées et dix packages prend des semaines.
Identifier le SQL spécifique à Oracle dans le code de l'application
Rechercher dans la base de code de l'application pour : ROWNUM, DE DUEL, NVL(, DÉCODE(, (+), CONNECT BY, SYSDATE, AJOUTER_MOIS, TRONQ(, TO_DATE(.
Chaque occurrence est une modification d'application nécessaire après la migration de la base de données.
Connaître le volume avant le début du projet permet d'éviter les surprises de périmètre en cours de route.
Séquences d'inventaire : valeurs CACHE et utilisation de CURRVAL
Les séquences Oracle utilisent par défaut CACHE 20.
Les séquences PostgreSQL font une mise en cache de 1 par défaut.
Les insertions à haut débit se comporteront différemment.
Identifiez également tous les emplacements du code de l'application qui appellent VALEUR ACTUELLE — PostgreSQL gère l'état des séquences en local à la session différemment, et la correction nécessite l'utilisation de RETOUR ou lastval().
Phase 2 : Conversion de schéma
Séquence CACHE
Définir une valeur CACHE réaliste dans la séquence DDL générée.
Pour la plupart des charges de travail OLTP, CACHE 20 ou plus est approprié.
PostgreSQL CACHE 1 signifie une écriture disque à chaque appel de séquence — c'est sûr, mais lent à l'échelle.
colonnes booléennes
Oracle n'a pas de type de données BOOLEAN natif.
Les applications stockent généralement les valeurs booléennes en tant que CHAR(1) ('Y'/'N') ou NUMÉRO(1) (1/0).
PostgreSQL a un type BOOLEAN natif.
Utilisez ora2pg MODIFICATION_TYPE directive pour convertir ces colonnes en BOULÉEN plutôt que de reporter la solution de contournement Oracle dans la nouvelle base de données.
Mettre à jour le code de l'application pour utiliser vrai/faux au lieu de 'Y'/'N' ou 1/0.
Identifier le cas
Oracle stocke les identificateurs non mis entre guillemets en majuscules.
PostgreSQL stocke les identifiants non cités en minuscules.
Ne citez jamais les identifiants dans PostgreSQL, sauf si le nom contient des caractères spéciaux ou une casse mixte qui doit être préservée.
Les identificateurs entre guillemets dans PostgreSQL sont sensibles à la casse — "Employé" et employé sont des objets différents.
L'approche la plus sûre consiste à laisser ora2pg convertir tous les identifiants en minuscules sans guillemets et à mettre à jour le code de l'application pour qu'il corresponde.
Partitionnement
Le partitionnement par liste, par plage et par hachage d'Oracle correspond directement au partitionnement déclaratif de PostgreSQL.
Le partitionnement par intervalle Oracle (création automatique de partitions par plage) n'a pas d'équivalent direct – implémentez-le avec une partition par plage et un travail planifié pour ajouter des partitions futures.
Le partitionnement composite d'Oracle (par exemple, range-hash) nécessite une conception manuelle dans PostgreSQL.
Identifier la stratégie de partitionnement et la tester dans PostgreSQL avant de migrer les données.
Types d'index
Les index Bitmap d'Oracle n'ont pas d'équivalent dans PostgreSQL.
Identifier tous les index Bitmap dans le schéma source et décider si un index B-tree standard, un index partiel ou un index BRIN permet d'obtenir le même plan de requête.
Ne sautez pas cette étape — les index manquants sont l'une des causes les plus fréquentes de problèmes de performance après une migration.
La date Oracle a-t-elle vraiment besoin d'être mappée à TIMESTAMP ?
Oui — toujours.
Oracle DATE stock à la fois la date et l'heure.
Le type de données DATE de PostgreSQL ne stocke que la date.
Le mappage d'une Oracle DATE à une PostgreSQL DATE supprime silencieusement le composant horaire de chaque valeur, sans erreur ni avertissement.
Ensemble MODIFY_TYPE date TIMESTAMP dans la configuration ora2pg et appliquez-la à toutes les colonnes de type DATE dans le schéma.
Phase 3 : Migration des données
Désactiver les contrôles de déclenchement FK avant le chargement, charger dans l'ordre (DDL → données → séquences), réinitialiser chaque séquence après le chargement à l'aide de setval(), validez le nombre de lignes pour chaque table, et vérifiez ponctuellement les données dans les colonnes de date, numériques et converties.
L'omission de l'une de ces étapes peut entraîner une corruption silencieuse des données ou des échecs d'insertion après la mise en production.
Désactiver les vérifications des déclencheurs de FK avant le chargement
ora2pg exporte les données de table par ordre alphabétique, pas par ordre de dépendance des clés étrangères.
Une table enfant apparaîtra souvent avant sa table parente dans le fichier de données, provoquant des violations de clés étrangères lors du chargement.
Charger des données dans une session avec SET session_replication_role = replica pour désactiver les contrôles de déclenchement FK, puis rétablir DÉFAUT immédiatement après que le chargement soit terminé.
Charger dans le bon ordre
Charger dans cet ordre : tables DDL → données → séquences.
Les tables doivent exister avant que les données puissent être chargées.
Les données doivent être chargées avant que les valeurs des séquences ne soient remises à zéro - COPY contourne entièrement les séquences, les laissant à leur valeur START, quelles que soient les ID chargées.
Réinitialiser les séquences après le chargement des données
Après le chargement des données, chaque séquence est encore à sa valeur START.
La prochaine insertion tentera d'utiliser une valeur de séquence qui existe déjà dans la table comme ID chargé.
Exécuter setval() pour que chaque séquence progresse au-delà de l'ID le plus chargé avant la mise en production de l'application.
L'ora2pg SÉQUENCE export génère ce script – exécutez-le comme étape finale.
Valider le nombre de lignes pour chaque table
Après le chargement, comparez le nombre de lignes entre Oracle et PostgreSQL pour chaque table.
Une divergence signifie qu'une erreur de COPIE a été ignorée silencieusement.
Vérifier la sortie psql pour ERREUR Lignes lors du chargement — La commande COPY signale les erreurs ligne par ligne et continue par défaut.
Contrôle ponctuel des données dans les colonnes à haut risque
Après avoir validé les décomptes de lignes, vérifiez manuellement les valeurs dans les colonnes DATE/TIMESTAMP, les colonnes numériques de haute précision et toutes les colonnes ayant fait l'objet d'une conversion de type.
Les comptages de lignes automatisés confirment l'exhaustivité ; des vérifications ponctuelles confirment l'exactitude.
En pleine migration et vous ne savez pas si vous avez tout couvert ?
Je propose une évaluation de la migration à prix fixe qui passe en revue votre schéma, votre configuration et votre plan de transition et qui fournit un registre des risques écrit avant la mise en service.
Voir ce que couvre l'évaluation
Phase 4 : Modifications d'application
Chaque construction SQL de dialecte Oracle doit être remplacée : ROWNUM → LIMIT, FROM DUAL supprimé, NVL → COALESCE, DECODE → CASE, jointures externes (+) → ANSI LEFT JOIN, CONNECT BY → WITH RECURSIVE, SYSDATE → NOW(), et CURRVAL remplacé par lastval() ou RETOUR.
PostgreSQL rejettera le SQL de dialecte Oracle à l'exécution — ce n'est pas facultatif.
| Oracle | Équivalent de PostgreSQL |
|---|---|
ROWNUM <= n | LIMITE n |
EXTRAIRE LES n PREMIÈRES LIGNES SEULEMENT | EXTRAIRE LES n PREMIÈRES LIGNES SEULEMENT (ANSI, fonctionne dans les deux cas) |
DE DUEL | Retirer — utiliser nu SELECTIONNER la valeur |
NVL(a, b) | COALESCE(a, b) |
DECODE(col, v1, r1, v2, r2, default) | CASE col WHEN v1 THEN r1 WHEN v2 THEN r2 ELSE default END |
col1 (+) = col2 | col1 JOINT GAUCHE col2 |
CONNECT BY PRIOR | AVEC RECURSIF |
SYSDATE | MAINTENANT() ou HORODATAGE_COURANT |
VALEUR ACTUELLE | lastval() ou RETURNING id |
ADD_MONTHS(d, n) | d + INTERVAL 'n mois' |
TRUNC(date) | DATE_TRUNC('day', date) |
Au-delà de la syntaxe, vérifiez les conversions de type implicites qu'Oracle accepte et que PostgreSQL rejette.
Oracle lancera silencieusement '123' à un nombre dans une comparaison numérique.
PostgreSQL générera une erreur d'incompatibilité de type.
Identifiez-les dans la demande et ajoutez des moulages explicites.
Phase 5 : Tests
Exécuter des tests de régression sur la base de données migrée
Chaque fonction qui touche au schéma migré doit être testée contre PostgreSQL avant la conversion.
Si l'application dispose d'une suite de tests existante, exécutez-la intégralement.
Dans le cas contraire, c'est la phase où l'absence de couverture de tests devient coûteuse — les tests fonctionnels manuels sont la seule alternative.
Établir une base de référence de performance avant la bascule
Exécutez le même ensemble de requêtes représentatives sur Oracle et PostgreSQL.
Collecter les plans d'exécution de PostgreSQL en utilisant EXPLIQUER (ANALYSER, TAMPONS).
Le planificateur de requêtes de PostgreSQL prend des décisions différentes de celui d'Oracle.
Les index manquants, les statistiques périmées et les mauvaises stratégies de jointure apparaissent tous ici - avant d'apparaître dans la production.
Test sous charge réaliste
Une requête qui fonctionne bien isolément peut se comporter différemment sous une charge concurrente.
Effectuez un test de charge contre PostgreSQL avec des volumes de données réels ou représentatifs avant de prendre une décision d'aller/ne pas aller.
pg_bench fournit des tests de débit de base ; des tests de charge au niveau de l'application par rapport au schéma migré sont préférables si l'outil existe.
Valider la gestion des cas limites de NULL
Testez chaque requête qui filtre sur NULL, insère NULL ou compare des colonnes pouvant contenir NULL.
La sémantique NULL est cohérente entre Oracle et PostgreSQL en SQL standard, mais le code d'application écrit selon le comportement "chaîne vide comme NULL" d'Oracle produira des résultats erronés.
Tester les identifiants générés par séquence lors d'insertions concurrentes
Exécutez des insertions concurrentes qui reposent sur des clés primaires générées par des séquences.
Vérifier qu'il n'y a pas de collisions et que les écarts de séquence se situent dans des limites acceptables pour l'application.
Phase 6 : Basculement
Décider de la stratégie de transition avant le début des travaux techniques
Deux choix s'offrent à nous : le basculement en fenêtre de maintenance (l'application est mise hors ligne pendant le basculement) ou le basculement sans temps d'arrêt (la réplication logique maintient la synchronisation de PostgreSQL pendant la transition).
La bascule pendant la fenêtre de maintenance est plus simple, moins chère et plus fiable.
Pour la plupart des systèmes internes ou non destinés au grand public, une fenêtre de maintenance de deux heures en dehors des heures de pointe est acceptable.
La bascule sans interruption de service ajoute une complexité et un coût considérables – ne l'utilisez que lorsque le SLA l'exige réellement.
Rédiger un plan de retour en arrière
La restauration à Oracle implique plusieurs étapes et considérations clés :**1. Durée :**La durée de la restauration à Oracle peut varier considérablement en fonction de plusieurs facteurs :* **Taille de la base de données :** Une base de données plus volumineuse prendra plus de temps à restaurer. * **Type de sauvegarde :** Une sauvegarde complète prendra plus de temps qu'une sauvegarde différentielle ou incrémentielle. * **Type de support de sauvegarde :** Restaurer à partir de bandes peut être plus lent que de restaurer à partir de disques ou d'un stockage cloud. * **Complexité de la configuration :** La présence de bases de données avancées, de Data Guard, d'options RAC, etc., peut influencer le temps. * **Performances du matériel :** La vitesse des disques, des contrôleurs et du réseau aura un impact. * **Niveau de compression de la sauvegarde :** Une compression plus élevée peut ralentir la lecture et le décompression. * **Le "point in time" ciblé :** Si vous restaurez à un moment précis très ancien, cela peut impliquer plus d'applications de journaux d'annulation (undo logs). * **Outil de sauvegarde utilisé :** RMAN est généralement optimisé pour la restauration, mais les performances peuvent varier.En pratique, cela peut aller de **quelques minutes** pour une petite base de données avec un stockage rapide et une sauvegarde récente, à **plusieurs heures, voire plusieurs jours** pour de très grandes bases de données, des supports de sauvegarde lents ou des restaurations complexes.**2. Qui exécute la restauration :**La restauration à Oracle est généralement exécutée par du personnel ayant des droits d'administration de base de données. Cela comprend typiquement :* **Administrateurs de bases de données (DBA) :** Ce sont les principaux responsables de la gestion et de la maintenance des bases de données Oracle. * **Ingénieurs de support Oracle ou de l'éditeur de solutions de sauvegarde :** Dans certains cas, notamment pour des problèmes complexes ou lors de la mise en œuvre initiale, le support du fournisseur peut être impliqué. * **Équipes d'exploitation/infrastructure :** Ces équipes peuvent être impliquées dans la préparation du matériel et de l'environnement réseau, ainsi que dans la supervision du processus.L'exécution se fait souvent via des utilitaires Oracle tels que **RMAN (Recovery Manager)**, qui est l'outil standard et le plus recommandé pour les opérations de sauvegarde et de restauration dans Oracle.**3. État des données à ce point :**Lorsque la restauration est terminée, l'état des données dépendra de ce qui a été spécifié lors de la commande de restauration :* **Restauration complète (Full Restore) :** Si vous effectuez une restauration complète vers la dernière sauvegarde disponible, la base de données sera dans l'état où elle se trouvait au moment où cette sauvegarde complète a été créée. Toutes les transactions validées après cette sauvegarde seront perdues. * **Restauration à un point dans le temps (Point-in-Time Recovery - PITR) :** Si vous ciblez un point spécifique dans le temps, Oracle restaurera la base de données à l'état de cette date et heure précises. Cela implique généralement de restaurer la dernière sauvegarde complète (ou incrémentielle/différentielle pertinente) et d'appliquer ensuite les journaux de transactions sauvegardés (archived redo logs) jusqu'au point désiré. Les transactions validées après ce point seront perdues. * **Restauration d'un tablespace ou d'un datafile :** Il est possible de restaurer et recover seulement des parties spécifiques de la base de données. L'état sera celui du moment de la sauvegarde pour ces objets restaurés, potentiellement mis à jour par les redo logs jusqu'à un certain point, laissant les autres parties de la base de données inchangées.**En résumé, le but de la restauration est de ramener la base de données à un état cohérent et opérationnel, soit au moment de la dernière sauvegarde, soit à un moment antérieur spécifié. Les données qui ont été modifiées après le point de restauration choisi seront généralement perdues.** Une bonne stratégie de sauvegarde avec des sauvegardes régulières et la conservation appropriée des archives redo logs est essentielle pour minimiser la perte de données lors d'une restauration.
Un plan de rollback qui n'a pas été rédigé n'existe pas.
Si un problème survient après le transfert et que l'équipe doit improviser un retour en arrière sous la pression, le résultat sera pire que si le plan avait été écrit et répété.
Définir les critères d'acceptation/refus par écrit
Avant la nuit de basculement, convenez par écrit des conditions dans lesquelles le basculement se déroule et des conditions dans lesquelles il est annulé.
Les décisions de go/no-go prises sous la pression du temps au milieu d'une fenêtre de maintenance ne sont pas fiables.
Exécution à sec de la transition dans la phase de mise en place
Exécutez la procédure de basculement complète — y compris le retour arrière — dans un environnement de staging au moins une fois avant la production.
L'essai à blanc mettra en évidence les lacunes procédurales qui ont échappé à la préparation technique.
Plan de communication
Déterminer qui doit être informé, à quel stade, par quel canal et qui a le pouvoir d'approuver le retour en arrière.
Documentez-le avant l'ouverture de la fenêtre de basculement.
Foire aux questions
La faute la plus courante dans une migration Oracle vers PostgreSQL est de traduire la syntaxe de manière littérale sans tenir compte des différences fondamentales entre les deux systèmes de gestion de bases de données.
Mappage des colonnes Oracle DATE en colonnes PostgreSQL DATE au lieu de TIMESTAMP.
Oracle DATE stock à la fois la date et l'heure.
Le type de données DATE de PostgreSQL ne stocke que la date.
La migration se termine sans erreur - et chaque valeur temporelle dans ces colonnes est silencieusement fixée à minuit.
Toujours mapper Oracle DATE à PostgreSQL TIMESTAMP.
Dois-je effectuer des tests de performance avant le passage à l'euro ?
Oui — toujours.
Le planificateur de requêtes de PostgreSQL prend des décisions différentes de celui d'Oracle.
Les index qui existaient dans Oracle n'ont peut-être pas été créés dans PostgreSQL.
Une requête qui s'exécute en 200 ms sur Oracle peut s'exécuter en 20 secondes sur PostgreSQL sans l'index approprié.
Établissez une base de référence de performance avant la bascule afin qu'il n'y ait pas de surprises le jour du lancement.
Quelle est l'approche la plus sûre pour le basculement d'une base de données Oracle de production ?
Une bascule dans une fenêtre de maintenance — où l'application devient brièvement indisponible lors du changement — est l'option la plus sûre pour la plupart des systèmes.
Il élimine la complexité liée à la synchronisation de deux bases de données et offre à l'équipe un point de basculement propre et déterministe.
Il est possible d'effectuer un basculement sans interruption de service via une réplication logique, mais cela entraîne des coûts et des risques importants.
Utilisez-le uniquement lorsque le SLA ne tolère absolument pas de fenêtre de maintenance.
Puis-je revenir en arrière après le basculement si quelque chose ne va pas ?
Oui, mais seulement si le plan de retour en arrière a été rédigé avant l'ouverture de la fenêtre de transition.
Un retour en arrière nécessite que l'environnement Oracle soit toujours intact, que l'état des données soit compris et que la procédure ait été répétée.
Si aucune de ces conditions n'est remplie, le retour en arrière devient une récupération improvisée sous pression.
Il faut toujours rédiger et répéter la procédure de retour en arrière avant la mise en production.
PostgreSQL gère-t-il NULL de la même manière qu'Oracle ?
Pour les sémantiques SQL standard de NULL — oui.
La différence se situe au niveau des chaînes vides : Oracle traite '' comme NULL, PostgreSQL les traite comme des valeurs distinctes.
Le code d'application qui insère '' en s'attendant à ce qu'il satisfasse une contrainte NOT NULL, ou qui interroge pour NULL en s'attendant à ce qu'il corresponde à des chaînes vides, se comportera différemment sur PostgreSQL.
Audit de ce modèle pendant la phase d'évaluation.
En résumé
Une migration d'Oracle vers PostgreSQL réussit ou échoue lors de la préparation.
Les outils sont gratuits, bien documentés et fiables.
Les échecs proviennent d'hypothèses non vérifiées : Oracle DATE mappé sur le mauvais type, séquences laissées à leur valeur de DÉMARRAGE, SQL d'application qu'Oracle a accepté silencieusement et PostgreSQL rejette explicitement.
Cette liste de contrôle couvre les modes de défaillance qui apparaissent le plus souvent lors des migrations réelles.
Travaillez à travers cela phase par phase — évaluation, conversion de schéma, migration de données, changements d'application, tests, basculement — et rien de tout cela ne devrait vous surprendre le jour du lancement.
Mettez cette page en signet - et si vous avez besoin d'aide pour l'appliquer en production, prendre contact →
