## Migration d'Oracle vers PostgreSQL sans interruption : Une analyse technique
Migrer d'Oracle vers PostgreSQL sans arrêter le service est une tâche ardue mais réalisable. Dans cet article, nous décomposons une stratégie de migration étape par étape basée sur un projet réel avec des microservices Spring Boot, où un impact nul sur les utilisateurs était une exigence clé. L'utilisation de CDC via Debezium a permis une synchronisation des données en temps réel, évitant les interruptions et minimisant les risques.
Préparation : Analyse de la structure et des données
La première étape consiste en un audit approfondi de la base de données actuelle. Il faut comprendre le volume de données, la répartition des types de champs, la présence d'enregistrements obsolètes et les constructions spécifiques à Oracle sans équivalents directs dans PostgreSQL. Nettoyer les données inutiles réduit le volume de migration et accélère le processus.
Un aspect clé est le mappage des types de données. Par exemple :
NUMBER(1,0)→BOOLEANVARCHAR2→TEXTouVARCHARDATE→TIMESTAMP WITHOUT TIME ZONECLOB→TEXT
Pour l'analyse, nous avons utilisé cette requête SQL :
select distinct DATA_TYPE
from ALL_TAB_COLUMNS
where owner = 'schemat'
order by DATA_TYPE
Sur la base des résultats, nous avons créé un tableau de mappage des types de données qui a servi de fondement à toutes les transformations ultérieures. Il est également crucial de prendre en compte les différences dans la gestion des NULL et des chaînes vides : dans Oracle, une chaîne vide est traitée comme NULL, mais pas dans PostgreSQL. Cela nécessite des ajustements dans la logique métier et les requêtes.
Adaptation du schéma et Liquibase
Un simple remplacement du pilote de base de données provoque des erreurs. Les scripts de migration doivent être adaptés pour PostgreSQL. Pour cela :
- Les opérations DDL et DML sont séparées via les contextes Liquibase — les DML sont temporairement désactivées.
- Les scripts sont testés de manière itérative : après chaque modification, le changelog est exécuté, suivi d'un nettoyage et de tests smoke.
- Les préconditions sont vérifiées pour leur exactitude, et la cohérence du schéma avec Oracle est assurée.
Une attention particulière est portée aux séquences. Si elles ne sont pas synchronisées, les nouveaux ID pourraient entrer en conflit avec les données historiques. La solution :
- Au démarrage de l'application, vérifier la valeur actuelle de la séquence dans PostgreSQL.
- Si elle est inférieure à celle d'Oracle, l'avancer avec une marge de sécurité.
- La logique est idempotente : des exécutions répétées ne provoquent pas d'échecs.
En résultat, le schéma PostgreSQL cible a été assemblé en une seule pull request, prêt pour le peuplement des données.
Ajustements du code applicatif
Après un lancement réussi de l'application sur un PostgreSQL vide, des erreurs au niveau Java émergent. Principaux changements :
- Remplacer l'annotation
@Lobpar@Column(columnDefinition = "text"). - Gérer les NULL dans les requêtes SQL natives, en particulier dans les constructions
IN (...). - Passer des indicateurs numériques (0/1) à
boolean. - Ajuster la logique de comparaison de chaînes en tenant compte des différences Oracle/PostgreSQL.
- Réécrire les requêtes natives pour le dialecte PostgreSQL.
Les tests ont été effectués au niveau des tests unitaires et des scénarios d'intégration. Focus particulier sur les cas limites : chaînes vides, valeurs NULL, champs texte volumineux.
Mise en œuvre de CDC via Debezium et Kafka Connect
Nous avons choisi la pile classique : Debezium + Kafka Connect. Architecture :
- Le connecteur source (Debezium Oracle) lit le journal de redo et génère des événements CDC.
- Les événements sont envoyés vers Kafka (un topic par table).
- Le connecteur sink (JDBC Sink) applique les changements à PostgreSQL dans le même ordre.
Étapes de configuration :
- Instantané initial — copie complète des données au moment du démarrage.
- Changements en streaming — réplication continue des INSERT/UPDATE/DELETE à partir du journal de redo.
- Préservation de l'ordre — garantie de la séquence des changements via LogMiner.
Images utilisées :
quay.io/debezium/kafka:3.0quay.io/debezium/zookeeper:3.0quay.io/debezium/connect:3.0provectuslabs/kafka-ui:0.7.2(pour la surveillance)
La configuration se fait via API REST avec curl. L'interface Debezium était instable pendant la migration, donc les configurations ont été passées manuellement au format JSON.
Exemple de configuration du connecteur source :
{
"name": "oracle-connector",
"config": {
"connector.class": "io.debezium.connector.oracle.OracleConnector",
"database.hostname": "oracle-host",
"database.port": "1521",
"database.user": "user",
"database.password": "password",
"database.dbname": "ORCLCDB",
"database.server.name": "server1",
"table.include.list": "schema.table1,schema.table2",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes"
}
}
Exemple de configuration du connecteur sink :
{
"name": "postgres-sink",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url": "jdbc:postgresql://postgres:5432/db",
"connection.user": "user",
"connection.password": "password",
"topics": "server1.schema.table1,server1.schema.table2",
"auto.create": "false",
"auto.evolve": "false",
"insert.mode": "upsert",
"pk.mode": "record_key",
"pk.fields": "id"
}
}
Certaines tables (par ex., celles avec des clés composites) nécessitent des configurations séparées. Chaque connecteur est testé isolément.
Basculement final et contrôle qualité
Après achèvement de l'instantané initial et stabilisation du streaming :
- Lancement d'instances de test des services connectées à PostgreSQL.
- Tests de bout en bout : API, UI, processus en arrière-plan.
- Tests de charge sur des données similaires à la production.
- Au moment de charge minimale, basculement des DNS ou routes ingress vers les nouvelles instances.
- Surveillance des logs, métriques et alertes pendant 24–48 heures.
Le rollback n'est possible que jusqu'au point de basculement. Après cela, le système fonctionne exclusivement sur PostgreSQL. Les sauvegardes Oracle sont conservées pour une récupération d'urgence des données.
Enseignements clés
- Pas de solution universelle — chaque projet nécessite une adaptation personnalisée.
- CDC sans écritures doubles — un compromis acceptable avec un décalage de quelques secondes.
- Synchronisation des séquences — essentielle pour éviter les conflits d'ID.
- Tests à chaque étape — la clé d'une migration stable.
- Debezium + Kafka Connect — une pile flexible et fiable pour les migrations en ligne.
La migration a pris 18 heures, préparation incluse, mais l'interruption réelle pour les utilisateurs a été de 0 seconde. Le projet fonctionne avec succès sur PostgreSQL depuis plus d'un an sans régressions.
— Editorial Team
Aucun commentaire pour le moment.