Quand une migration de données tourne mal : stratégies de rollback qui fonctionnent vraiment

Vous venez de déployer une migration de base de données en production. Le script a tourné pendant douze minutes, modifié trois tables, déplacé des données entre colonnes, puis a échoué sur la dernière instruction. La moitié des changements sont appliqués. L'autre moitié ne l'est pas. Votre application renvoie maintenant des erreurs car elle attend un schéma qui n'existe pas complètement.

C'est à ce moment que la plupart des équipes découvrent que revenir en arrière sur une migration de données n'a rien à voir avec un rollback de déploiement applicatif. Pour le code applicatif, on échange le binaire ou l'image conteneur, et l'ancienne version s'exécute à nouveau. Avec les données, on ne peut pas annuler la suppression d'une colonne en redéployant l'ancien code. La colonne a disparu. Les données qui s'y trouvaient aussi.

Une stratégie de rollback pour une migration de données doit exister avant le début de la migration. La planifier après l'échec est trop tard.

Sauvegarde avant migration, pas après

Le mécanisme de rollback le plus fiable est un instantané complet de la base de données pris immédiatement avant le début de la migration. Ce n'est pas votre sauvegarde nocturne. C'est une copie ponctuelle qui capture l'état exact des données juste avant le changement.

Cette sauvegarde doit être automatisée dans le pipeline. Avant que l'étape de migration ne s'exécute, le pipeline déclenche un dump de base de données, un snapshot, ou un arrêt de réplication qui crée un point de restauration. Si l'étape de sauvegarde échoue, le pipeline s'arrête. La migration ne s'exécute pas. Cela élimine l'erreur humaine d'oublier de faire une sauvegarde manuelle avant de lancer le déploiement.

Le diagramme suivant illustre le chemin de décision après un échec de migration, pour vous aider à choisir la méthode de rollback adaptée à la situation.

flowchart TD A[Sauvegarde pré-migration créée] --> B[Migration exécutée] B --> C{Migration réussie ?} C -->|Oui| D[Terminé] C -->|Non| E{Choisir méthode de rollback} E -->|Changement destructeur ou perte de données| F[Restauration à un point dans le temps] E -->|Changement de schéma réversible| G[Rollback de version - migration descendante] E -->|Snapshot complet disponible| H[Restaurer le snapshot pré-migration] F --> I[Analyser la cause racine] G --> I H --> I I --> J[Corriger le script de migration] J --> B

Pour les bases de données cloud, cela signifie souvent prendre un snapshot du volume ou créer un clone de l'instance. Pour les bases de données auto-hébergées, cela signifie exécuter une commande de dump ou utiliser des snapshots du système de fichiers. L'important est que la sauvegarde soit vérifiable. Un fichier de sauvegarde qui ne peut pas être restauré n'est pas une sauvegarde.

Le rollback de version de migration a ses limites

La plupart des frameworks de migration supportent les versions avant et arrière. Flyway les appelle migrate et undo. Liquibase les appelle update et rollback. Alembic les appelle upgrade et downgrade. Ces outils peuvent inverser les changements de schéma en exécutant un script de migration descendante.

Le problème est que les migrations descendantes ne fonctionnent de manière sûre que pour les changements réversibles. Ajouter une colonne nullable est réversible : la migration descendante supprime la colonne, et aucune donnée n'est perdue. Renommer une colonne est réversible si la migration descendante la renomme à l'identique. Mais les changements destructeurs sont une autre histoire. Si vous supprimez une colonne, la migration descendante peut la recréer, mais les données qui s'y trouvaient sont perdues. Si vous transformez des données d'un format à un autre, la migration descendante ne peut inverser la transformation que si vous avez stocké les valeurs originales quelque part.

Le rollback de version est utile pour rattraper les erreurs tôt, comme une migration déployée dans le mauvais environnement ou un changement de schéma qui casse une requête. Mais ce n'est pas un filet de sécurité contre la perte de données. Se fier uniquement aux migrations descendantes est une erreur courante qui entraîne une perte de données lors du rollback.

La restauration à un point dans le temps comme filet de sécurité

La stratégie de rollback la plus robuste ne dépend pas du tout des scripts de migration. La restauration à un point dans le temps utilise le journal de transactions de la base de données pour restaurer la base à n'importe quel moment avant le début de la migration.

Voici comment cela fonctionne. La base de données écrit en continu des journaux de transactions ou des journaux d'écriture anticipée qui enregistrent chaque modification. Si vous disposez de ces journaux et d'une sauvegarde de base, vous pouvez rejouer les journaux jusqu'à un timestamp spécifique. Lorsqu'une migration échoue à 14h00, vous restaurez la base de données à 13h59, avant que la migration ne commence. Toutes les modifications apportées par la migration disparaissent, et la base de données retrouve son état d'origine, quelle que soit la destructivité de la migration.

La restauration à un point dans le temps nécessite une préparation. La base de données doit être configurée pour archiver les journaux de transactions en continu. L'équipe doit disposer des outils et des permissions pour effectuer une restauration à un moment précis. Et le processus doit être testé régulièrement. De nombreuses équipes découvrent que leur configuration de restauration à un point dans le temps est cassée seulement lorsqu'elles en ont besoin lors d'un incident.

Cette approche fonctionne pour toute migration, y compris les migrations destructrices. Elle ne se soucie pas de savoir si la migration a ajouté des colonnes, supprimé des tables ou transformé des millions de lignes. Elle remonte simplement le temps.

Testez le rollback, pas seulement la migration

Une migration qui réussit tous les tests en staging peut encore échouer en production en raison d'un volume de données inattendu, de conflits de verrouillage ou de cas particuliers dans les données. Il en va de même pour le rollback. La seule façon de savoir qu'un rollback fonctionne est de le tester.

Dans votre environnement de staging, exécutez la migration. Ensuite, tentez de revenir en arrière en utilisant chacune de vos stratégies : la migration descendante, la sauvegarde pré-migration et la restauration à un point dans le temps. Mesurez le temps que prend chaque méthode. Si la restauration à un point dans le temps prend quatre heures, c'est une information importante à avoir avant un incident en production.

Si le rollback échoue ou prend trop de temps, corrigez le processus avant d'en avoir besoin. Ce test devrait faire partie de votre pipeline. Un job planifié peut exécuter un cycle de migration et de rollback en staging chaque semaine pour vérifier que les mécanismes de récupération fonctionnent toujours après des changements d'infrastructure.

Après un rollback, enquêtez avant de réessayer

Lorsqu'un rollback réussit, la réaction naturelle est de corriger le script de migration et de l'exécuter à nouveau. Résistez à cette impulsion. L'échec a peut-être révélé un problème plus profond : une incohérence de données que la migration n'a pas prise en compte, une condition de concurrence avec un autre processus, ou une mauvaise compréhension du schéma.

Enquêtez d'abord sur la cause racine. Vérifiez les journaux de migration. Examinez les données qui ont causé l'échec. Vérifiez si la migration supposait une forme de données qui n'existe pas en production. Ce n'est qu'après avoir compris pourquoi elle a échoué que vous devez modifier le script et réessayer.

Liste de contrôle pratique pour le rollback de migration

  • Automatisez une étape de sauvegarde pré-migration dans le pipeline. Si la sauvegarde échoue, le pipeline échoue.
  • Écrivez des migrations descendantes uniquement pour les changements de schéma réversibles. Ne vous fiez pas à elles pour les opérations destructrices.
  • Configurez la restauration à un point dans le temps pour votre base de données et testez-la au moins une fois par trimestre.
  • Testez le rollback en staging avant chaque migration en production, pas seulement lors de la configuration initiale.
  • Documentez la procédure de rollback et le temps de restauration estimé pour chaque environnement.
  • Après un rollback, enquêtez sur la cause racine avant de réessayer la migration.

L'essentiel à retenir

Un rollback de migration de données n'est pas un script que vous exécutez. C'est un système que vous construisez avant le début de la migration. La sauvegarde pré-migration est votre première ligne de défense. La restauration à un point dans le temps est votre dernier recours. Les migrations descendantes ne sont utiles que dans les cas restreints où les changements sont réversibles. Testez-les toutes en staging, documentez la procédure, et ne supposez jamais qu'un rollback fonctionnera avant d'avoir prouvé le contraire.