Aller au contenu
← Idées

Modifications de schéma de base de données : déployer sans interrompre le service

Découvrez comment déployer des modifications de schéma avec plusieurs versions de l’application, des validations et un retrait progressif afin de réduire les interruptions et les risques.

Schéma d’une modification de base de données déployée par étapes, avec plusieurs versions de l’application en coexistence puis le retrait de l’ancien schéma.

Modifier une table peut sembler être un changement interne, mais une application en production a rarement un seul consommateur de la base de données. Pendant un déploiement, différentes versions du service peuvent coexister ; des requêtes de reporting, des intégrations ou des tâches planifiées peuvent également dépendre du schéma actuel. Si une modification cesse d’être compatible avec l’un de ces consommateurs, elle peut provoquer une erreur visible ou une interruption de service.

La stratégie la plus sûre ne consiste pas à modifier le schéma et le code en même temps, mais à diviser le travail en étapes compatibles. Chaque version peut ainsi continuer à fonctionner pendant le déploiement de la suivante et la vérification de son comportement. Cette approche n’élimine pas tous les risques : elle suppose de connaître les dépendances, de surveiller le système et de décider à l’avance de la conduite à tenir en cas de problème.

Pourquoi une petite modification peut interrompre le service

Pourquoi une petite modification peut interrompre le service

Le schéma est un contrat entre la base de données et tous les logiciels qui l’interrogent. Une ancienne version de l’application peut s’attendre à trouver une colonne supprimée par une migration ; une nouvelle version peut supposer qu’une colonne existe alors qu’elle n’a pas encore été créée. Ces situations sont fréquentes lorsque le déploiement de l’application et celui de la base de données ne se déroulent pas exactement au même moment.

La manière dont l’opération est exécutée compte également. Selon le moteur et la modification, un changement peut bloquer les écritures, prendre du temps ou entrer en concurrence avec la charge habituelle pour l’accès aux ressources. Ne partez pas du principe qu’une opération sera instantanée ou qu’elle aura le même impact dans tous les environnements. Vérifiez son comportement pour votre moteur et sa version, la taille et l’utilisation des tables, ainsi que le mécanisme de migration choisi.

Avant de planifier le changement, identifiez qui lit et écrit les données : les différentes versions de l’application, les services connectés, les requêtes analytiques, les traitements par lots, les scripts et les opérations manuelles. Examinez aussi les dépendances moins visibles, comme les procédures stockées, les vues et les contraintes. Si vous ne pouvez pas confirmer quels composants utilisent un champ, ne le supprimez pas encore.

Appliquer le modèle « expand and contract »

Le modèle expand and contract (« élargir puis réduire ») divise une modification incompatible en plusieurs phases. On commence par étendre le schéma de manière additive ; on déploie ensuite un code capable de coexister avec l’ancien ; enfin, on supprime l’élément obsolète lorsqu’aucun consommateur n’en a plus besoin. La compatibilité entre les étapes est essentielle : pendant la transition, chaque version active doit pouvoir fonctionner avec le schéma disponible.

  1. Élargir : ajoutez la nouvelle colonne, table ou structure sans supprimer ni modifier l’ancienne pour le moment. Évitez d’introduire d’emblée une contrainte que les données existantes ou l’ancienne application ne pourraient pas respecter.
  2. Préparer l’application : déployez une version capable de gérer l’ancien et le nouveau schéma, selon les besoins. Effectuez un déploiement progressif et confirmez que les anciennes instances ne sont plus actives avant de considérer qu’il n’y a plus de lectures ou d’écritures utilisant l’ancienne structure.
  3. Effectuer la transition : faites basculer les lectures ou les écritures vers la nouvelle représentation. Si les deux colonnes doivent être conservées, définissez la source de vérité et la manière de les synchroniser pendant cette période.
  4. Réduire : après avoir vérifié que le code et les processus n’utilisent plus l’ancien élément, supprimez-le lors d’une modification ultérieure. Cette phase doit être indépendante du déploiement qui a lancé la transition.

En séparant les phases, on évite qu’une application déployée progressivement se retrouve soudain face à un schéma qu’elle ne comprend pas encore. La réponse aux problèmes est également plus claire : il est souvent possible d’interrompre le changement de code sans annuler immédiatement une extension compatible du schéma.

Gérer les colonnes, les renommages et les changements de type

Nouvelles colonnes : ajoutez d’abord la colonne, puis déployez un code capable de fonctionner même si elle ne contient pas encore la valeur attendue. Commencez ensuite à l’alimenter et vérifiez que les nouvelles écritures se déroulent correctement. Si les enregistrements existants doivent être complétés, traitez cette tâche séparément : elle peut prendre du temps et consommer des ressources, et il est préférable d’en surveiller l’avancement. Ce n’est qu’une fois les données préparées et le nouveau champ utilisé en lecture que vous pouvez envisager de retirer l’ancien.

Renommages : un renommage direct est généralement incompatible avec les versions qui interrogent encore l’ancien nom. Il est plus sûr d’ajouter une colonne portant le nouveau nom, de coordonner temporairement les écritures, puis de faire basculer les lectures par étapes. Ne supprimez l’ancien nom qu’après avoir vérifié qu’aucune version active ni aucun processus dépendant ne l’utilise.

Changements de type : ne supposez pas qu’une conversion préservera toutes les valeurs. Définissez le traitement des données qui ne correspondent pas au nouveau type, vérifiez des échantillons et planifiez une conversion contrôlable et vérifiable. Si le nouveau type impose des règles plus strictes, validez les données existantes avant de les appliquer.

Contraintes et valeurs obligatoires : rendre une colonne obligatoire peut provoquer un échec s’il reste des lignes sans valeur ou si certains processus d’écriture ne la renseignent pas encore. Préparez d’abord les données et le code ; appliquez ensuite la contrainte lorsque vous pouvez démontrer qu’elle est respectée. La séquence exacte dépend du moteur de base de données et de sa gestion de la validation et des verrouillages.

Vérifications avant, pendant et après le déploiement

La réussite d’une migration ne se mesure pas uniquement à la fin de l’exécution de la commande. Vérifiez que le fonctionnement opérationnel et les fonctionnalités restent corrects. Avant le changement, consignez les éléments pertinents pour pouvoir les comparer et définissez les signaux qui justifieraient l’arrêt du déploiement.

  • Compatibilité : confirmez quelles versions de l’application seront actives à chaque étape et testez leur capacité à fonctionner avec le schéma correspondant.
  • Données : vérifiez les décomptes, les valeurs nulles et les règles métier pertinentes avant et après le changement. Pour une transformation, comparez le résultat à des critères connus au lieu de vous contenter de constater l’absence d’erreurs.
  • Performances : surveillez la durée de la migration, les verrouillages, la charge et la latence des opérations concernées. Si ces indicateurs se dégradent, interrompez l’étape suivante et évaluez l’impact avant de poursuivre.
  • Erreurs : examinez les échecs de requêtes, les exceptions de l’application et les erreurs dans les intégrations ou les tâches planifiées. L’absence d’alertes ne prouve pas à elle seule que tous les consommateurs ont été pris en compte.
  • Utilisation de l’ancien schéma : recherchez les références dans le code et les requêtes, puis vérifiez pendant une période appropriée si des lectures ou des écritures concernent encore le champ que vous souhaitez supprimer.

Lorsque c’est possible, répétez la procédure dans un environnement représentatif, y compris les étapes de vérification. Cet essai permet de découvrir des dépendances et des opérations lentes, sans garantir que la charge ou la répartition des données en production sera identique. Veillez également à ce que la migration soit identifiable et à ce que l’équipe sache qui décide de poursuivre, de suspendre ou de revenir en arrière.

Retour arrière, correction en avant et limites

Il n’est pas toujours sûr de revenir sur une migration. Il est généralement plus facile de laisser en place une extension additive que de l’annuler, surtout si l’application a déjà écrit des données dans la nouvelle colonne. Supprimer ces données pour revenir à l’état précédent peut entraîner une perte d’informations. Un plan de retour arrière doit donc préciser ce qui sera annulé — le code, le schéma ou les deux — et quelles données seront conservées.

Si les nouvelles écritures ne peuvent pas être converties de manière fiable vers l’ancien schéma, il peut être plus prudent d’interrompre le déploiement et de préparer une correction en avant. Définissez à l’avance les critères de décision : par exemple, des erreurs touchant des opérations critiques, une dégradation persistante ou des données incohérentes. Ne promettez pas un retour arrière immédiat sans avoir vérifié qu’il est réalisable pour cette modification précise.

Liste de contrôle pour planifier la modification

Liste de contrôle pour planifier la modification
  • Tous les lecteurs, rédacteurs et processus qui utilisent le schéma concerné ont-ils été identifiés ?
  • La modification initiale est-elle compatible avec les versions qui resteront actives pendant le déploiement ?
  • L’extension, la transition du code et le retrait de l’ancien élément ont-ils été séparés ?
  • La source de vérité est-elle définie si deux représentations sont conservées temporairement ?
  • Les vérifications des données, des erreurs et des performances sont-elles définies, avec des responsables et des critères de suspension ?
  • Le plan précise-t-il ce qui peut être annulé et à quel moment une correction en avant sera nécessaire ?

Pour répondre à la question de savoir comment modifier le schéma d’une base de données sans interrompre le service, pensez en termes de compatibilité par étapes plutôt que de modification isolée. Ajoutez avant de supprimer, maintenez le fonctionnement des versions qui coexistent et validez chaque transition à l’aide de signaux observables. Si la modification ne peut pas être réalisée de manière additive, identifiez explicitement les risques et préparez une fenêtre de maintenance ou une stratégie de récupération adaptée ; ne supposez pas que toute modification permet un déploiement sans interruption.

Fuentes y referencias

  1. MDN Web DocsMozilla
  2. Web performanceweb.dev
  3. OWASP Cheat Sheet SeriesOWASP Foundation