Slik unngår du å skyte deg selv i foten med Liquibase

Aldri skjedd før, og her er vi i gang igjen!

På vårt neste prosjekt bestemte vi oss for å bruke Liquibase helt fra begynnelsen for å unngå problemer i fremtiden. Det viser seg at ikke alle unge teammedlemmer vet hvordan de skal bruke det riktig. Jeg holdt en intern workshop, som jeg så bestemte meg for å gjøre om til en artikkel.

Artikkelen inneholder nyttige tips og en beskrivelse av de tre mest åpenbare fallgruvene du kan falle i når du arbeider med relasjonsdatabasemigreringsverktøy, spesielt Liquibase. Designet for Java-utviklere på junior- og mellomnivå; for mer erfarne utviklere kan det være av interesse for å strukturere og gjenta det som mest sannsynlig allerede er kjent.

Slik unngår du å skyte deg selv i foten med Liquibase

Liquibase og Flyway er de viktigste konkurrerende teknologiene for å løse versjonskontrollproblemer av relasjonsstrukturer i Java-verdenen. Den første er helt gratis, i praksis blir den oftest valgt for bruk, og derfor ble Liquibase valgt som helten i publikasjonen. Noen av de beskrevne fremgangsmåtene kan imidlertid være universelle, avhengig av applikasjonsarkitekturen.

Migreringer av relasjonsstrukturer er en tvungen måte å håndtere den svake fleksibiliteten til relasjonsdatalagre. I tiden med OOP-mote betydde stilen med å jobbe med databaser at vi ville beskrive skjemaet en gang og ikke røre det igjen. Men realiteten er alltid at ting endrer seg, og endringer i tabellstrukturen kreves ganske ofte. Naturligvis kan selve prosessen være smertefull og ubehagelig.

Jeg vil ikke gå dypere inn på beskrivelsen av teknologien og instruksjonene for å legge til et bibliotek i prosjektet ditt; det er skrevet ganske mange artikler om dette emnet:

I tillegg var det allerede en utmerket artikkel om emnet nyttige tips:

Советы

Jeg vil dele mine råd og kommentarer, som ble født gjennom svette, blod og smerte ved å løse problemer med migrasjon.

1. Før du starter arbeidet, bør du gjøre deg kjent med avsnittet om beste praksis om nettsted Liquibase

der enkle, men svært viktige ting er beskrevet, uten hvilke bruk av biblioteket kan komplisere livet ditt. For eksempel vil en ustrukturert tilnærming til å administrere endringssett før eller siden føre til forvirring og ødelagte migrasjoner. Hvis du ikke ruller ut gjensidig avhengige endringer i databasestrukturen og tjenestelogikken samtidig, er det stor sannsynlighet for at dette vil føre til røde tester eller et ødelagt miljø. I tillegg inneholder anbefalinger for bruk av Liquibase på den offisielle nettsiden en klausul om utvikling og testing av tilbakerullingsskript sammen med de viktigste migreringsskriptene. Vel, i artikkelen https://habr.com/ru/post/178665/ Det er kodeeksempler angående migreringer og tilbakeføringsmekanismen.

2. Hvis du begynner å bruke migreringsverktøy, ikke tillat manuelle korrigeringer i databasestrukturen

Som ordtaket sier: "En gang Persil, alltid Persil." Hvis basen til applikasjonen din begynner å bli administrert av Liquibase, fører eventuelle manuelle endringer umiddelbart til en inkonsekvent tilstand, og tillitsnivået til endringssett blir null. Potensielle risikoer inkluderer flere timer brukt på å gjenopprette databasen; i verste fall en død server. Hvis du har en "old school" DBA-arkitekt på laget ditt, forklar ham tålmodig og omtenksomt hvor ille ting vil være hvis han ganske enkelt redigerer databasen i henhold til sin egen forståelse fra en betinget SQL-utvikler.

3. Hvis endringssettet allerede er presset inn i depotet, unngå redigering

Hvis en annen utvikler gjorde et trekk og brukte et endringssett, som senere vil bli redigert, vil han definitivt huske deg med et vennlig ord når han mottar en feilmelding når han starter applikasjonen. Hvis redigering av endringssettet på en eller annen måte lekker ut i utviklingen, må du følge den glatte bakken med hurtigreparasjoner. Essensen av problemet hviler på validering av endringer ved hashsum - hovedmekanismen til Liquibase. Når du redigerer endringssettkoden, endres hash-beløpet. Redigering av endringssett er bare mulig når det er mulig å distribuere hele databasen fra bunnen av uten å miste data. I dette tilfellet kan refaktorisering av SQL- eller XML-koden tvert imot gjøre livet enklere og gjøre migreringer mer lesbare. Et eksempel kan være en situasjon der, ved starten av applikasjonen, ble skjemaet til kildedatabasen avtalt i teamet.

4. Ha verifiserte sikkerhetskopier av databasen hvis mulig

Her tror jeg alt er klart. Hvis migreringen plutselig mislyktes, kan alt returneres. Liquibase har et verktøy for å rulle tilbake endringer, men tilbakerullingsskriptene er også skrevet av utvikleren selv, og de kan ha problemer med samme sannsynlighet som skriptene til hovedendringssettet. Dette betyr at det er nyttig å spille det trygt med sikkerhetskopier i alle fall.

5. Bruk dokumenterte sikkerhetskopier av database under utvikling, hvis mulig

Hvis dette ikke strider mot kontrakter og personvern, er det ingen personopplysninger i databasen, og den veier ikke så mye som to soler – før du bruker den på live migrasjonsservere kan du sjekke hvordan den vil fungere på utviklerens maskin og beregne nesten 100 % av potensielle problemer under migrering.

6. Kommuniser med andre utviklere i teamet

I en godt organisert utviklingsprosess vet alle i teamet hvem som gjør hva. I virkeligheten er dette ofte ikke tilfelle, derfor, hvis du forbereder endringer i databasestrukturen som en del av oppgaven din, er det lurt å varsle hele teamet om dette i tillegg. Hvis noen gjør endringer parallelt, bør du organisere deg nøye. Det er verdt å kommunisere med kolleger etter endt arbeid, ikke bare i starten. Mange potensielle problemer med endringssett kan løses på kodegjennomgangsstadiet.

7. Tenk over hva du gjør!

Det virker som et selvinnlysende råd som gjelder for enhver situasjon. Mange problemer kunne imidlertid vært unngått dersom utvikleren nok en gang hadde analysert hva han gjorde og hva det kunne påvirke. Arbeid med migreringer krever alltid ekstra oppmerksomhet og nøyaktighet.

feller

La oss nå se på de typiske fellene du kan gå i hvis du ikke følger rådene ovenfor, og hva bør du egentlig gjøre?

Situasjon 1: To utviklere prøver å legge til nye endringssett samtidig

Slik unngår du å skyte deg selv i foten med Liquibase
Vasya og Petya ønsker å lage et endringssett versjon 4, uten å vite om hverandre. De gjorde endringer i databasestrukturen og sendte ut en pull-forespørsel med forskjellige endringssettfiler. Følgende virkningsmekanisme er foreslått:

Hvordan bestemme

  1. På en eller annen måte må kollegaer bli enige om i hvilken rekkefølge endringssettene deres skal gå, for eksempel bør Petin brukes først.
  2. Noen bør legge til den andre til seg selv og markere Vasyas endringssett med versjon 5. Dette kan gjøres gjennom Cherry Pick eller en pen sammenslåing.
  3. Etter endringer bør du definitivt sjekke gyldigheten av handlingene som er utført.
    Faktisk vil Liquibase-mekanismene tillate deg å ha to versjon 4-endringssett i depotet, slik at du kan la alt være som det er. Det vil si at du rett og slett har to endringer til versjon 4 med forskjellige navn. Med denne tilnærmingen blir det senere svært vanskelig å navigere i databaseversjonene.

I tillegg holder Liquibase, som hjemmet til hobbitene, på mange hemmeligheter. En av dem er validCheckSum-nøkkelen, som dukket opp i versjon 1.7 og lar deg spesifisere en gyldig hash-verdi for et spesifikt endringssett, uavhengig av hva som er lagret i databasen. Dokumentasjon https://www.liquibase.org/documentation/changeset.html sier følgende:

Legg til en kontrollsum som anses som gyldig for dette endringssettet, uavhengig av hva som er lagret i databasen. Brukes først og fremst når du trenger å endre et changeSet og ikke vil ha feil kastet på databaser som det allerede har kjørt på (ikke en anbefalt prosedyre)

Ja, ja, denne prosedyren anbefales ikke. Men noen ganger behersker en sterk lysmagiker også mørketeknikker

Situasjon 2: Migrering som avhenger av data

Slik unngår du å skyte deg selv i foten med Liquibase

La oss anta at du ikke har muligheten til å bruke databasesikkerhetskopier fra live-servere. Petya opprettet et endringssett, testet det lokalt og, med full tillit til at han hadde rett, sendte han en pull-forespørsel til utvikleren. For sikkerhets skyld avklarte prosjektlederen om Petya hadde sjekket det, og deretter lagt det til. Men distribusjonen på utviklingsserveren falt.

Faktisk er dette mulig, og ingen er immun mot dette. Dette skjer hvis endringer i tabellstrukturen på en eller annen måte er knyttet til spesifikke data fra databasen. Det er klart, hvis Petyas database bare er fylt med testdata, kan det hende at den ikke dekker alle problemtilfeller. For eksempel, når du sletter en tabell, viser det seg at det er poster i andre tabeller etter Foreign Key som er relatert til poster i den som slettes. Eller når du endrer en kolonnetype, viser det seg at ikke 100 % av dataene kan konverteres til den nye typen.

Hvordan bestemme

  • Skriv spesielle skript som skal brukes én gang sammen med migreringen og bringe dataene inn i riktig form. Dette er en generell måte å løse problemet med å overføre data til nye strukturer etter bruk av migreringer, men noe lignende kan brukes før, i spesielle tilfeller. Denne banen er selvfølgelig ikke alltid tilgjengelig, fordi redigering av data på live-servere kan være farlig og til og med ødeleggende.
  • En annen vanskelig måte er å redigere et eksisterende endringssett. Problemet er at alle databaser der det allerede er brukt i sin eksisterende form, må gjenopprettes. Det er godt mulig at hele backend-teamet vil bli tvunget til å rulle ut databasen lokalt fra bunnen av.
  • Og den mest universelle måten er å overføre problemet med dataene til utviklerens miljø, gjenskape den samme situasjonen og legge til et nytt endringssett til det ødelagte, som vil omgå problemet.
    Slik unngår du å skyte deg selv i foten med Liquibase

Generelt, jo mer databasen er lik sammensetningen av produksjonsserverdatabasen, jo mindre sjanse for at problemer med migreringer vil gå langt. Og, selvfølgelig, før du sender et endringssett til depotet, bør du tenke flere ganger om det vil ødelegge noe.

Situasjon 3. Liquibase begynner å brukes etter at den går i produksjon

Anta at teamlederen ba Petya om å inkludere Liquibase i prosjektet, men prosjektet er allerede i produksjon og det er en eksisterende databasestruktur.

Følgelig er problemet at på alle nye servere eller utviklermaskiner, må disse tabellene gjenskapes fra bunnen av, og det eksisterende miljøet må forbli i en konsistent tilstand, klar til å akseptere nye endringssett.

Hvordan bestemme

Det er også flere måter:

  • Det første og mest åpenbare er å ha et eget skript som må brukes manuelt ved initialisering av et nytt miljø.
  • Den andre er mindre åpenbar, ha en Liquibase-migrering som er i en annen Liquibase-kontekst, og bruk den. Du kan lese mer om Liquibase Context her: https://www.liquibase.org/documentation/contexts.html. Generelt er dette en interessant mekanisme som med hell kan brukes til for eksempel testing.
  • Den tredje veien består av flere trinn. Først må det opprettes en migrering for eksisterende tabeller. Deretter må den brukes på et eller annet miljø og dermed oppnås hash-summen. Det neste trinnet er å initialisere tomme Liquibase-tabeller på vår ikke-tomme server, og i tabellen med historikken for bruk av endringssett kan du manuelt legge inn en post om endringssettet "som om anvendt" med endringer som allerede eksisterer i databasen . På en eksisterende server vil derfor historienedtellingen starte fra versjon 2, og alle nye miljøer vil oppføre seg likt.
    Slik unngår du å skyte deg selv i foten med Liquibase

Situasjon 4. Migrasjoner blir enorme og har ikke tid til å fullføre

I begynnelsen av tjenesteutviklingen brukes som regel Liquibase som en ekstern avhengighet, og alle migreringer behandles når applikasjonen starter. Men over tid kan du snuble over følgende tilfeller:

  • Migrasjoner blir enorme og tar lang tid å fullføre.
  • Det er behov for migrering i distribuerte miljøer, for eksempel på flere databaseserverinstanser samtidig.
    I dette tilfellet vil bruk av migreringer for lenge resultere i et tidsavbrudd når programmet starter. I tillegg kan bruk av migreringer til hver applikasjonsforekomst separat føre til at forskjellige servere ikke er synkroniserte.

Hvordan bestemme

I slike tilfeller er prosjektet ditt allerede stort, kanskje til og med en voksen, og Liquibase begynner å fungere som et eget eksternt verktøy. Faktum er at Liquibase som bibliotek er kompilert til en jar-fil, og kan fungere som en avhengighet i et prosjekt eller uavhengig.

I frittstående modus kan du overlate implementeringen av migreringer til CI/CD-miljøet eller til de sterke skuldrene til systemadministratorene og distribusjonsspesialistene. For å gjøre dette trenger du Liquibase-kommandolinjen https://www.liquibase.org/documentation/command_line.html. I denne modusen blir det mulig å starte applikasjonen etter at alle nødvendige migreringer er utført.

Utgang

Faktisk kan det være mange flere fallgruver når du arbeider med databasemigreringer, og mange av dem krever en kreativ tilnærming. Det er viktig å forstå at hvis du bruker verktøyet riktig, kan de fleste av disse fallgruvene unngås. Spesifikt måtte jeg håndtere alle de oppførte problemene i forskjellige former, og noen av dem var et resultat av mine feil. Stort sett skjer dette, selvfølgelig, på grunn av uoppmerksomhet, men noen ganger på grunn av kriminell manglende evne til å bruke verktøyet.

Kilde: www.habr.com

Legg til en kommentar