Sådan skyder du ikke dig selv i foden med Liquibase

Det skete aldrig, og her er det igen!

På det næste projekt besluttede vi at bruge Liquibase helt fra begyndelsen for at undgå problemer i fremtiden. Det viste sig, at ikke alle unge teammedlemmer ved, hvordan man bruger det korrekt. Jeg lavede en intern workshop, som jeg så besluttede at lave om til en artikel.

Denne artikel indeholder nyttige tips og beskrivelser af tre af de mest åbenlyse faldgruber, du kan falde i, når du arbejder med relationelle databasemigreringsværktøjer, især Liquibase. Designet til Java-udviklere på junior- og mellemniveau, for mere erfarne udviklere kan det være interessant at strukturere og gentage, hvad der højst sandsynligt allerede er kendt.

Sådan skyder du ikke dig selv i foden med Liquibase

Liquibase og Flyway er de vigtigste konkurrerende teknologier til at løse problemerne med versionskontrol af relationelle strukturer i Java-verdenen. Den første er helt gratis, i praksis er den oftere valgt til brug, hvorfor Liquibase blev valgt som publikationens helt. Nogle af de beskrevne fremgangsmåder kan dog være generiske, afhængigt af din applikations arkitektur.

Relationelle migrationer er en tvungen måde at håndtere den svage fleksibilitet i relationelle datalagre. I modeens æra for OOP betød stilen med at arbejde med databasen, at vi ville beskrive skemaet én gang og ikke røre det igen. Men virkeligheden er altid, at tingene ændrer sig, og ændringer i tabellernes struktur er påkrævet ret ofte. Naturligvis er selve processen smertefuld og ubehagelig.

Jeg vil ikke dykke ned i beskrivelsen af ​​teknologien og instruktionerne til at tilføje biblioteket til dit projekt, der er skrevet nok artikler om dette emne:

Derudover var der allerede en god artikel om emnet nyttige tips:

Советы

Jeg vil gerne dele mine råd og kommentarer, som blev født gennem sved, blod og smerte ved at løse problemer med migration.

1. Før du starter, bør du læse afsnittet om bedste praksis vedr Online Liquibase

Там enkle, men meget vigtige ting er beskrevet, uden hvilke brugen af ​​biblioteket kan komplicere dit liv. For eksempel vil en ikke-strukturel tilgang til ændringssætstyring før eller siden føre til forvirring og brudte migrationer. Hvis man ikke samtidig udruller gensidigt afhængige ændringer i strukturen af ​​databasen og tjenesternes logik, så er der stor sandsynlighed for, at det vil føre til røde tests eller et ødelagt miljø. Derudover indeholder anbefalingerne for brug af Liquibase på den officielle hjemmeside et afsnit om udvikling og verificering af rollback-scripts sammen med de vigtigste migreringsscripts. Nå, i artiklen https://habr.com/ru/post/178665/ der er eksempler på kode relateret til migrationer og rollback-mekanismen.

2. Hvis du begyndte at bruge migreringsværktøjer, tillad ikke manuelle rettelser i databasestrukturen

Som man siger: "En gang Persil, altid Persil." Hvis basen af ​​din applikation er begyndt at blive administreret af Liquibase-værktøjer, fører eventuelle manuelle ændringer øjeblikkeligt til en inkonsistent tilstand, og tilliden til ændringssæt bliver nul. Potentielle risici - flere timer brugt på at gendanne databasen, i værste fald - en død server. Hvis dit team har en "old school" DBA-arkitekt, så forklar ham tålmodigt og eftertænksomt, hvor slemt det vil gå, hvis han bare redigerer databasen på sin egen måde fra den betingede SQL-udvikler.

3. Hvis ændringssættet allerede er blevet skubbet til lageret, undgå redigering

Hvis en anden udvikler trak og anvendte et ændringssæt, der vil blive redigeret senere, vil han helt sikkert huske dig med et venligt ord, når han modtager en fejl, når applikationen starter. Hvis redigering af ændringssættet på en eller anden måde lækker ind i udviklingen, bliver du nødt til at gå ned ad den glatte bakke med hotfixes. Essensen af ​​problemet hviler på valideringen af ​​ændringer ved hjælp af hashsum - Liquibases hovedmekanisme. Når du redigerer ændringssætkoden, ændres hash-summen. Redigering af ændringssæt er kun muligt, når det er muligt at implementere hele databasen fra bunden uden at miste data. I dette tilfælde kan refaktorering af SQL eller XML-kode tværtimod gøre livet lettere, gøre migreringer mere læsbare. Et eksempel kunne være en situation, hvor skemaet for kildedatabasen blev koordineret i teamet ved starten af ​​applikationen.

4. Hav verificerede databasesikkerhedskopier, hvis det er muligt

Her tror jeg, alt er klart. Hvis migreringen pludselig mislykkedes, kan alt returneres. Liquibase har et rollback værktøj, men rollback scripts er også skrevet af udvikleren selv, og de kan have problemer med samme sandsynlighed som i de vigtigste changeset scripts. Det betyder, at det er nyttigt at spille sikkert med sikkerhedskopier under alle omstændigheder.

5. Brug verificerede databasebackups under udvikling, hvis det er muligt

Hvis dette ikke er i modstrid med kontrakter og privatliv, er der ingen personlige data i databasen, og det vejer ikke som to sole - før du anvender det på live migrationsservere, kan du tjekke, hvordan det fungerer på udviklerens maskine og beregne næsten 100 % potentielle problemer under migration.

6. Chat med andre udviklere på holdet

I en velorganiseret udviklingsproces ved alle på teamet, hvem der gør hvad. I virkeligheden er dette ofte ikke tilfældet, så hvis du forbereder ændringer i databasestrukturen som en del af din opgave, er det tilrådeligt yderligere at give hele teamet besked om dette. Hvis nogen foretager ændringer parallelt, bør du organisere dig omhyggeligt. Det er værd at kommunikere med kolleger selv i slutningen af ​​arbejdet, ikke kun i starten. Mange potentielle problemer med ændringssæt kan løses på kodegennemgangsstadiet.

7. Tænk, hvad du laver!

Tilsyneladende selvindlysende råd, der gælder i enhver situation. Mange problemer kunne dog være undgået, hvis udvikleren endnu en gang havde analyseret, hvad han lavede, og hvad det kunne påvirke. At arbejde med migreringer kræver altid ekstra opmærksomhed og nøjagtighed.

fælder

Lad os nu se på de typiske fælder, man kan falde i, hvis man ikke følger rådene ovenfor, og hvad skal man egentlig gøre?

Situation 1. To udviklere forsøger at tilføje nye ændringssæt på samme tid

Sådan skyder du ikke dig selv i foden med Liquibase
Vasya og Petya ønsker at oprette et version 4-ændringssæt uden at kende til hinanden. De lavede ændringer i databasestrukturen og udrullede en pull-anmodning med forskellige ændringssætfiler. Følgende mekanisme foreslås nedenfor:

Hvordan man beslutter sig

  1. På en eller anden måde skal kollegerne blive enige om den rækkefølge, som deres ændringer skal gå i, lad os sige, at Petin skal anvendes først.
  2. Én person bør hælde den anden i og markere Vasyas ændringssæt med version 5. Dette kan gøres via Cherry Pick eller en pæn sammenfletning.
  3. Efter ændringerne skal du sørge for at kontrollere gyldigheden af ​​de udførte handlinger.
    Faktisk vil Liquibase-mekanismerne tillade dig at have to version 4-ændringssæt i depotet, så du kan lade alt være som det er. Det vil sige, at du blot vil have to versioner af version 4 med forskellige navne. Med denne tilgang bliver databaseversioner meget vanskelige at navigere i senere.

Derudover holder Liquibase, ligesom hobitternes hjem, på en masse hemmeligheder. En af dem er validCheckSum-nøglen, som er dukket op siden version 1.7 og giver dig mulighed for at angive en gyldig hashværdi for et specifikt ændringssæt, uanset hvad der er gemt i databasen. Dokumentation https://www.liquibase.org/documentation/changeset.html siger følgende:

Tilføj en kontrolsum, der anses for at være gyldig for dette ændringssæt, uanset hvad der er gemt i databasen. Bruges primært når du skal ændre et changeSet og ikke vil have fejl smidt på databaser, som det allerede har kørt på (ikke en anbefalet procedure)

Ja, dette anbefales ikke. Men nogle gange mestrer en stærk lysmagiker også mørke teknikker.

Case 2: Datadrevet migration

Sådan skyder du ikke dig selv i foden med Liquibase

Lad os sige, at du ikke kan bruge database backups fra live servere. Petya oprettede et ændringssæt, testede det lokalt, og med fuld tillid til, at han havde ret, fremsatte han en pull-anmodning til udvikleren. For en sikkerheds skyld afklarede projektlederen, om Petya tjekkede det, og hældte det derefter ind. Men implementeringen på udviklingsserveren er faldet.

Faktisk er dette muligt, og ingen er immune over for dette. Dette sker, hvis ændringer af tabelstrukturen på en eller anden måde er knyttet til specifikke data fra databasen. Det er klart, at hvis Petyas database kun er fyldt med testdata, dækker den muligvis ikke alle problemtilfælde. Når man f.eks. sletter en tabel, viser det sig, at der er poster i andre tabeller efter Foreign Key tilknyttet poster i den, der slettes. Eller når man skifter kolonnetype, viser det sig, at ikke 100 % af dataene kan konverteres til den nye type.

Hvordan man beslutter sig

  • Skriv specielle scripts, der vil blive anvendt én gang sammen med migreringen, og bring dataene i den rigtige form. Dette er en generel måde at løse problemet med at overføre data til nye strukturer efter anvendelse af migreringer, men noget lignende kan anvendes før, i særlige tilfælde. Denne sti er selvfølgelig ikke altid tilgængelig, fordi redigering af data på live-servere kan være farlig og endda fatal.
  • En anden vanskelig måde er at redigere et eksisterende ændringssæt. Vanskeligheden er, at alle de databaser, hvor det allerede er blevet anvendt i sin eksisterende form, skal gendannes. Det er meget muligt, at hele backend-teamet vil blive tvunget til lokalt at rulle databasen op fra bunden.
  • Og den mest universelle måde er at overføre dataproblemet til udviklerens miljø, genskabe den samme situation og tilføje et nyt ændringssæt til et ødelagt, der vil omgå problemet.
    Sådan skyder du ikke dig selv i foden med Liquibase

Generelt gælder det, at jo mere databasen i sammensætning ligner produktionsserverdatabasen, jo mindre sandsynligt vil problemer med migreringer gå langt. Og selvfølgelig, før du sender ændringssættet til repository, bør du overveje flere gange, om det vil bryde noget.

Situation 3. Liquibase begynder at blive brugt, efter at den går i produktion

Antag, at teamlederen bad Petya om at inkludere Liquibase i projektet, men projektet er allerede i produktion, og der er en allerede eksisterende databasestruktur.

Derfor er problemet, at på alle nye servere eller udviklermaskiner skal tabeldataene genskabes fra bunden, og det allerede eksisterende miljø skal forblive i en konsistent tilstand og være klar til at acceptere nye ændringer.

Hvordan man beslutter sig

Der er også flere måder:

  • Den første og mest oplagte er at have et separat script, der skal anvendes manuelt, når et nyt miljø initialiseres.
  • Den anden, mindre indlysende, er at have en Liquibase-migrering, der er i en anden Liquibase-kontekst, og anvende den. Du kan læse mere om Liquibase Context her: https://www.liquibase.org/documentation/contexts.html. Generelt er dette en interessant mekanisme, der med succes kan anvendes, for eksempel til test.
  • Den tredje vej består af flere trin. Først skal der oprettes en migrering for eksisterende tabeller. Så skal det anvendes på et eller andet miljø, og dermed vil dens hash-sum blive opnået. Det næste trin er at initialisere tomme Liquibase-tabeller på vores ikke-tomme server, og du kan manuelt indsætte en registrering af et "som om anvendt" ændringssæt med de ændringer, der allerede er i databasen, i tabellen med historikken for anvendelse af ændringssæt. På en allerede eksisterende server vil historikken således starte fra version 2, og alle nye miljøer vil opføre sig identisk.
    Sådan skyder du ikke dig selv i foden med Liquibase

Scenario 4: Migrationer bliver enorme og kan ikke følge med

I starten af ​​serviceudviklingen bruges Liquibase som udgangspunkt som en ekstern afhængighed, og alle migreringer behandles når applikationen starter. Men med tiden kan du støde på følgende tilfælde:

  • Migrationer bliver enorme og tager lang tid at gennemføre.
  • Der er behov for at migrere i distribuerede miljøer, for eksempel på flere forekomster af databaseservere på samme tid.
    I dette tilfælde vil anvendelse af migreringer i for lang tid resultere i en timeout, når applikationen starter. Anvendelse af migreringer pr. applikationsforekomst kan også resultere i, at forskellige servere er ude af synkronisering.

Hvordan man beslutter sig

I sådanne tilfælde er dit projekt allerede stort, måske endda en voksen, og Liquibase begynder at fungere som et separat eksternt værktøj. Faktum er, at Liquibase, som et bibliotek, er samlet i en jar-fil, og kan fungere som en afhængighed i projektet, såvel som selvstændigt.

Offline kan du overlade anvendelsen af ​​migrationer til dit CI/CD-miljø eller til dine sysadmins/installatørers stærke skuldre. For at gøre dette skal du bruge Liquibase-kommandolinjen https://www.liquibase.org/documentation/command_line.html. I denne tilstand bliver det muligt at starte applikationen, efter at alle de nødvendige migreringer er gennemført.

Output

Faktisk er der mange flere faldgruber, når man arbejder med databasemigreringer, og mange af dem kræver en kreativ tilgang. Det er vigtigt at forstå, at hvis du bruger værktøjet korrekt, så kan de fleste af disse fælder undgås. Specifikt skulle jeg stå over for alle de problemer, der var anført i forskellige former, og nogle af dem var resultatet af mine jambs. Grundlæggende sker dette selvfølgelig på grund af uopmærksomhed, men nogle gange - på grund af den kriminelle manglende evne til at bruge værktøjet.

Kilde: www.habr.com

Tilføj en kommentar