Comment ne pas se tirer une balle dans le pied avec Liquibase

Cela n'est jamais arrivé auparavant, et c'est reparti !

Lors de notre prochain projet, nous avons décidé d'utiliser Liquibase dès le début pour éviter des problèmes à l'avenir. Il s’avère que tous les jeunes membres de l’équipe ne savent pas l’utiliser correctement. J'ai organisé un atelier interne, que j'ai ensuite décidé de transformer en article.

L'article comprend des conseils utiles et une description des trois pièges les plus évidents dans lesquels vous pouvez tomber lorsque vous travaillez avec des outils de migration de bases de données relationnelles, en particulier Liquibase. Conçu pour les développeurs Java de niveaux Junior et Middle, pour les développeurs plus expérimentés, il peut être intéressant pour structurer et répéter ce qui est probablement déjà connu.

Comment ne pas se tirer une balle dans le pied avec Liquibase

Liquibase et Flyway sont les principales technologies concurrentes pour résoudre les problèmes de contrôle de version des structures relationnelles dans le monde Java. Le premier est totalement gratuit, en pratique il est le plus souvent choisi pour son utilisation, c'est pourquoi Liquibase a été choisi comme héros de la publication. Toutefois, certaines des pratiques décrites peuvent être universelles, en fonction de l'architecture de votre application.

Les migrations de structures relationnelles sont une manière forcée de faire face à la faible flexibilité des magasins de données relationnelles. À l'ère de la mode POO, le style de travail avec les bases de données signifiait que nous devions décrire le schéma une seule fois et ne plus y toucher. Mais la réalité est toujours que les choses changent et que des modifications de la structure des tables sont souvent nécessaires. Naturellement, le processus lui-même peut être douloureux et désagréable.

Je n'entrerai pas plus profondément dans la description de la technologie et les instructions pour ajouter une bibliothèque à votre projet ; de nombreux articles ont été écrits sur ce sujet :

De plus, il y avait déjà un excellent article sur le thème des conseils utiles :

Conseils

Je souhaite partager mes conseils et mes commentaires, nés de la sueur, du sang et de la douleur liés à la résolution des problèmes liés à la migration.

1. Avant de commencer à travailler, vous devez vous familiariser avec la section des meilleures pratiques sur En ligne Liquibase

des choses simples mais très importantes sont décrites, sans lesquelles l'utilisation de la bibliothèque peut vous compliquer la vie. Par exemple, une approche non structurée de la gestion des ensembles de modifications entraînera tôt ou tard de la confusion et des migrations interrompues. Si vous ne déployez pas simultanément des modifications mutuellement dépendantes de la structure de la base de données et de la logique du service, il est fort probable que cela conduise à des tests rouges ou à un environnement défectueux. De plus, les recommandations d'utilisation de Liquibase sur le site officiel contiennent une clause sur le développement et les tests de scripts de restauration ainsi que les principaux scripts de migration. Eh bien, dans l'article https://habr.com/ru/post/178665/ Il existe des exemples de code concernant les migrations et le mécanisme de restauration.

2. Si vous commencez à utiliser des outils de migration, n'autorisez pas les corrections manuelles dans la structure de la base de données

Comme le dit le proverbe : « Persil un jour, Persil toujours ». Si la base de votre application commence à être gérée par Liquibase, toute modification manuelle conduit immédiatement à un état incohérent et le niveau de confiance dans les ensembles de modifications devient nul. Les risques potentiels incluent plusieurs heures passées à restaurer la base de données ; dans le pire des cas, un serveur mort. Si vous avez un architecte DBA « de la vieille école » dans votre équipe, expliquez-lui patiemment et de manière réfléchie à quel point les choses seraient mauvaises s'il éditait simplement la base de données selon sa propre compréhension d'un développeur SQL conditionnel.

3. Si l'ensemble de modifications a déjà été transféré dans le référentiel, évitez de le modifier

Si un autre développeur a effectué un pull et appliqué un ensemble de modifications, qui sera ensuite modifié, il se souviendra certainement de vous avec un mot gentil lorsqu'il recevra une erreur lors du démarrage de l'application. Si la modification de l'ensemble de modifications s'infiltre d'une manière ou d'une autre dans le développement, vous devrez suivre la pente glissante des correctifs. L'essence du problème repose sur la validation des modifications par somme de hachage - le mécanisme principal de Liquibase. Lors de la modification du code de l'ensemble de modifications, le montant de hachage change. La modification des ensembles de modifications n'est possible que lorsqu'il est possible de déployer l'intégralité de la base de données à partir de zéro sans perdre de données. Dans ce cas, refactoriser le code SQL ou XML peut au contraire faciliter la vie et rendre les migrations plus lisibles. Un exemple serait une situation où, au démarrage de l’application, le schéma de la base de données source a été convenu au sein de l’équipe.

4. Faites vérifier les sauvegardes de la base de données si possible

Ici, je pense, tout est clair. Si soudainement la migration échoue, tout peut être restitué. Liquibase dispose d'un outil pour annuler les modifications, mais les scripts d'annulation sont également écrits par le développeur lui-même, et ils peuvent rencontrer des problèmes avec la même probabilité que les scripts de l'ensemble de modifications principal. Cela signifie qu’il est utile de jouer la sécurité avec les sauvegardes dans tous les cas.

5. Utilisez si possible des sauvegardes de bases de données éprouvées lors du développement

Si cela n'est pas en contradiction avec les contrats et la confidentialité, il n'y a pas de données personnelles dans la base de données et cela ne pèse pas deux soleils - avant de l'utiliser sur des serveurs de migration en direct, vous pouvez vérifier comment cela fonctionnera sur la machine du développeur et calculer près de 100 % des problèmes potentiels lors de la migration.

6. Communiquer avec les autres développeurs de l'équipe

Dans un processus de développement bien organisé, tous les membres de l’équipe savent qui fait quoi. En réalité, ce n'est souvent pas le cas. Par conséquent, si vous préparez des modifications à la structure de la base de données dans le cadre de votre tâche, il est conseillé d'en informer également toute l'équipe. Si quelqu’un apporte des changements en parallèle, vous devez vous organiser avec soin. Cela vaut la peine de communiquer avec vos collègues une fois le travail terminé, et pas seulement au début. De nombreux problèmes potentiels liés aux ensembles de modifications peuvent être résolus au stade de la révision du code.

7. Pensez à ce que vous faites !

Cela semble être un conseil évident qui s’applique à n’importe quelle situation. Cependant, de nombreux problèmes auraient pu être évités si le développeur avait à nouveau analysé ce qu'il faisait et ce que cela pourrait affecter. Travailler avec des migrations nécessite toujours une attention et une précision supplémentaires.

Pièges

Examinons maintenant les pièges typiques dans lesquels vous pouvez tomber si vous ne suivez pas les conseils ci-dessus, et que devez-vous faire exactement ?

Situation 1 : deux développeurs tentent d'ajouter de nouveaux ensembles de modifications en même temps

Comment ne pas se tirer une balle dans le pied avec Liquibase
Vasya et Petya veulent créer une version 4 de l'ensemble de modifications, sans se connaître. Ils ont apporté des modifications à la structure de la base de données et émis une demande d'extraction avec différents fichiers d'ensemble de modifications. Le mécanisme d’action suivant est proposé :

Comment décider

  1. D'une manière ou d'une autre, les collègues doivent se mettre d'accord sur l'ordre dans lequel leurs modifications doivent être effectuées, par exemple, Petin doit être appliqué en premier.
  2. Quelqu'un devrait ajouter le deuxième à lui-même et marquer l'ensemble de modifications de Vasya avec la version 5. Cela peut être fait via Cherry Pick ou une fusion soignée.
  3. Après des modifications, vous devez impérativement vérifier la validité des actions entreprises.
    En fait, les mécanismes de Liquibase vous permettront d'avoir deux ensembles de modifications de la version 4 dans le référentiel, vous pourrez donc tout laisser tel quel. Autrement dit, vous aurez simplement deux modifications vers la version 4 avec des noms différents. Avec cette approche, il devient ensuite très difficile de naviguer dans les versions de la base de données.

De plus, Liquibase, comme la maison des hobbits, garde de nombreux secrets. L'une d'elles est la clé validCheckSum, apparue dans la version 1.7 et qui vous permet de spécifier une valeur de hachage valide pour un ensemble de modifications spécifique, quel que soit ce qui est stocké dans la base de données. Documentation https://www.liquibase.org/documentation/changeset.html dit ce qui suit :

Ajoutez une somme de contrôle considérée comme valide pour ce changeSet, quel que soit ce qui est stocké dans la base de données. Utilisé principalement lorsque vous devez modifier un changeSet et que vous ne souhaitez pas que des erreurs soient générées sur les bases de données sur lesquelles il a déjà été exécuté (ce n'est pas une procédure recommandée)

Oui, oui, cette procédure n'est pas recommandée. Mais parfois, un puissant magicien de la lumière maîtrise aussi les techniques sombres.

Situation 2 : Migration qui dépend des données

Comment ne pas se tirer une balle dans le pied avec Liquibase

Supposons que vous n'ayez pas la possibilité d'utiliser des sauvegardes de bases de données à partir de serveurs actifs. Petya a créé un ensemble de modifications, l'a testé localement et, en toute confiance qu'il avait raison, a fait une pull request au développeur. Juste au cas où, le responsable du projet a précisé si Petya l'avait vérifié, puis l'a ajouté. Mais le déploiement sur le serveur de développement a chuté.

En fait, cela est possible et personne n’est à l’abri. Cela se produit si les modifications apportées à la structure de la table sont liées d'une manière ou d'une autre à des données spécifiques de la base de données. Évidemment, si la base de données de Petya est remplie uniquement de données de test, elle risque de ne pas couvrir tous les cas problématiques. Par exemple, lors de la suppression d'une table, il s'avère qu'il existe des enregistrements dans d'autres tables par clé étrangère qui sont liés aux enregistrements de celle en cours de suppression. Ou lors du changement de type de colonne, il s'avère que 100 % des données ne peuvent pas être converties vers le nouveau type.

Comment décider

  • Écrivez des scripts spéciaux qui seront utilisés une fois avec la migration et mettez les données sous la forme appropriée. Il s'agit d'une manière générale de résoudre le problème du transfert de données vers de nouvelles structures après l'application des migrations, mais quelque chose de similaire peut être appliqué auparavant, dans des cas particuliers. Bien entendu, cette voie n'est pas toujours disponible, car l'édition de données sur des serveurs en direct peut être dangereuse, voire destructrice.
  • Une autre méthode difficile consiste à modifier un ensemble de modifications existant. La difficulté est que toutes les bases de données dans lesquelles il a déjà été appliqué sous sa forme existante devront être restaurées. Il est fort possible que toute l’équipe backend soit obligée de déployer localement la base de données à partir de zéro.
  • Et le moyen le plus universel consiste à transférer le problème avec les données vers l'environnement du développeur, en recréant la même situation et en ajoutant un nouvel ensemble de modifications, à celui qui est cassé, ce qui contournera le problème.
    Comment ne pas se tirer une balle dans le pied avec Liquibase

En général, plus la composition de la base de données est similaire à celle du serveur de production, moins les problèmes de migration risquent d'aller loin. Et, bien sûr, avant d'envoyer un ensemble de modifications au référentiel, vous devez réfléchir plusieurs fois si cela va casser quelque chose.

Situation 3. Liquibase commence à être utilisé après sa mise en production

Supposons que le chef d'équipe demande à Petya d'inclure Liquibase dans le projet, mais que le projet est déjà en production et qu'il existe une structure de base de données existante.

En conséquence, le problème est que sur tout nouveau serveur ou machine de développement, ces tables doivent être recréées à partir de zéro et l'environnement existant doit rester dans un état cohérent, prêt à accepter de nouveaux ensembles de modifications.

Comment décider

Il existe également plusieurs manières :

  • La première et la plus évidente consiste à disposer d’un script distinct qui doit être appliqué manuellement lors de l’initialisation d’un nouvel environnement.
  • La seconde est moins évidente, effectuer une migration Liquibase dans un autre contexte Liquibase et l'appliquer. Vous pouvez en savoir plus sur le contexte Liquibase ici : https://www.liquibase.org/documentation/contexts.html. En général, il s’agit d’un mécanisme intéressant qui peut être utilisé avec succès, par exemple pour des tests.
  • Le troisième chemin comprend plusieurs étapes. Tout d’abord, une migration doit être créée pour les tables existantes. Ensuite, il doit être appliqué à un environnement et ainsi sa somme de hachage sera obtenue. L'étape suivante consiste à initialiser les tables Liquibase vides sur notre serveur non vide, et dans la table avec l'historique d'utilisation des ensembles de modifications, vous pouvez mettre manuellement un enregistrement sur l'ensemble de modifications « comme si appliqué » avec les modifications déjà existantes dans la base de données. . Ainsi, sur un serveur existant, le compte à rebours de l'historique démarrera à partir de la version 2, et tous les nouveaux environnements se comporteront de manière identique.
    Comment ne pas se tirer une balle dans le pied avec Liquibase

Situation 4. Les migrations deviennent énormes et n'ont pas le temps de se terminer

En règle générale, au début du développement du service, Liquibase est utilisé comme dépendance externe et toutes les migrations sont traitées au démarrage de l'application. Cependant, au fil du temps, vous pouvez tomber sur les cas suivants :

  • Les migrations deviennent énormes et prennent beaucoup de temps.
  • Il existe un besoin de migration dans les environnements distribués, par exemple sur plusieurs instances de serveur de base de données simultanément.
    Dans ce cas, appliquer des migrations pendant trop longtemps entraînera un délai d'attente au démarrage de l'application. De plus, l'application de migrations à chaque instance d'application séparément peut entraîner une désynchronisation de différents serveurs.

Comment décider

Dans de tels cas, votre projet est déjà volumineux, peut-être même adulte, et Liquibase commence à agir comme un outil externe distinct. Le fait est que Liquibase, en tant que bibliothèque, est compilée dans un fichier jar et peut fonctionner comme une dépendance au sein d'un projet ou indépendamment.

En mode autonome, vous pouvez confier la mise en œuvre des migrations à votre environnement CI/CD ou aux solides épaules de vos administrateurs système et spécialistes du déploiement. Pour ce faire, vous aurez besoin de la ligne de commande Liquibase https://www.liquibase.org/documentation/command_line.html. Dans ce mode, il devient possible de lancer l'application après avoir effectué toutes les migrations nécessaires.

conclusion

En fait, il peut y avoir bien d’autres pièges lors de la migration de bases de données, et nombre d’entre eux nécessitent une approche créative. Il est important de comprendre que si vous utilisez correctement l’outil, la plupart de ces pièges peuvent être évités. Plus précisément, j'ai dû faire face à tous les problèmes répertoriés sous différentes formes, et certains d'entre eux étaient le résultat de mes erreurs. Cela se produit généralement, bien sûr, par inattention, mais parfois par incapacité criminelle à utiliser l'outil.

Source: habr.com

Ajouter un commentaire