{"id":6655,"date":"2026-04-02T14:25:10","date_gmt":"2026-04-02T12:25:10","guid":{"rendered":"https:\/\/rootfan.com\/?p=6655"},"modified":"2026-04-20T22:49:52","modified_gmt":"2026-04-20T20:49:52","slug":"bonnes-pratiques-de-migration-doracle-vers-postgresql","status":"publish","type":"post","link":"https:\/\/rootfan.com\/fr\/oracle-to-postgresql-migration-best-practices\/","title":{"rendered":"Bonnes pratiques de migration d'Oracle vers PostgreSQL : une liste de contr\u00f4le pour les administrateurs de bases de donn\u00e9es et les architectes"},"content":{"rendered":"<p><strong>TL;DR :<\/strong> La plupart des migrations d'Oracle vers PostgreSQL n'\u00e9chouent pas \u00e0 cause des outils, mais \u00e0 cause d'\u00e9tapes saut\u00e9es.<br>Cette liste de contr\u00f4le couvre toutes les phases, de l'\u00e9valuation pr\u00e9alable \u00e0 la mise en production : les pi\u00e8ges li\u00e9s aux types de donn\u00e9es qui causent une perte de donn\u00e9es silencieuse, les diff\u00e9rences de s\u00e9quence et de NULL qui d\u00e9gradent les applications apr\u00e8s la mise en service, les \u00e9tapes de test qui sont supprim\u00e9es lorsque les d\u00e9lais sont d\u00e9pass\u00e9s, et les d\u00e9cisions de mise en production qui d\u00e9terminent si vous pouvez revenir en arri\u00e8re en cas de probl\u00e8me.<\/p>\n\n\n\n<!--more-->\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>La migration d'Oracle vers PostgreSQL semblait simple sur le papier.<\/p>\n\n\n\n<p>Le sch\u00e9ma \u00e9tait simple \u2014 cinquante tables, pas de partitionnement, PL\/SQL l\u00e9ger.<\/p>\n\n\n\n<p>L'\u00e9quipe a ex\u00e9cut\u00e9 ora2pg, les donn\u00e9es ont \u00e9t\u00e9 charg\u00e9es proprement, les d\u00e9comptes de lignes correspondaient.<\/p>\n\n\n\n<p>Ils ont lanc\u00e9 en direct un samedi matin.<\/p>\n\n\n\n<p>Lundi, la file d'attente du support \u00e9tait pleine.<\/p>\n\n\n\n<p>Chaque horodatage du syst\u00e8me affichait minuit.<\/p>\n\n\n\n<p>Les colonnes Oracle DATE avaient \u00e9t\u00e9 mapp\u00e9es \u00e0 des colonnes PostgreSQL DATE \u2013 qui ne stockent que la date.<\/p>\n\n\n\n<p>Deux ans de donn\u00e9es temporelles, silencieusement \u00e9cart\u00e9s.<\/p>\n\n\n\n<p>Aucune erreur.<\/p>\n\n\n\n<p>Aucun avertissement.<\/p>\n\n\n\n<p>Cette seule erreur \u2014 une mauvaise valeur par d\u00e9faut dans la configuration de la migration \u2014 est \u00e9vitable.<\/p>\n\n\n\n<p>Il en va de m\u00eame pour tous les autres modes de d\u00e9faillance de cette liste.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table des mati\u00e8res<\/h2><nav><ul><li><a href=\"#what-is-the-most-common-cause-of-oracle-to-postgre-sql-migration-failures\">Quelle est la cause la plus fr\u00e9quente des \u00e9checs de migration d'Oracle vers PostgreSQL ?<\/a><\/li><li><a href=\"#phase-1-pre-migration-assessment\">Phase 1 : \u00c9valuation pr\u00e9alable \u00e0 la migration<\/a><\/li><li><a href=\"#phase-2-schema-conversion\">Phase 2\u00a0: Conversion de sch\u00e9ma<\/a><\/li><li><a href=\"#phase-3-data-migration\">Phase 3 : Migration des donn\u00e9es<\/a><\/li><li><a href=\"#phase-4-application-changes\">Phase 4 : Modifications d'application<\/a><\/li><li><a href=\"#phase-5-testing\">Phase 5 : Tests<\/a><\/li><li><a href=\"#phase-6-cutover\">Phase 6 : Basculement<\/a><\/li><li><a href=\"#frequently-asked-questions\">Foire aux questions<\/a><ul><li><a href=\"#faq-question-1775135092634\">La faute la plus courante dans une migration Oracle vers PostgreSQL est de traduire la syntaxe de mani\u00e8re litt\u00e9rale sans tenir compte des diff\u00e9rences fondamentales entre les deux syst\u00e8mes de gestion de bases de donn\u00e9es.<\/a><\/li><li><a href=\"#faq-question-1775135093634\">Dois-je effectuer des tests de performance avant le passage \u00e0 l'euro ?<\/a><\/li><li><a href=\"#faq-question-1775135094634\">Quelle est l'approche la plus s\u00fbre pour le basculement d'une base de donn\u00e9es Oracle de production ?<\/a><\/li><li><a href=\"#faq-question-1775135095634\">Puis-je revenir en arri\u00e8re apr\u00e8s le basculement si quelque chose ne va pas ?<\/a><\/li><li><a href=\"#faq-question-1775135096634\">PostgreSQL g\u00e8re-t-il NULL de la m\u00eame mani\u00e8re qu'Oracle ?<\/a><\/li><\/ul><\/li><li><a href=\"#in-summary\">En r\u00e9sum\u00e9<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-the-most-common-cause-of-oracle-to-postgre-sql-migration-failures\">Quelle est la cause la plus fr\u00e9quente des \u00e9checs de migration d'Oracle vers PostgreSQL ?<\/h2>\n\n\n\n<p>La cause la plus fr\u00e9quente n'est pas la complexit\u00e9 technique \u2014 ce sont des hypoth\u00e8ses non v\u00e9rifi\u00e9es.<\/p>\n\n\n\n<p>Les \u00e9quipes supposent que PostgreSQL g\u00e8re les types de donn\u00e9es, la s\u00e9mantique NULL et la syntaxe SQL de la m\u00eame mani\u00e8re qu'Oracle.<\/p>\n\n\n\n<p>\u00c7a ne le fait pas.<\/p>\n\n\n\n<p>Les diff\u00e9rences sont suffisamment petites pour passer inaper\u00e7ues pendant le d\u00e9veloppement et suffisamment grandes pour casser la production.<\/p>\n\n\n\n<p>La liste de contr\u00f4le ci-dessous est \u00e9tablie \u00e0 partir de ces types de d\u00e9faillance.<\/p>\n\n\n\n<p>Chaque objet existe parce que quelqu'un a saut\u00e9 et a pay\u00e9 plus tard.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-1-pre-migration-assessment\">Phase 1 : \u00c9valuation pr\u00e9alable \u00e0 la migration<\/h2>\n\n\n\n<p>L'\u00e9valuation devrait couvrir cinq domaines : les fonctionnalit\u00e9s sp\u00e9cifiques \u00e0 Oracle utilis\u00e9es, chaque colonne DATE qui doit \u00eatre mapp\u00e9e \u00e0 TIMESTAMP, l'utilisation des cha\u00eenes vides par rapport \u00e0 NULL dans l'application, un d\u00e9compte complet des objets PL\/SQL, et une recherche de SQL de dialecte Oracle dans la base de code.<br>Si vous n\u00e9gligez l'un de ces points, vous d\u00e9couvrirez la lacune au milieu du projet, \u00e0 un moment o\u00f9 il est co\u00fbteux d'y rem\u00e9dier.<\/p>\n\n\n\n<p>La phase d'\u00e9valuation d\u00e9termine la port\u00e9e et le co\u00fbt de tout ce qui suit.<br>L'ignorer est le moyen le plus rapide de d\u00e9passer le budget et de manquer la date de mise en production.<\/p>\n\n\n\n<p><strong>Auditer les fonctionnalit\u00e9s sp\u00e9cifiques \u00e0 Oracle utilis\u00e9es<\/strong><br>V\u00e9rifiez le partitionnement, Advanced Queuing, le rafra\u00eechissement rapide des vues mat\u00e9rialis\u00e9es, Oracle Text et Workspace Manager.<br>Chacune de ces questions n\u00e9cessite une d\u00e9cision architecturale \u2014 pas seulement un changement de syntaxe.<br>Certains ont des \u00e9quivalents PostgreSQL.<br>Certains n\u00e9cessitent une refonte.<br>Identifiez-les avant le d\u00e9but du projet, pas une fois la conversion de sch\u00e9ma achev\u00e9e \u00e0 80%.<\/p>\n\n\n\n<p><strong>Mapper chaque colonne Oracle DATE \u2014 toujours en TIMESTAMP<\/strong><br>Oracle DATE stock \u00e0 la fois la date et l'heure.<br>Le type de donn\u00e9es DATE de PostgreSQL ne stocke que la date.<br>La mise en correspondance d'Oracle DATE avec PostgreSQL DATE ignore silencieusement le composant temporel de chaque valeur de cette colonne.<br>Il n'y a pas d'erreur ni d'avertissement \u2014 les donn\u00e9es se chargent proprement et le temps a disparu.<br>Chaque colonne Oracle DATE doit \u00eatre mapp\u00e9e \u00e0 TIMESTAMP dans PostgreSQL dans la configuration ora2pg, sans exception.<\/p>\n\n\n\n<p><strong>Audit de l'utilisation de la cha\u00eene vide vs NULL<\/strong><br>Oracle traite une cha\u00eene vide (<code>''<\/code>) comme NULL.<br>PostgreSQL les traite comme des valeurs distinctes.<br>Une application qui ins\u00e8re <code>''<\/code> s'attendre \u00e0 un NULL se comportera diff\u00e9remment apr\u00e8s la migration.<br>Interroger le sch\u00e9ma source pour les colonnes avec des contraintes NOT NULL et v\u00e9rifier le code de l'application pour les insertions de cha\u00eenes vides avant le d\u00e9but de la migration.<\/p>\n\n\n\n<p><strong>Compter et cat\u00e9goriser tous les objets PL\/SQL<\/strong><br>Ex\u00e9cuter le rapport d'\u00e9valuation ora2pg<code>ora2pg -t SHOW_REPORT<\/code>) pour obtenir une estimation du nombre d'objets et du co\u00fbt de migration.<br>Enregistrez le nombre de proc\u00e9dures stock\u00e9es, fonctions, packages, d\u00e9clencheurs et corps de package.<br>C'est le principal moteur des efforts et des co\u00fbts de migration.<br>Un sch\u00e9ma sans PL\/SQL et sans fonctionnalit\u00e9s sp\u00e9cifiques \u00e0 Oracle peut \u00eatre migr\u00e9 en quelques jours.<br>Un sch\u00e9ma avec cinquante proc\u00e9dures stock\u00e9es et dix packages prend des semaines.<\/p>\n\n\n\n<p><strong>Identifier le SQL sp\u00e9cifique \u00e0 Oracle dans le code de l'application<\/strong><br>Rechercher dans la base de code de l'application pour : <code>ROWNUM<\/code>, <code>DE DUEL<\/code>, <code>NVL(<\/code>, <code>D\u00c9CODE(<\/code>, <code>(+)<\/code>, <code>CONNECT BY<\/code>, <code>SYSDATE<\/code>, <code>AJOUTER_MOIS<\/code>, <code>TRONQ(<\/code>, <code>TO_DATE(<\/code>.<br>Chaque occurrence est une modification d'application n\u00e9cessaire apr\u00e8s la migration de la base de donn\u00e9es.<br>Conna\u00eetre le volume avant le d\u00e9but du projet permet d'\u00e9viter les surprises de p\u00e9rim\u00e8tre en cours de route.<\/p>\n\n\n\n<p><strong>S\u00e9quences d'inventaire : valeurs CACHE et utilisation de CURRVAL<\/strong><br>Les s\u00e9quences Oracle utilisent par d\u00e9faut CACHE 20.<br>Les s\u00e9quences PostgreSQL font une mise en cache de 1 par d\u00e9faut.<br>Les insertions \u00e0 haut d\u00e9bit se comporteront diff\u00e9remment.<br>Identifiez \u00e9galement tous les emplacements du code de l'application qui appellent <code>VALEUR ACTUELLE<\/code> \u2014 PostgreSQL g\u00e8re l'\u00e9tat des s\u00e9quences en local \u00e0 la session diff\u00e9remment, et la correction n\u00e9cessite l'utilisation de <code>RETOUR<\/code> ou <code>lastval()<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-2-schema-conversion\">Phase 2\u00a0: Conversion de sch\u00e9ma<\/h2>\n\n\n\n<p><strong>S\u00e9quence CACHE<\/strong><br>D\u00e9finir une valeur CACHE r\u00e9aliste dans la s\u00e9quence DDL g\u00e9n\u00e9r\u00e9e.<br>Pour la plupart des charges de travail OLTP, CACHE 20 ou plus est appropri\u00e9.<br>PostgreSQL CACHE 1 signifie une \u00e9criture disque \u00e0 chaque appel de s\u00e9quence \u2014 c'est s\u00fbr, mais lent \u00e0 l'\u00e9chelle.<\/p>\n\n\n\n<p><strong>colonnes bool\u00e9ennes<\/strong><br>Oracle n'a pas de type de donn\u00e9es BOOLEAN natif.<br>Les applications stockent g\u00e9n\u00e9ralement les valeurs bool\u00e9ennes en tant que <code>CHAR(1)<\/code> (<code>'Y'<\/code>\/<code>'N'<\/code>) ou <code>NUM\u00c9RO(1)<\/code> (<code>1<\/code>\/<code>0<\/code>).<br>PostgreSQL a un type BOOLEAN natif.<br>Utilisez ora2pg <code>MODIFICATION_TYPE<\/code> directive pour convertir ces colonnes en <code>BOUL\u00c9EN<\/code> plut\u00f4t que de reporter la solution de contournement Oracle dans la nouvelle base de donn\u00e9es.<br>Mettre \u00e0 jour le code de l'application pour utiliser <code>vrai<\/code>\/<code>faux<\/code> au lieu de <code>'Y'<\/code>\/<code>'N'<\/code> ou <code>1<\/code>\/<code>0<\/code>.<\/p>\n\n\n\n<p><strong>Identifier le cas<\/strong><br>Oracle stocke les identificateurs non mis entre guillemets en majuscules.<br>PostgreSQL stocke les identifiants non cit\u00e9s en minuscules.<br>Ne citez jamais les identifiants dans PostgreSQL, sauf si le nom contient des caract\u00e8res sp\u00e9ciaux ou une casse mixte qui doit \u00eatre pr\u00e9serv\u00e9e.<br>Les identificateurs entre guillemets dans PostgreSQL sont sensibles \u00e0 la casse \u2014 <code>\"Employ\u00e9\"<\/code> et <code>employ\u00e9<\/code> sont des objets diff\u00e9rents.<br>L'approche la plus s\u00fbre consiste \u00e0 laisser ora2pg convertir tous les identifiants en minuscules sans guillemets et \u00e0 mettre \u00e0 jour le code de l'application pour qu'il corresponde.<\/p>\n\n\n\n<p><strong>Partitionnement<\/strong><br>Le partitionnement par liste, par plage et par hachage d'Oracle correspond directement au partitionnement d\u00e9claratif de PostgreSQL.<br>Le partitionnement par intervalle Oracle (cr\u00e9ation automatique de partitions par plage) n'a pas d'\u00e9quivalent direct \u2013 impl\u00e9mentez-le avec une partition par plage et un travail planifi\u00e9 pour ajouter des partitions futures.<br>Le partitionnement composite d'Oracle (par exemple, range-hash) n\u00e9cessite une conception manuelle dans PostgreSQL.<br>Identifier la strat\u00e9gie de partitionnement et la tester dans PostgreSQL avant de migrer les donn\u00e9es.<\/p>\n\n\n\n<p><strong>Types d'index<\/strong><br>Les index Bitmap d'Oracle n'ont pas d'\u00e9quivalent dans PostgreSQL.<br>Identifier tous les index Bitmap dans le sch\u00e9ma source et d\u00e9cider si un index B-tree standard, un index partiel ou un index BRIN permet d'obtenir le m\u00eame plan de requ\u00eate.<br>Ne sautez pas cette \u00e9tape \u2014 les index manquants sont l'une des causes les plus fr\u00e9quentes de probl\u00e8mes de performance apr\u00e8s une migration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-3-data-migration\">Phase 3 : Migration des donn\u00e9es<\/h2>\n\n\n\n<p>D\u00e9sactiver les contr\u00f4les de d\u00e9clenchement FK avant le chargement, charger dans l'ordre (DDL \u2192 donn\u00e9es \u2192 s\u00e9quences), r\u00e9initialiser chaque s\u00e9quence apr\u00e8s le chargement \u00e0 l'aide de <code>setval()<\/code>, validez le nombre de lignes pour chaque table, et v\u00e9rifiez ponctuellement les donn\u00e9es dans les colonnes de date, num\u00e9riques et converties.<br>L'omission de l'une de ces \u00e9tapes peut entra\u00eener une corruption silencieuse des donn\u00e9es ou des \u00e9checs d'insertion apr\u00e8s la mise en production.<\/p>\n\n\n\n<p><strong>D\u00e9sactiver les v\u00e9rifications des d\u00e9clencheurs de FK avant le chargement<\/strong><br>ora2pg exporte les donn\u00e9es de table par ordre alphab\u00e9tique, pas par ordre de d\u00e9pendance des cl\u00e9s \u00e9trang\u00e8res.<br>Une table enfant appara\u00eetra souvent avant sa table parente dans le fichier de donn\u00e9es, provoquant des violations de cl\u00e9s \u00e9trang\u00e8res lors du chargement.<br>Charger des donn\u00e9es dans une session avec <code>SET session_replication_role = replica<\/code> pour d\u00e9sactiver les contr\u00f4les de d\u00e9clenchement FK, puis r\u00e9tablir <code>D\u00c9FAUT<\/code> imm\u00e9diatement apr\u00e8s que le chargement soit termin\u00e9.<\/p>\n\n\n\n<p><strong>Charger dans le bon ordre<\/strong><br>Charger dans cet ordre : tables DDL \u2192 donn\u00e9es \u2192 s\u00e9quences.<br>Les tables doivent exister avant que les donn\u00e9es puissent \u00eatre charg\u00e9es.<br>Les donn\u00e9es doivent \u00eatre charg\u00e9es avant que les valeurs des s\u00e9quences ne soient remises \u00e0 z\u00e9ro - COPY contourne enti\u00e8rement les s\u00e9quences, les laissant \u00e0 leur valeur START, quelles que soient les ID charg\u00e9es.<\/p>\n\n\n\n<p><strong>R\u00e9initialiser les s\u00e9quences apr\u00e8s le chargement des donn\u00e9es<\/strong><br>Apr\u00e8s le chargement des donn\u00e9es, chaque s\u00e9quence est encore \u00e0 sa valeur START.<br>La prochaine insertion tentera d'utiliser une valeur de s\u00e9quence qui existe d\u00e9j\u00e0 dans la table comme ID charg\u00e9.<br>Ex\u00e9cuter <code>setval()<\/code> pour que chaque s\u00e9quence progresse au-del\u00e0 de l'ID le plus charg\u00e9 avant la mise en production de l'application.<br>L'ora2pg <code>S\u00c9QUENCE<\/code> export g\u00e9n\u00e8re ce script \u2013 ex\u00e9cutez-le comme \u00e9tape finale.<\/p>\n\n\n\n<p><strong>Valider le nombre de lignes pour chaque table<\/strong><br>Apr\u00e8s le chargement, comparez le nombre de lignes entre Oracle et PostgreSQL pour chaque table.<br>Une divergence signifie qu'une erreur de COPIE a \u00e9t\u00e9 ignor\u00e9e silencieusement.<br>V\u00e9rifier la sortie psql pour <code>ERREUR<\/code> Lignes lors du chargement \u2014 La commande COPY signale les erreurs ligne par ligne et continue par d\u00e9faut.<\/p>\n\n\n\n<p><strong>Contr\u00f4le ponctuel des donn\u00e9es dans les colonnes \u00e0 haut risque<\/strong><br>Apr\u00e8s avoir valid\u00e9 les d\u00e9comptes de lignes, v\u00e9rifiez manuellement les valeurs dans les colonnes DATE\/TIMESTAMP, les colonnes num\u00e9riques de haute pr\u00e9cision et toutes les colonnes ayant fait l'objet d'une conversion de type.<br>Les comptages de lignes automatis\u00e9s confirment l'exhaustivit\u00e9 ; des v\u00e9rifications ponctuelles confirment l'exactitude.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>En pleine migration et vous ne savez pas si vous avez tout couvert ?<\/strong><br>Je propose une \u00e9valuation de la migration \u00e0 prix fixe qui passe en revue votre sch\u00e9ma, votre configuration et votre plan de transition et qui fournit un registre des risques \u00e9crit avant la mise en service.<br><a href=\"https:\/\/rootfan.com\/fr\/services\/\">Voir ce que couvre l'\u00e9valuation<\/a><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-4-application-changes\">Phase 4 : Modifications d'application<\/h2>\n\n\n\n<p>Chaque construction SQL de dialecte Oracle doit \u00eatre remplac\u00e9e : ROWNUM \u2192 LIMIT, FROM DUAL supprim\u00e9, NVL \u2192 COALESCE, DECODE \u2192 CASE, jointures externes (+) \u2192 ANSI LEFT JOIN, CONNECT BY \u2192 WITH RECURSIVE, SYSDATE \u2192 NOW(), et CURRVAL remplac\u00e9 par <code>lastval()<\/code> ou <code>RETOUR<\/code>.<br>PostgreSQL rejettera le SQL de dialecte Oracle \u00e0 l'ex\u00e9cution \u2014 ce n'est pas facultatif.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Oracle<\/th><th>\u00c9quivalent de PostgreSQL<\/th><\/tr><\/thead><tbody><tr><td><code>ROWNUM &lt;= n<\/code><\/td><td><code>LIMITE n<\/code><\/td><\/tr><tr><td><code>EXTRAIRE LES n PREMI\u00c8RES LIGNES SEULEMENT<\/code><\/td><td><code>EXTRAIRE LES n PREMI\u00c8RES LIGNES SEULEMENT<\/code> (ANSI, fonctionne dans les deux cas)<\/td><\/tr><tr><td><code>DE DUEL<\/code><\/td><td>Retirer \u2014 utiliser nu <code>SELECTIONNER la valeur<\/code><\/td><\/tr><tr><td><code>NVL(a, b)<\/code><\/td><td><code>COALESCE(a, b)<\/code><\/td><\/tr><tr><td><code>DECODE(col, v1, r1, v2, r2, default)<\/code><\/td><td><code>CASE col WHEN v1 THEN r1 WHEN v2 THEN r2 ELSE default END<\/code><\/td><\/tr><tr><td><code>col1 (+) = col2<\/code><\/td><td><code>col1 JOINT GAUCHE col2<\/code><\/td><\/tr><tr><td><code>CONNECT BY PRIOR<\/code><\/td><td><code>AVEC RECURSIF<\/code><\/td><\/tr><tr><td><code>SYSDATE<\/code><\/td><td><code>MAINTENANT()<\/code> ou <code>HORODATAGE_COURANT<\/code><\/td><\/tr><tr><td><code>VALEUR ACTUELLE<\/code><\/td><td><code>lastval()<\/code> ou <code>RETURNING id<\/code><\/td><\/tr><tr><td><code>ADD_MONTHS(d, n)<\/code><\/td><td><code>d + INTERVAL 'n mois'<\/code><\/td><\/tr><tr><td><code>TRUNC(date)<\/code><\/td><td><code>DATE_TRUNC('day', date)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Au-del\u00e0 de la syntaxe, v\u00e9rifiez les conversions de type implicites qu'Oracle accepte et que PostgreSQL rejette.<br>Oracle lancera silencieusement <code>'123'<\/code> \u00e0 un nombre dans une comparaison num\u00e9rique.<br>PostgreSQL g\u00e9n\u00e9rera une erreur d'incompatibilit\u00e9 de type.<br>Identifiez-les dans la demande et ajoutez des moulages explicites.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-5-testing\">Phase 5 : Tests<\/h2>\n\n\n\n<p><strong>Ex\u00e9cuter des tests de r\u00e9gression sur la base de donn\u00e9es migr\u00e9e<\/strong><br>Chaque fonction qui touche au sch\u00e9ma migr\u00e9 doit \u00eatre test\u00e9e contre PostgreSQL avant la conversion.<br>Si l'application dispose d'une suite de tests existante, ex\u00e9cutez-la int\u00e9gralement.<br>Dans le cas contraire, c'est la phase o\u00f9 l'absence de couverture de tests devient co\u00fbteuse \u2014 les tests fonctionnels manuels sont la seule alternative.<\/p>\n\n\n\n<p><strong>\u00c9tablir une base de r\u00e9f\u00e9rence de performance avant la bascule<\/strong><br>Ex\u00e9cutez le m\u00eame ensemble de requ\u00eates repr\u00e9sentatives sur Oracle et PostgreSQL.<br>Collecter les plans d'ex\u00e9cution de PostgreSQL en utilisant <code>EXPLIQUER (ANALYSER, TAMPONS)<\/code>.<br>Le planificateur de requ\u00eates de PostgreSQL prend des d\u00e9cisions diff\u00e9rentes de celui d'Oracle.<br>Les index manquants, les statistiques p\u00e9rim\u00e9es et les mauvaises strat\u00e9gies de jointure apparaissent tous ici - avant d'appara\u00eetre dans la production.<\/p>\n\n\n\n<p><strong>Test sous charge r\u00e9aliste<\/strong><br>Une requ\u00eate qui fonctionne bien isol\u00e9ment peut se comporter diff\u00e9remment sous une charge concurrente.<br>Effectuez un test de charge contre PostgreSQL avec des volumes de donn\u00e9es r\u00e9els ou repr\u00e9sentatifs avant de prendre une d\u00e9cision d'aller\/ne pas aller.<br>pg_bench fournit des tests de d\u00e9bit de base ; des tests de charge au niveau de l'application par rapport au sch\u00e9ma migr\u00e9 sont pr\u00e9f\u00e9rables si l'outil existe.<\/p>\n\n\n\n<p><strong>Valider la gestion des cas limites de NULL<\/strong><br>Testez chaque requ\u00eate qui filtre sur NULL, ins\u00e8re NULL ou compare des colonnes pouvant contenir NULL.<br>La s\u00e9mantique de NULL est coh\u00e9rente entre Oracle et PostgreSQL en SQL standard, mais le code applicatif \u00e9crit pour le comportement d'Oracle qui consid\u00e8re une cha\u00eene vide comme NULL produira des r\u00e9sultats erron\u00e9s.<\/p>\n\n\n\n<p><strong>Tester les identifiants g\u00e9n\u00e9r\u00e9s par s\u00e9quence lors d'insertions concurrentes<\/strong><br>Ex\u00e9cutez des insertions concurrentes qui reposent sur des cl\u00e9s primaires g\u00e9n\u00e9r\u00e9es par des s\u00e9quences.<br>V\u00e9rifier qu'il n'y a pas de collisions et que les \u00e9carts de s\u00e9quence se situent dans des limites acceptables pour l'application.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-6-cutover\">Phase 6 : Basculement<\/h2>\n\n\n\n<p><strong>D\u00e9cider de la strat\u00e9gie de transition avant le d\u00e9but des travaux techniques<\/strong><br>Deux choix s'offrent \u00e0 nous : le basculement en fen\u00eatre de maintenance (l'application est mise hors ligne pendant le basculement) ou le basculement sans temps d'arr\u00eat (la r\u00e9plication logique maintient la synchronisation de PostgreSQL pendant la transition).<br>La bascule pendant la fen\u00eatre de maintenance est plus simple, moins ch\u00e8re et plus fiable.<br>Pour la plupart des syst\u00e8mes internes ou non destin\u00e9s au grand public, une fen\u00eatre de maintenance de deux heures en dehors des heures de pointe est acceptable.<br>La bascule sans interruption de service ajoute une complexit\u00e9 et un co\u00fbt consid\u00e9rables \u2013 ne l'utilisez que lorsque le SLA l'exige r\u00e9ellement.<\/p>\n\n\n\n<p><strong>R\u00e9diger un plan de retour en arri\u00e8re<\/strong><br>La restauration \u00e0 Oracle implique plusieurs \u00e9tapes et consid\u00e9rations cl\u00e9s :\n\n**1. Dur\u00e9e :**\n\nLa dur\u00e9e de la restauration \u00e0 Oracle peut varier consid\u00e9rablement en fonction de plusieurs facteurs :\n\n*   **Taille de la base de donn\u00e9es :** Une base de donn\u00e9es plus volumineuse prendra plus de temps \u00e0 restaurer.\n*   **Type de sauvegarde :** Une sauvegarde compl\u00e8te prendra plus de temps qu'une sauvegarde diff\u00e9rentielle ou incr\u00e9mentielle.\n*   **Type de support de sauvegarde :** Restaurer \u00e0 partir de bandes peut \u00eatre plus lent que de restaurer \u00e0 partir de disques ou d'un stockage cloud.\n*   **Complexit\u00e9 de la configuration :** La pr\u00e9sence de bases de donn\u00e9es avanc\u00e9es, de Data Guard, d'options RAC, etc., peut influencer le temps.\n*   **Performances du mat\u00e9riel :** La vitesse des disques, des contr\u00f4leurs et du r\u00e9seau aura un impact.\n*   **Niveau de compression de la sauvegarde :** Une compression plus \u00e9lev\u00e9e peut ralentir la lecture et le d\u00e9compression.\n*   **Le \"point in time\" cibl\u00e9 :** Si vous restaurez \u00e0 un moment pr\u00e9cis tr\u00e8s ancien, cela peut impliquer plus d'applications de journaux d'annulation (undo logs).\n*   **Outil de sauvegarde utilis\u00e9 :** RMAN est g\u00e9n\u00e9ralement optimis\u00e9 pour la restauration, mais les performances peuvent varier.\n\nEn pratique, cela peut aller de **quelques minutes** pour une petite base de donn\u00e9es avec un stockage rapide et une sauvegarde r\u00e9cente, \u00e0 **plusieurs heures, voire plusieurs jours** pour de tr\u00e8s grandes bases de donn\u00e9es, des supports de sauvegarde lents ou des restaurations complexes.\n\n**2. Qui ex\u00e9cute la restauration :**\n\nLa restauration \u00e0 Oracle est g\u00e9n\u00e9ralement ex\u00e9cut\u00e9e par du personnel ayant des droits d'administration de base de donn\u00e9es. Cela comprend typiquement :\n\n*   **Administrateurs de bases de donn\u00e9es (DBA) :** Ce sont les principaux responsables de la gestion et de la maintenance des bases de donn\u00e9es Oracle.\n*   **Ing\u00e9nieurs de support Oracle ou de l'\u00e9diteur de solutions de sauvegarde :** Dans certains cas, notamment pour des probl\u00e8mes complexes ou lors de la mise en \u0153uvre initiale, le support du fournisseur peut \u00eatre impliqu\u00e9.\n*   **\u00c9quipes d'exploitation\/infrastructure :** Ces \u00e9quipes peuvent \u00eatre impliqu\u00e9es dans la pr\u00e9paration du mat\u00e9riel et de l'environnement r\u00e9seau, ainsi que dans la supervision du processus.\n\nL'ex\u00e9cution se fait souvent via des utilitaires Oracle tels que **RMAN (Recovery Manager)**, qui est l'outil standard et le plus recommand\u00e9 pour les op\u00e9rations de sauvegarde et de restauration dans Oracle.\n\n**3. \u00c9tat des donn\u00e9es \u00e0 ce point :**\n\nLorsque la restauration est termin\u00e9e, l'\u00e9tat des donn\u00e9es d\u00e9pendra de ce qui a \u00e9t\u00e9 sp\u00e9cifi\u00e9 lors de la commande de restauration :\n\n*   **Restauration compl\u00e8te (Full Restore) :** Si vous effectuez une restauration compl\u00e8te vers la derni\u00e8re sauvegarde disponible, la base de donn\u00e9es sera dans l'\u00e9tat o\u00f9 elle se trouvait au moment o\u00f9 cette sauvegarde compl\u00e8te a \u00e9t\u00e9 cr\u00e9\u00e9e. Toutes les transactions valid\u00e9es apr\u00e8s cette sauvegarde seront perdues.\n*   **Restauration \u00e0 un point dans le temps (Point-in-Time Recovery - PITR) :** Si vous ciblez un point sp\u00e9cifique dans le temps, Oracle restaurera la base de donn\u00e9es \u00e0 l'\u00e9tat de cette date et heure pr\u00e9cises. Cela implique g\u00e9n\u00e9ralement de restaurer la derni\u00e8re sauvegarde compl\u00e8te (ou incr\u00e9mentielle\/diff\u00e9rentielle pertinente) et d'appliquer ensuite les journaux de transactions sauvegard\u00e9s (archived redo logs) jusqu'au point d\u00e9sir\u00e9. Les transactions valid\u00e9es apr\u00e8s ce point seront perdues.\n*   **Restauration d'un tablespace ou d'un datafile :** Il est possible de restaurer et recover seulement des parties sp\u00e9cifiques de la base de donn\u00e9es. L'\u00e9tat sera celui du moment de la sauvegarde pour ces objets restaur\u00e9s, potentiellement mis \u00e0 jour par les redo logs jusqu'\u00e0 un certain point, laissant les autres parties de la base de donn\u00e9es inchang\u00e9es.\n\n**En r\u00e9sum\u00e9, le but de la restauration est de ramener la base de donn\u00e9es \u00e0 un \u00e9tat coh\u00e9rent et op\u00e9rationnel, soit au moment de la derni\u00e8re sauvegarde, soit \u00e0 un moment ant\u00e9rieur sp\u00e9cifi\u00e9. Les donn\u00e9es qui ont \u00e9t\u00e9 modifi\u00e9es apr\u00e8s le point de restauration choisi seront g\u00e9n\u00e9ralement perdues.** Une bonne strat\u00e9gie de sauvegarde avec des sauvegardes r\u00e9guli\u00e8res et la conservation appropri\u00e9e des archives redo logs est essentielle pour minimiser la perte de donn\u00e9es lors d'une restauration.<br>Un plan de rollback qui n'a pas \u00e9t\u00e9 r\u00e9dig\u00e9 n'existe pas.<br>Si un probl\u00e8me survient apr\u00e8s le transfert et que l'\u00e9quipe doit improviser un retour en arri\u00e8re sous la pression, le r\u00e9sultat sera pire que si le plan avait \u00e9t\u00e9 \u00e9crit et r\u00e9p\u00e9t\u00e9.<\/p>\n\n\n\n<p><strong>D\u00e9finir les crit\u00e8res d'acceptation\/refus par \u00e9crit<\/strong><br>Avant la nuit de basculement, convenez par \u00e9crit des conditions dans lesquelles le basculement se d\u00e9roule et des conditions dans lesquelles il est annul\u00e9.<br>Les d\u00e9cisions de go\/no-go prises sous la pression du temps au milieu d'une fen\u00eatre de maintenance ne sont pas fiables.<\/p>\n\n\n\n<p><strong>Ex\u00e9cution \u00e0 sec de la transition dans la phase de mise en place<\/strong><br>Ex\u00e9cutez la proc\u00e9dure de basculement compl\u00e8te \u2014 y compris le retour arri\u00e8re \u2014 dans un environnement de staging au moins une fois avant la production.<br>L'essai \u00e0 blanc mettra en \u00e9vidence les lacunes proc\u00e9durales qui ont \u00e9chapp\u00e9 \u00e0 la pr\u00e9paration technique.<\/p>\n\n\n\n<p><strong>Plan de communication<\/strong><br>D\u00e9terminer qui doit \u00eatre inform\u00e9, \u00e0 quel stade, par quel canal et qui a le pouvoir d'approuver le retour en arri\u00e8re.<br>Documentez-le avant l'ouverture de la fen\u00eatre de basculement.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"frequently-asked-questions\">Foire aux questions<\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list\">\n<div id=\"faq-question-1775135092634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>La faute la plus courante dans une migration Oracle vers PostgreSQL est de traduire la syntaxe de mani\u00e8re litt\u00e9rale sans tenir compte des diff\u00e9rences fondamentales entre les deux syst\u00e8mes de gestion de bases de donn\u00e9es.<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Mappage des colonnes Oracle DATE en colonnes PostgreSQL DATE au lieu de TIMESTAMP.<br \/>Oracle DATE stock \u00e0 la fois la date et l'heure.<br \/>Le type de donn\u00e9es DATE de PostgreSQL ne stocke que la date.<br \/>La migration se termine sans erreur - et chaque valeur temporelle dans ces colonnes est silencieusement fix\u00e9e \u00e0 minuit.<br \/>Toujours mapper Oracle DATE \u00e0 PostgreSQL TIMESTAMP.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135093634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>Dois-je effectuer des tests de performance avant le passage \u00e0 l'euro ?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Oui \u2014 toujours.<br \/>Le planificateur de requ\u00eates de PostgreSQL prend des d\u00e9cisions diff\u00e9rentes de celui d'Oracle.<br \/>Les index qui existaient dans Oracle n'ont peut-\u00eatre pas \u00e9t\u00e9 cr\u00e9\u00e9s dans PostgreSQL.<br \/>Une requ\u00eate qui s'ex\u00e9cute en 200 ms sur Oracle peut s'ex\u00e9cuter en 20 secondes sur PostgreSQL sans l'index appropri\u00e9.<br \/>\u00c9tablissez une base de r\u00e9f\u00e9rence de performance avant la bascule afin qu'il n'y ait pas de surprises le jour du lancement.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135094634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>Quelle est l'approche la plus s\u00fbre pour le basculement d'une base de donn\u00e9es Oracle de production ?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Une bascule dans une fen\u00eatre de maintenance \u2014 o\u00f9 l'application devient bri\u00e8vement indisponible lors du changement \u2014 est l'option la plus s\u00fbre pour la plupart des syst\u00e8mes.<br \/>Il \u00e9limine la complexit\u00e9 li\u00e9e \u00e0 la synchronisation de deux bases de donn\u00e9es et offre \u00e0 l'\u00e9quipe un point de basculement propre et d\u00e9terministe.<br \/>Il est possible d'effectuer un basculement sans interruption de service via une r\u00e9plication logique, mais cela entra\u00eene des co\u00fbts et des risques importants.<br \/>Utilisez-le uniquement lorsque le SLA ne tol\u00e8re absolument pas de fen\u00eatre de maintenance.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135095634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>Puis-je revenir en arri\u00e8re apr\u00e8s le basculement si quelque chose ne va pas ?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Oui, mais seulement si le plan de retour en arri\u00e8re a \u00e9t\u00e9 r\u00e9dig\u00e9 avant l'ouverture de la fen\u00eatre de transition.<br \/>Un retour en arri\u00e8re n\u00e9cessite que l'environnement Oracle soit toujours intact, que l'\u00e9tat des donn\u00e9es soit compris et que la proc\u00e9dure ait \u00e9t\u00e9 r\u00e9p\u00e9t\u00e9e.<br \/>Si aucune de ces conditions n'est remplie, le retour en arri\u00e8re devient une r\u00e9cup\u00e9ration improvis\u00e9e sous pression.<br \/>Il faut toujours r\u00e9diger et r\u00e9p\u00e9ter la proc\u00e9dure de retour en arri\u00e8re avant la mise en production.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135096634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>PostgreSQL g\u00e8re-t-il NULL de la m\u00eame mani\u00e8re qu'Oracle ?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Pour les s\u00e9mantiques SQL standard de NULL \u2014 oui.<br \/>La diff\u00e9rence se situe au niveau des cha\u00eenes vides : Oracle traite '' comme NULL, PostgreSQL les traite comme des valeurs distinctes.<br \/>Le code d'application qui ins\u00e8re '' en s'attendant \u00e0 ce qu'il satisfasse une contrainte NOT NULL, ou qui interroge pour NULL en s'attendant \u00e0 ce qu'il corresponde \u00e0 des cha\u00eenes vides, se comportera diff\u00e9remment sur PostgreSQL.<br \/>Audit de ce mod\u00e8le pendant la phase d'\u00e9valuation.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-summary\">En r\u00e9sum\u00e9<\/h2>\n\n\n\n<p>Une migration d'Oracle vers PostgreSQL r\u00e9ussit ou \u00e9choue lors de la pr\u00e9paration.<br>Les outils sont gratuits, bien document\u00e9s et fiables.<br>Les \u00e9checs proviennent d'hypoth\u00e8ses non v\u00e9rifi\u00e9es : Oracle DATE mapp\u00e9 sur le mauvais type, s\u00e9quences laiss\u00e9es \u00e0 leur valeur de D\u00c9MARRAGE, SQL d'application qu'Oracle a accept\u00e9 silencieusement et PostgreSQL rejette explicitement.<\/p>\n\n\n\n<p>Cette liste de contr\u00f4le couvre les modes de d\u00e9faillance qui apparaissent le plus souvent lors des migrations r\u00e9elles.<br>Travaillez \u00e0 travers cela phase par phase \u2014 \u00e9valuation, conversion de sch\u00e9ma, migration de donn\u00e9es, changements d'application, tests, basculement \u2014 et rien de tout cela ne devrait vous surprendre le jour du lancement.<\/p>\n\n\n\n<p>Mettez cette page en signet - et si vous avez besoin d'aide pour l'appliquer en production, <a href=\"https:\/\/rootfan.com\/fr\/services\/\">prendre contact \u2192<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>En bref : La plupart des migrations d'Oracle vers PostgreSQL n'\u00e9chouent pas \u00e0 cause des outils \u2014 elles \u00e9chouent \u00e0 cause des \u00e9tapes manqu\u00e9es. Cette checklist couvre toutes les phases, de l'\u00e9valuation pr\u00e9-migration \u00e0 la bascule : les pi\u00e8ges des types de donn\u00e9es qui causent une perte de donn\u00e9es silencieuse, les diff\u00e9rences de s\u00e9quences et de NULL qui font planter les applications apr\u00e8s la mise en service, les \u00e9tapes de test qui sont r\u00e9duites lorsque les d\u00e9lais\u2026 <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/rootfan.com\/fr\/oracle-to-postgresql-migration-best-practices\/\" class=\"more-link\">Continuer la lecture<span class=\"screen-reader-text\"> de &laquo;&nbsp;Oracle to PostgreSQL Migration Best Practices: A Checklist for DBAs and Architects&nbsp;&raquo;<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":6656,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_focus_keyword":"oracle to postgresql migration best practices","rank_math_title":"Oracle to PostgreSQL Migration Best Practices: A Checklist for DBAs and Architects","rank_math_description":"A phase-by-phase checklist of Oracle to PostgreSQL migration best practices \u2014 covering pre-migration assessment, schema conversion, data migration, application changes, testing, and cutover.","rank_math_robots":"","rank_math_og_title":"","rank_math_og_description":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[146],"tags":[140,143,141,137,142,81],"class_list":["post-6655","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle-to-postgresql","tag-audit","tag-data-migration","tag-data-types","tag-migration","tag-pl-sql","tag-step-by-step"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/rootfan.com\/wp-content\/uploads\/pexels-photo-5674761.jpeg?fit=1880%2C1253&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/posts\/6655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/comments?post=6655"}],"version-history":[{"count":12,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/posts\/6655\/revisions"}],"predecessor-version":[{"id":6786,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/posts\/6655\/revisions\/6786"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/media\/6656"}],"wp:attachment":[{"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/media?parent=6655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/categories?post=6655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rootfan.com\/fr\/wp-json\/wp\/v2\/tags?post=6655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}