Retour aux projets
15 avr. 2026 • Projet

SpringBatch-ETL : migrer 73 millions de lignes en 40 minutes

ETL Java 21 / Spring Batch pour la migration de PharmaGDD v1 vers v2 : 73 M de lignes MySQL à ~1,8 M lignes/min, colonnes PHP sérialisées décodées par un daemon Swoole en TCP, rejoué chaque nuit par GitHub Actions.

Java 21Spring BatchSwooleMySQLDockerGitHub Actions
Contexte
La refonte de PharmaGDD (v1 Symfony vers v2 Sylius) demande de migrer toute la base, dont des colonnes stockées au format sérialisé de PHP.
Mon rôle
Conception et développement de l'ETL, puis de son pipeline : images Docker, exécution nocturne sur une VM cloud, contrôles d'intégrité.
Résultat
73 millions de lignes migrées en 40 minutes (~1,8 M lignes/min), rejouées chaque nuit sur le dump de prod.

Le contexte

PharmaGDD passe de sa v1 (Symfony, legacy) à une v2 sous Sylius. Les schémas ne sont pas les mêmes, et une partie des données est stockée dans des colonnes sérialisées au format PHP (serialize()), illisibles telles quelles depuis Java.

Il fallait un outil capable de migrer 73 millions de lignes en un temps raisonnable, et de le refaire autant de fois que nécessaire avant la bascule.

Décoder du PHP depuis Java

C’est la contrainte qui a guidé l’architecture.

Le pipeline

L’ETL est écrit en Java 21 avec Spring Batch, qui découpe le travail en chunks transactionnels.

Résultat : environ 1,8 million de lignes par minute, soit 40 minutes pour l’ensemble.

Rejoué chaque nuit

Une migration ne se joue pas une seule fois. Pour arriver à la bascule avec un outil éprouvé, l’ETL tourne toutes les nuits sur une VM cloud, orchestré par GitHub Actions sur un runner self-hosted :

  1. Téléchargement du dump de prod du jour depuis un bucket S3 OVH, puis import dans une MySQL source.
  2. Lancement de l’ETL à partir des images Docker (ETL Java et daemon Swoole), construites par la CI et poussées dans le registry OVH.
  3. Contrôles d’intégrité sur la base cible : des requêtes comptent les lignes orphelines (clés étrangères sans parent). Un résultat non nul fait échouer le run.
  4. Nettoyage des conteneurs et des données.

Ces contrôles attrapent par exemple une table parente oubliée dans la configuration : les enfants sont migrés, le parent non, et l’erreur remonte dès le lendemain au lieu d’apparaître des jours plus tard.

Ce que j’en retiens