Pourquoi vous ne pouvez pas simplement supprimer cette colonne de base de données
Votre équipe vient de finir de mettre à jour le code applicatif pour utiliser le nouveau schéma de base de données. L'ancienne colonne semble être du poids mort. Vous voulez faire le ménage. Alors vous la supprimez.
Quelques minutes plus tard, les erreurs commencent à inonder les logs. Les utilisateurs signalent qu'une fonctionnalité qu'ils utilisaient il y a cinq minutes renvoie désormais des pages blanches. Quelqu'un de l'équipe de nuit appelle parce que le traitement par lots qui s'exécute à minuit vient de planter. Vous passez les deux heures suivantes à comprendre ce qui a mal tourné.
Ce scénario se reproduit dans des équipes de toutes tailles. L'envie de supprimer immédiatement l'ancien schéma est compréhensible, mais dans un système de production, cela se retourne presque toujours contre vous. Voici pourquoi.
Les anciennes instances sont toujours en cours d'exécution
La raison la plus courante pour laquelle la suppression d'un schéma échoue est que toutes les instances de l'application n'ont pas encore été mises à jour. En production, les déploiements se font progressivement. Vous mettez à jour un serveur, puis le suivant, puis le suivant. Pendant cette fenêtre, certains serveurs exécutent encore l'ancien code.
Lorsqu'une ancienne instance tente de lire ou d'écrire dans une colonne qui n'existe plus, la base de données renvoie une erreur. Cette erreur devient une requête échouée. Cette requête échouée devient une plainte d'utilisateur. Le problème ne vient pas du nouveau code, mais du décalage temporel entre les étapes de déploiement.
Même si vous utilisez un déploiement blue-green ou des canary releases, le même principe s'applique : à tout moment du déploiement, plusieurs versions de votre application sont actives. Elles partagent toutes la même base de données. Si le schéma change avant que toutes les instances aient été mises à jour, quelque chose va casser.
La migration des données est rarement instantanée
Le deuxième problème concerne les données. Les anciennes colonnes et tables contiennent souvent encore des données qui n'ont pas été déplacées vers la nouvelle structure. Peut-être que le script de migration a fonctionné en staging, mais qu'en production le jeu de données est dix fois plus volumineux. Peut-être qu'il y a des relations de clés étrangères qui nécessitent une vérification manuelle. Peut-être que la migration elle-même prend des heures et ne peut pas être terminée en une seule fenêtre de maintenance.
Si vous supprimez le schéma avant que toutes les données ne soient migrées, ces données sont perdues. Les récupérer implique une restauration à partir d'une sauvegarde, ce qui entraîne des temps d'arrêt et risque de perdre toutes les données écrites après la sauvegarde. Pour les tables avec un volume d'écriture élevé, cet écart peut être significatif.
Certaines équipes supposent qu'elles peuvent migrer les données dans une étape séparée avant de supprimer le schéma. Cela fonctionne en théorie, mais en pratique, des cas particuliers font toujours surface. Un travail planifié dont personne ne se souvenait, une requête de reporting qui s'exécute une fois par mois, une intégration héritée qui ne se déclenche que sous certaines conditions. Ces consommateurs cachés de l'ancien schéma ne se révèlent qu'après la suppression de la colonne.
Les dépendances cachées sont partout
Cela nous amène au problème le plus difficile : les dépendances inconnues. Tous les consommateurs de votre schéma de base de données ne sont pas documentés. Et tous les consommateurs ne sont même pas des applications que vous contrôlez.
Considérez ces scénarios :
- Un traitement par lots écrit par une autre équipe s'exécute chaque nuit et lit dans la table que vous êtes sur le point de supprimer.
- Un outil de reporting interroge l'ancienne colonne pour un tableau de bord que personne ne maintient plus.
- Un script de surveillance vérifie une table spécifique pour s'assurer de la fraîcheur des données.
- Une intégration tierce envoie des données à un point de terminaison qui écrit dans l'ancien schéma.
Aucun de ces éléments n'est visible dans votre code applicatif. Aucun n'apparaîtra dans un grep de votre dépôt. Ils ne deviennent visibles que lorsqu'ils cassent.
Le pire, c'est que certains de ces échecs sont silencieux. Une requête qui fait référence à une colonne supprimée peut ne pas planter immédiatement. Elle peut renvoyer des valeurs NULL ou des ensembles de résultats vides, et le système consommateur peut interpréter cela comme des données valides. Vous vous retrouvez avec des rapports corrompus, des tableaux de bord incorrects ou des pipelines de données qui produisent silencieusement des résultats erronés. Au moment où quelqu'un s'en aperçoit, la cause racine est enterrée sous des couches de traitement en aval.
Les modifications irréversibles amplifient le risque
Le problème fondamental avec la suppression directe d'un schéma est qu'elle est irréversible. Une fois qu'une colonne ou une table a disparu, la seule façon de la récupérer est une restauration complète de la base de données. Cela signifie des temps d'arrêt. Cela signifie une perte potentielle de données. Cela signifie que votre équipe est sous pression pour réparer quelque chose rapidement, ce qui est exactement le moment où les erreurs se produisent.
Comparez cela à l'ajout d'une nouvelle colonne. Ajouter est réversible : si quelque chose ne va pas, vous pouvez supprimer la colonne que vous venez d'ajouter. Supprimer ne l'est pas. Une fois que vous vous engagez dans la suppression, vous vous êtes engagé dans une voie sans retour en arrière facile.
Cette asymétrie explique pourquoi les équipes expérimentées traitent la suppression de schéma comme un processus en plusieurs étapes, et non comme une action unique. Elles ne suppriment l'ancien schéma que lorsqu'elles sont certaines que tous les consommateurs ont migré. Et elles construisent cette certitude par l'observation, pas par la supposition.
L'approche plus sûre : étendre puis contracter
Au lieu de supprimer l'ancien schéma en espérant que rien ne casse, il existe un meilleur modèle. Il comporte deux phases.
Le diagramme ci-dessous compare les deux chemins.
D'abord, étendre : ajoutez la nouvelle colonne ou table tout en conservant l'ancienne. Les deux structures existent simultanément. Le code applicatif est mis à jour pour écrire dans les deux, ou pour lire depuis la nouvelle tout en utilisant l'ancienne comme fallback si nécessaire. Pendant cette phase, vous surveillez les erreurs, vérifiez que les données sont écrites correctement et confirmez que tous les consommateurs utilisent la nouvelle structure.
Ensuite, contracter : une fois que vous avez la preuve que rien ne dépend plus de l'ancien schéma, supprimez-le. Ce n'est pas une supposition. Vous avez des logs, des métriques et une analyse des requêtes montrant que l'ancienne colonne n'a pas été accédée pendant une période raisonnable. Alors seulement, vous la supprimez.
Ce modèle s'appelle expand-contract, et c'est l'approche standard pour effectuer des modifications de schéma non rétrocompatibles en toute sécurité. Cela prend plus de temps, mais cela évite le genre d'incidents de production qui transforment un simple nettoyage en une session de débogage impliquant toute l'équipe.
L'extrait SQL suivant oppose la suppression immédiate risquée au processus plus sûr en plusieurs étapes.
-- NON SÉCURISÉ : suppression immédiate de la colonne
ALTER TABLE users DROP COLUMN old_plan;
-- PLUS SÉCURISÉ : approche expand-contract
-- Étape 1 : Ajouter la nouvelle colonne
ALTER TABLE users ADD COLUMN new_plan VARCHAR(50);
-- Étape 2 : Remplir les données de l'ancienne vers la nouvelle colonne
UPDATE users SET new_plan = old_plan WHERE new_plan IS NULL;
-- Étape 3 : Mettre à jour l'application pour écrire dans les deux colonnes
-- (géré dans le code, pas en SQL)
-- Étape 4 : Après avoir confirmé qu'aucune lecture n'est faite sur l'ancienne colonne, la supprimer
ALTER TABLE users DROP COLUMN old_plan;
Liste de contrôle pratique avant de supprimer un schéma
Avant de supprimer une colonne ou une table, vérifiez ces conditions :
- Toutes les instances de l'application exécutent le nouveau code depuis au moins un cycle de déploiement complet.
- Aucune requête n'a référencé l'ancien schéma en production depuis au moins une semaine.
- Tous les traitements par lots, rapports et intégrations qui pourraient utiliser l'ancien schéma ont été mis à jour ou désactivés.
- La migration des données est terminée et vérifiée, y compris les enregistrements historiques.
- Un plan de rollback existe et ne nécessite pas une restauration complète de la base de données.
Si l'une de ces conditions n'est pas remplie, vous n'êtes pas prêt à supprimer.
Ce qu'il faut retenir
Supprimer une colonne de base de données n'est pas une tâche de nettoyage. C'est un changement de production aux conséquences irréversibles. La façon sécurisée de le faire est de garder l'ancien schéma en vie jusqu'à ce que vous ayez la preuve que personne n'en a plus besoin. Cette preuve prend du temps à rassembler, mais c'est le seul moyen d'éviter l'appel tardif concernant une fonctionnalité cassée qui fonctionnait parfaitement avant.