Zo voorkom je dat je jezelf in de voet schiet met Liquibase

Nog nooit eerder gebeurd, en daar gaan we weer!

Bij ons volgende project besloten we vanaf het begin Liquibase te gebruiken om problemen in de toekomst te voorkomen. Het blijkt dat niet alle jonge teamleden weten hoe ze het correct moeten gebruiken. Ik hield een interne workshop, die ik vervolgens besloot om te zetten in een artikel.

Het artikel bevat nuttige tips en een beschrijving van de drie meest voor de hand liggende valkuilen waar u in kunt trappen als u werkt met relationele databasemigratietools, in het bijzonder Liquibase. Ontworpen voor Java-ontwikkelaars op Junior- en Midden-niveau; voor meer ervaren ontwikkelaars kan het interessant zijn voor het structureren en herhalen van wat waarschijnlijk al bekend is.

Zo voorkom je dat je jezelf in de voet schiet met Liquibase

Liquibase en Flyway zijn de belangrijkste concurrerende technologieën voor het oplossen van versiebeheerproblemen van relationele structuren in de Java-wereld. De eerste is volledig gratis, in de praktijk wordt deze meestal gekozen voor gebruik, daarom werd Liquibase gekozen als de held van de publicatie. Sommige van de beschreven praktijken kunnen echter universeel zijn, afhankelijk van uw applicatiearchitectuur.

Migraties van relationele structuren zijn een geforceerde manier om met de zwakke flexibiliteit van relationele gegevensopslag om te gaan. In het tijdperk van de OOP-mode betekende de stijl van het werken met databases dat we het schema één keer zouden beschrijven en er niet meer aan zouden raken. Maar de realiteit is altijd dat dingen veranderen, en dat veranderingen in de tabelstructuur vrij vaak nodig zijn. Uiteraard kan het proces zelf pijnlijk en onaangenaam zijn.

Ik zal niet dieper ingaan op de beschrijving van de technologie en instructies voor het toevoegen van een bibliotheek aan je project; er zijn nogal wat artikelen over dit onderwerp geschreven:

Daarnaast was er al een uitstekend artikel over het onderwerp nuttige tips:

Советы

Ik wil mijn advies en opmerkingen delen, die zijn ontstaan ​​door het zweet, het bloed en de pijn bij het oplossen van migratieproblemen.

1. Voordat u met uw werk begint, moet u zich vertrouwd maken met het gedeelte over best practices Online Liquibasis

Там Er worden eenvoudige maar zeer belangrijke dingen beschreven, zonder welke het gebruik van de bibliotheek uw leven kan bemoeilijken. Een ongestructureerde aanpak voor het beheren van wijzigingensets zal bijvoorbeeld vroeg of laat leiden tot verwarring en mislukte migraties. Als je onderling afhankelijke wijzigingen in de databasestructuur en servicelogica niet tegelijkertijd doorvoert, is de kans groot dat dit tot rode tests of een kapotte omgeving leidt. Bovendien bevatten de aanbevelingen voor het gebruik van Liquibase op de officiële website een clausule over het ontwikkelen en testen van rollback-scripts, samen met de belangrijkste migratiescripts. Nou ja, in het artikel https://habr.com/ru/post/178665/ Er zijn codevoorbeelden met betrekking tot migraties en het terugdraaimechanisme.

2. Als u migratietools gaat gebruiken, sta dan geen handmatige correcties in de databasestructuur toe

Zoals het gezegde luidt: “Eens Persil, altijd Persil.” Als de basis van uw applicatie door Liquibase wordt beheerd, leiden eventuele handmatige wijzigingen onmiddellijk tot een inconsistente toestand en wordt het vertrouwen in wijzigingensets nul. Potentiële risico's zijn onder meer het urenlang herstellen van de database; in het ergste geval een dode server. Als je een ‘old school’ DBA-architect in je team hebt, leg hem dan geduldig en bedachtzaam uit hoe erg de situatie zal zijn als hij de database eenvoudigweg bewerkt volgens zijn eigen inzichten van een voorwaardelijke SQL-ontwikkelaar.

3. Als de wijzigingenset al naar de repository is gepusht, vermijd dan bewerken

Als een andere ontwikkelaar een pull heeft gemaakt en een wijzigingenset heeft toegepast, die later zal worden bewerkt, zal hij u zeker met een vriendelijk woord herinneren wanneer hij een foutmelding krijgt bij het starten van de applicatie. Als het bewerken van de wijzigingenset op de een of andere manier in de ontwikkeling terechtkomt, zul je het hellende vlak van hotfixes moeten volgen. De essentie van het probleem berust op de validatie van wijzigingen door hash sum - het belangrijkste mechanisme van Liquibase. Bij het bewerken van de wijzigingssetcode verandert de hashhoeveelheid. Het bewerken van wijzigingensets is alleen mogelijk als het mogelijk is om de hele database helemaal opnieuw te implementeren zonder gegevens te verliezen. In dit geval kan het refactoren van de SQL- of XML-code het leven juist gemakkelijker maken en migraties leesbaarder maken. Een voorbeeld hiervan is een situatie waarin bij de start van de applicatie binnen het team overeenstemming was bereikt over het schema van de brondatabase.

4. Zorg indien mogelijk voor geverifieerde databaseback-ups

Hier is, denk ik, alles duidelijk. Als de migratie plotseling niet lukt, kan alles worden teruggezet. Liquibase heeft een tool om wijzigingen terug te draaien, maar de terugdraaiscripts zijn ook door de ontwikkelaar zelf geschreven en kunnen met dezelfde waarschijnlijkheid problemen opleveren als de scripts van de hoofdwijzigingsset. Dit betekent dat het in ieder geval handig is om op veilig te spelen met back-ups.

5. Gebruik indien mogelijk beproefde databaseback-ups tijdens de ontwikkeling

Als dit niet in tegenspraak is met contracten en privacy, staan ​​er geen persoonlijke gegevens in de database en weegt deze niet zoveel als twee zonnen - voordat u deze op livemigratieservers gebruikt, kunt u controleren hoe het zal werken op de machine van de ontwikkelaar en berekenen bijna 100% van de potentiële problemen tijdens de migratie.

6. Communiceer met andere ontwikkelaars in het team

In een goed georganiseerd ontwikkelproces weet iedereen in het team wie wat doet. In werkelijkheid is dit vaak niet het geval. Als u in het kader van uw taak wijzigingen aan de databasestructuur voorbereidt, is het raadzaam om het hele team hiervan bovendien op de hoogte te stellen. Als iemand tegelijkertijd wijzigingen aanbrengt, moet u dit zorgvuldig organiseren. Het is de moeite waard om met collega's te communiceren nadat het werk is afgerond, en niet alleen aan het begin. Veel potentiële problemen met wijzigingensets kunnen worden opgelost in de codebeoordelingsfase.

7. Denk na over wat je doet!

Het lijkt een vanzelfsprekend advies dat voor elke situatie geldt. Veel problemen hadden echter voorkomen kunnen worden als de ontwikkelaar opnieuw had geanalyseerd wat hij aan het doen was en welke gevolgen dit zou kunnen hebben. Het werken met migraties vergt altijd extra aandacht en nauwkeurigheid.

traps

Laten we nu eens kijken naar de typische valkuilen waarin u kunt trappen als u het bovenstaande advies niet opvolgt, en wat moet u precies doen?

Situatie 1: Twee ontwikkelaars proberen tegelijkertijd nieuwe wijzigingensets toe te voegen

Zo voorkom je dat je jezelf in de voet schiet met Liquibase
Vasya en Petya willen een wijzigingenset versie 4 maken, zonder dat ze het van elkaar weten. Ze brachten wijzigingen aan in de databasestructuur en gaven een pull-verzoek uit met verschillende wijzigingensetbestanden. Het volgende werkingsmechanisme wordt voorgesteld:

Hoe te beslissen

  1. Op de een of andere manier moeten collega's het eens worden over de volgorde waarin hun wijzigingensets moeten komen, bijvoorbeeld Petin moet eerst worden toegepast.
  2. Iemand zou de tweede aan zichzelf moeten toevoegen en Vasi's wijzigingenset met versie 5 moeten markeren. Dit kan gedaan worden via Cherry Pick of een nette samenvoeging.
  3. Na wijzigingen moet u zeker de geldigheid van de ondernomen acties controleren.
    In feite zorgen de Liquibase-mechanismen ervoor dat je twee versie 4-wijzigingensets in de repository hebt, zodat je alles kunt laten zoals het is. Dat wil zeggen dat u eenvoudigweg twee wijzigingen in versie 4 met verschillende namen zult hebben. Met deze aanpak wordt het later erg moeilijk om door de databaseversies te navigeren.

Bovendien bewaart Liquibase, net als het huis van de hobbits, veel geheimen. Eén daarvan is de validCheckSum-sleutel, die verscheen in versie 1.7 en waarmee u een geldige hash-waarde kunt opgeven voor een specifieke wijzigingenset, ongeacht wat er in de database is opgeslagen. Documentatie https://www.liquibase.org/documentation/changeset.html zegt het volgende:

Voeg een controlesom toe die als geldig wordt beschouwd voor deze changeSet, ongeacht wat er in de database is opgeslagen. Wordt voornamelijk gebruikt wanneer u een changeSet moet wijzigen en niet wilt dat er fouten worden gegenereerd in databases waarop deze al is uitgevoerd (geen aanbevolen procedure)

Ja, ja, deze procedure wordt niet aanbevolen. Maar soms beheerst een sterke lichtgoochelaar ook donkere technieken

Situatie 2: Migratie die afhankelijk is van data

Zo voorkom je dat je jezelf in de voet schiet met Liquibase

Laten we aannemen dat u niet de mogelijkheid heeft om databaseback-ups van live servers te gebruiken. Petya heeft een wijzigingenset gemaakt, deze lokaal getest en, met het volste vertrouwen dat hij gelijk had, een pull-verzoek ingediend bij de ontwikkelaar. Voor de zekerheid verduidelijkte de projectleider of Petya het had gecontroleerd, en voegde het vervolgens toe. Maar de implementatie op de ontwikkelingsserver viel terug.

In feite is dit mogelijk, en niemand is hier immuun voor. Dit gebeurt als wijzigingen in de tabelstructuur op de een of andere manier verband houden met specifieke gegevens uit de database. Het is duidelijk dat als de database van Petya alleen gevuld is met testgegevens, deze mogelijk niet alle probleemgevallen dekt. Wanneer u bijvoorbeeld een tabel verwijdert, blijkt dat er records in andere tabellen van Foreign Key zijn die gerelateerd zijn aan records in de tabel die wordt verwijderd. Of bij het wijzigen van een kolomtype blijkt dat niet 100% van de data naar het nieuwe type geconverteerd kan worden.

Hoe te beslissen

  • Schrijf speciale scripts die eenmalig gebruikt worden bij de migratie en breng de data in de juiste vorm. Dit is een algemene manier om het probleem van het overbrengen van gegevens naar nieuwe structuren na het toepassen van migraties op te lossen, maar in speciale gevallen kan eerder iets soortgelijks worden toegepast. Dit pad is uiteraard niet altijd beschikbaar, omdat het bewerken van gegevens op live servers gevaarlijk en zelfs destructief kan zijn.
  • Een andere moeilijke manier is het bewerken van een bestaande wijzigingenset. De moeilijkheid is dat alle databases waar het al in zijn bestaande vorm is toegepast, zullen moeten worden hersteld. Het is goed mogelijk dat het hele backend-team gedwongen wordt om de database vanaf nul lokaal uit te rollen.
  • En de meest universele manier is om het probleem met de gegevens over te dragen naar de omgeving van de ontwikkelaar, waarbij dezelfde situatie opnieuw wordt gecreëerd en een nieuwe wijzigingenset wordt toegevoegd aan de kapotte, waardoor het probleem wordt omzeild.
    Zo voorkom je dat je jezelf in de voet schiet met Liquibase

Over het algemeen geldt dat hoe meer de database qua samenstelling vergelijkbaar is met de database van de productieserver, hoe kleiner de kans dat problemen met migraties groot zullen zijn. En voordat u een wijzigingenset naar de repository verzendt, moet u natuurlijk meerdere keren nadenken of er iets kapot gaat.

Situatie 3. Liquibase wordt gebruikt nadat het in productie is gegaan

Stel dat de teamleider Petya heeft gevraagd om Liquibase in het project op te nemen, maar het project is al in productie en er is een bestaande databasestructuur.

Het probleem is dus dat op nieuwe servers of ontwikkelaarsmachines deze tabellen helemaal opnieuw moeten worden gemaakt, en dat de bestaande omgeving in een consistente staat moet blijven, klaar om nieuwe wijzigingen te accepteren.

Hoe te beslissen

Er zijn ook verschillende manieren:

  • De eerste en meest voor de hand liggende is om een ​​apart script te hebben dat handmatig moet worden toegepast bij het initialiseren van een nieuwe omgeving.
  • De tweede ligt minder voor de hand: voer een Liquibase-migratie uit die zich in een andere Liquibase-context bevindt en pas deze toe. U kunt hier meer lezen over Liquibase Context: https://www.liquibase.org/documentation/contexts.html. Over het algemeen is dit een interessant mechanisme dat bijvoorbeeld met succes kan worden gebruikt voor testen.
  • Het derde pad bestaat uit verschillende stappen. Eerst moet er een migratie worden gemaakt voor bestaande tabellen. Vervolgens moet het op een bepaalde omgeving worden toegepast en zo wordt de hashsom ervan verkregen. De volgende stap is het initialiseren van lege Liquibase-tabellen op onze niet-lege server, en in de tabel met de geschiedenis van het gebruik van wijzigingensets kunt u handmatig een record plaatsen over de “alsof toegepast” wijzigingenset met wijzigingen die al in de database bestaan. . Op een bestaande server begint het aftellen van de geschiedenis dus vanaf versie 2 en zullen alle nieuwe omgevingen zich identiek gedragen.
    Zo voorkom je dat je jezelf in de voet schiet met Liquibase

Situatie 4. Migraties worden enorm en hebben geen tijd om ze te voltooien

Aan het begin van de serviceontwikkeling wordt Liquibase in de regel gebruikt als een externe afhankelijkheid en worden alle migraties verwerkt wanneer de applicatie start. Na verloop van tijd kunt u echter de volgende gevallen tegenkomen:

  • Migraties worden enorm en duren lang.
  • Er is behoefte aan migratie in gedistribueerde omgevingen, bijvoorbeeld op meerdere databaseserverinstanties tegelijk.
    In dit geval zal het te lang toepassen van migraties resulteren in een time-out wanneer de applicatie start. Bovendien kan het afzonderlijk toepassen van migraties op elk applicatie-exemplaar ertoe leiden dat verschillende servers niet gesynchroniseerd zijn.

Hoe te beslissen

In dergelijke gevallen is uw project al groot, misschien zelfs een volwassen project, en begint Liquibase als een afzonderlijk extern hulpmiddel te fungeren. Feit is dat Liquibase als bibliotheek is gecompileerd in een jar-bestand en als afhankelijkheid binnen een project of zelfstandig kan werken.

In de standalone modus kunt u de uitvoering van migraties overlaten aan uw CI/CD-omgeving of aan de sterke schouders van uw systeembeheerders en implementatiespecialisten. Hiervoor heeft u de Liquibase-opdrachtregel nodig https://www.liquibase.org/documentation/command_line.html. In deze modus wordt het mogelijk om de applicatie te starten nadat alle noodzakelijke migraties zijn uitgevoerd.

Uitgang

In feite kunnen er nog veel meer valkuilen zijn bij het werken met databasemigraties, en veel daarvan vereisen een creatieve aanpak. Het is belangrijk om te begrijpen dat als u de tool correct gebruikt, de meeste van deze valkuilen kunnen worden vermeden. Concreet kreeg ik te maken met alle genoemde problemen in verschillende vormen, en sommige daarvan waren het gevolg van mijn fouten. Meestal gebeurt dit natuurlijk door onoplettendheid, maar soms ook door het onvermogen van de crimineel om de tool te gebruiken.

Bron: www.habr.com

Voeg een reactie