{"id":70973,"date":"2020-02-23T00:58:26","date_gmt":"2020-02-22T21:58:26","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase"},"modified":"2020-03-03T16:14:41","modified_gmt":"2020-03-03T13:14:41","slug":"kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","title":{"rendered":"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Aldrig har det v\u00e6ret, og nu er det igen!<\/p>\n<p><\/p>\n<p>I et nyt projekt besluttede vi at bruge Liquibase fra starten for at undg\u00e5 problemer i fremtiden. Det viste sig, at ikke alle unge teammedlemmer ved, hvordan man bruger det korrekt. Jeg afholdt en intern workshop, som jeg derefter besluttede at g\u00f8re til en artikel. <\/p>\n<p><\/p>\n<p>Artiklen indeholder nyttige tips og beskriver tre af de mest \u00e5benlyse f\u00e6lder, man kan falde i, n\u00e5r man arbejder med v\u00e6rkt\u00f8jer til migrering af relationelle databaser, is\u00e6r Liquibase. Den er rettet mod Java-udviklere p\u00e5 junior- og mellem-niveau; mere erfarne udviklere kan finde den interessant til strukturerings- og repetitionsform\u00e5l for det, der sandsynligvis allerede er kendt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/f8b3c9a456bde7aa123702fae132b4b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Liquibase og Flyway er de prim\u00e6re konkurrencepr\u00e6gede teknologier til kontrol af versioner af relationelle strukturer i Java-verdenen. Den f\u00f8rste er fuldst\u00e6ndig gratis, og i praksis v\u00e6lges den oftere til brug, s\u00e5 det er netop Liquibase, der er valgt som fokus for denne publikation. Ikke desto mindre kan nogle af de beskrevne praksisser v\u00e6re universelle, afh\u00e6ngigt af din applikations arkitektur. <\/p>\n<p><\/p>\n<p>Migrering af relationelle strukturer er en n\u00f8dvendighed for at bek\u00e6mpe den begr\u00e6nsede fleksibilitet i relationelle datalagre. I den tid, hvor OOP var p\u00e5 mode, indebar m\u00e5den at arbejde med databaser p\u00e5, at vi engang beskrev skemaet og ikke ville r\u00f8re det igen. Men virkeligheden er altid s\u00e5dan, at alt \u00e6ndrer sig, og \u00e6ndringer i tabelstrukturer er n\u00f8dvendige ret ofte. Naturligvis kan processen i sig selv v\u00e6re smertefuld og ubehagelig. <\/p>\n<p><\/p>\n<p>Jeg vil ikke g\u00e5 i dybden med teknologien og instruktionerne til at tilf\u00f8je biblioteket til dit projekt; der er skrevet tilstr\u00e6kkeligt om dette emne:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460377\/\">Brug af Liquibase til at styre databasens struktur i et Spring Boot projekt. Del 1<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460907\/\">Brug af Liquibase til at styre databasens struktur i et Spring Boot projekt. Del 2<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436994\/\">Liquibase og Maven<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/330662\/\">Tilgange til versionering af \u00e6ndringer i databasen<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/271719\/\">Spring MVC\/Security, REST, Hibernate, Liquibase, startes med to linjer<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<p>Derudover har der allerede v\u00e6ret en fremragende artikel om nyttige tips:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/179425\/\">Brug af Liquibase uden hovedpine. 10 tips fra virkelige udviklingserfaringer<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"sovety\">Tips<\/h2>\n<p><\/p>\n<p>Jeg vil gerne dele mine r\u00e5d og kommentarer, der er opst\u00e5et gennem sved, blod og smerte ved l\u00f8sning af migrationsproblemer.<\/p>\n<p><\/p>\n<h3 id=\"1--pered-rabotoy-sleduet-oznakomitsya-s-razdelom-luchshih-praktik-na-saytehttpswwwliquibaseorgbestpracticeshtml-liquibase\">1. F\u00f8r du begynder, b\u00f8r du g\u00f8re dig bekendt med afsnittet om bedste praksis p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">websitet<\/a><\/noindex> Liquibase<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">Der<\/a><\/noindex> Der er beskrevet enkle, men meget vigtige ting, uden hvilke brugen af biblioteket kan komplicere dit liv. For eksempel vil en ustruktureret tilgang til h\u00e5ndtering af changesets f\u00f8r eller senere f\u00f8re til forvirring og brudte migrationer. Hvis \u00e6ndringer i databasen og logikken i tjenesterne, der afh\u00e6nger af hinanden, ikke udf\u00f8res samtidig, er der stor risiko for, at dette vil f\u00f8re til fejltagelser eller \u00f8delagte milj\u00f8er. Desuden indeholder anbefalingerne for brug af Liquibase p\u00e5 den officielle hjemmeside et punkt om udvikling og test af rollback-scripts sammen med de prim\u00e6re migrationsscripts. Og i artiklen <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/178665\/\">https:\/\/habr.com\/ru\/post\/178665\/<\/a><\/noindex> findes der kodeeksempler relateret til migrationer og rollback-mekanismen. <\/p>\n<p><\/p>\n<h3 id=\"2-esli-nachali-ispolzovat-sredstva-migracii--ne-dopuskayte-manualnyh-ispravleniy-v-strukture-bazy\">2. Hvis du er begyndt at bruge migrationsv\u00e6rkt\u00f8jer \u2013 m\u00e5 du ikke lave manuelle \u00e6ndringer i databasens struktur<\/h3>\n<p><\/p>\n<p>Som man siger: \"\u00c9n gang Persil \u2013 altid Persil\". Hvis din applikations database begynder at blive styret af Liquibase, vil enhver manuel \u00e6ndring \u00f8jeblikkeligt f\u00f8re til en inkonsistent tilstand, og tilliden til changesets bliver lig med nul. Potentielle risici inkluderer flere timers arbejde p\u00e5 at genskabe databasen; i v\u00e6rste fald kan det f\u00f8re til en \u00f8delagt server. Hvis du har en DBA-arkitekt i dit team, der er \"gammeldags\", skal du t\u00e5lmodigt og omhyggeligt forklare ham, hvordan alt vil g\u00e5 galt, hvis han blot redigerer databasen efter eget sk\u00f8n fra en hypotetisk SQL Developer. <\/p>\n<p><\/p>\n<h3 id=\"3-esli-chendzhset-uzhe-byl-zapushen-v-repozitoriy-izbegayte-redaktirovaniya\">3. Hvis changesetet allerede er blevet pushed til repositoryet, skal du undg\u00e5 redigering<\/h3>\n<p><\/p>\n<p>Hvis en anden udvikler har lavet en pull og anvendt et changeset, der senere vil blive redigeret, vil han helt sikkert n\u00e6vne dig med venlighed, n\u00e5r han f\u00e5r en fejl ved opstart af applikationen. Hvis redigeringen af changesetet p\u00e5 en eller anden m\u00e5de sniger sig ind i udviklingen, vil det v\u00e6re n\u00f8dvendigt at g\u00e5 en usikker vej med hotfixes. Kernen i problemet ligger i valideringen af \u00e6ndringer efter hash-v\u00e6rdi \u2013 den grundl\u00e6ggende mekanisme i Liquibase. N\u00e5r koden i changesetet redigeres, \u00e6ndres hash-v\u00e6rdien. Redigering af changesets er kun mulig, n\u00e5r der er mulighed for at genopbygge hele databasen fra bunden uden tab af data. I s\u00e5danne tilf\u00e6lde kan refaktorering af SQL- eller XML-koden faktisk lette arbejdet og g\u00f8re migrationer mere l\u00e6sevenlige. Et eksempel kan v\u00e6re situationen, hvor skemaet for den oprindelige database blev koordineret internt i teamet ved opstart af applikationen. <\/p>\n<p><\/p>\n<h3 id=\"4--imey-proverennye-bekapy-baz-dannyh-esli-eto-vozmozhno\">4. Hav altid verificerede databasebackups, hvis det er muligt<\/h3>\n<p><\/p>\n<p>Her tror jeg, det hele er klart. Hvis migreringen skulle mislykkes, kan alt blive gendannet. I Liquibase er der et v\u00e6rkt\u00f8j til at rulle \u00e6ndringer tilbage, men scripts til tilbagerulning skrives ogs\u00e5 af udvikleren, og der kan v\u00e6re problemer med dem med samme sandsynlighed som med scripts fra den prim\u00e6re changset. Det betyder, at det er en god id\u00e9 at v\u00e6re forsigtig med backups i alle tilf\u00e6lde. <\/p>\n<p><\/p>\n<h3 id=\"5-ispolzuy-proverennye-bekapy-baz-dannyh-v-razrabotke-esli-eto-vozmozhno\">5. Brug verificerede databasebackups i udviklingen, hvis det er muligt<\/h3>\n<p><\/p>\n<p>Hvis det ikke strider mod kontrakter og privatliv, der ikke er personlige data i databasen, og den ikke fylder som to sunne \u2014 f\u00f8r du anvender migreringen p\u00e5 live-servere, kan du teste, hvordan det fungerer p\u00e5 udviklermaskinen, og identificere n\u00e6sten 100% af de potentielle problemer ved migreringen. <\/p>\n<p><\/p>\n<h3 id=\"6-obschaysya-s-drugimi-razrabotchikami-v-komande\">6. Kommuniker med andre udviklere i teamet<\/h3>\n<p><\/p>\n<p>I en korrekt organiseret udviklingsproces ved alle i teamet, hvem der laver hvad. I virkeligheden er det ofte ikke tilf\u00e6ldet, s\u00e5 hvis du forbereder \u00e6ndringer i database-strukturen i forbindelse med din opgave, er det bedst at informere hele teamet om dette. Hvis nogen laver \u00e6ndringer parallelt \u2014 skal I organisere jer forsigtigt. Det er v\u00e6rdifuldt at kommunikere med kolleger, ogs\u00e5 efter arbejdet er f\u00e6rdigt, ikke kun i starten. Mange potentielle problemer med changsets kan blive l\u00f8st i kodegennemgangen. <\/p>\n<p><\/p>\n<h3 id=\"7-dumay-chto-delaesh\">7. T\u00e6nk over, hvad du g\u00f8r!<\/h3>\n<p><\/p>\n<p>Det virker som en selvf\u00f8lgelighed, anvendelig i enhver situation. Dog ville mange problemer kunne undg\u00e5s, hvis udvikleren tog et \u00f8jeblik til at analysere, hvad han g\u00f8r, og hvilken indflydelse det kan have. Arbejdet med migrationer kr\u00e6ver altid ekstra opm\u00e6rksomhed og omhu. <\/p>\n<p><\/p>\n<h2 id=\"lovushki\">F\u00e6lder<\/h2>\n<p><\/p>\n<p>Lad os nu se p\u00e5 typiske f\u00e6lder, man kan falde i, hvis man ikke f\u00f8lger ovenst\u00e5ende r\u00e5d, og hvad skal man egentlig g\u00f8re?<\/p>\n<p><\/p>\n<h3 id=\"situaciya-1-dva-razrabotchika-pytayutsya-odnovremenno-dobavlyat-novye-chendzhsety\">Situation 1. To udviklere fors\u00f8ger samtidigt at tilf\u00f8je nye changsets<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/20706fc970510bc06634fa001a4c7ceb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVasya og Petya \u00f8nsker at oprette changset version 4 uden at vide om hinanden. De har foretaget \u00e6ndringer i database-strukturen og har sendt pull request med forskellige changset-filer. F\u00f8lgende handlingsmekanisme foresl\u00e5s:<\/p>\n<p><\/p>\n<h4 id=\"kak-reshat\">Hvordan man l\u00f8ser det<\/h4>\n<p><\/p>\n<ol>\n<li>P\u00e5 en eller anden m\u00e5de skal kollegerne blive enige om, i hvilken r\u00e6kkef\u00f8lge deres changsets skal anvendes, for eksempel, at Petyas skal anvendes f\u00f8rst. <\/li>\n<li>En person skal h\u00e6lde den anden i sig og markere Vasja's changetset med version 5. Dette kan g\u00f8res gennem Cherry Pick eller en forsigtig merge. <\/li>\n<li>Efter \u00e6ndringerne skal man altid kontrollere gyldigheden af de udf\u00f8rte handlinger.<br \/>\nFaktisk vil Liquibase mekanismerne tillade at have to changets med version 4 i arkivet, s\u00e5 det kan efterlades som det er. Det vil sige, at du bare vil have to \u00e6ndringer til version 4 med forskellige navne. Med denne tilgang bliver det meget vanskeligt at navigere i versionerne af databasen senere. <\/li>\n<\/ol>\n<p><\/p>\n<p>Desuden opbevarer Liquibase, ligesom hobbitternes hjem, mange hemmeligheder. En af dem er n\u00f8glen validCheckSum, der blev introduceret med version 1.7 og g\u00f8r det muligt at angive en gyldig v\u00e6rdi for checksummen for et bestemt changetset uanset hvad der er lagret i databasen. Dokumentation <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/changeset.html\">https:\/\/www.liquibase.org\/documentation\/changeset.html<\/a><\/noindex> siger f\u00f8lgende:<\/p>\n<p><\/p>\n<blockquote><p>Tilf\u00f8j en checksum, der betragtes som gyldig for denne changeSet, uanset hvad der er gemt i databasen. Bruges prim\u00e6rt, n\u00e5r du har brug for at \u00e6ndre en changeSet og ikke \u00f8nsker, at der opst\u00e5r fejl p\u00e5 databaser, som det allerede er blevet k\u00f8rt p\u00e5 (ikke en anbefalet procedure)<\/p><\/blockquote>\n<p>Ja, ja, denne procedure anbefales ikke. Men nogle gange besidder en st\u00e6rk lys magiker ogs\u00e5 m\u00f8rke teknikker. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-2-migraciya-kotoraya-zavisit-ot-dannyh\">Situation 2. Migrationen afh\u00e6nger af data<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/31a6eebb55278c0631115bf16483c7b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Antag, at du ikke har mulighed for at bruge backup af databaser fra live servere. Petja oprettede et changetset, testede det lokalt og med fuld tillid til sin egen retf\u00e6rdighed lavede han en pull request til udviklingen. Projektlederen bekr\u00e6ftede ligeledes, om Petja havde tjekket det og derefter fusionerede det. Men udrulningen p\u00e5 udviklingsserveren fejlede.<\/p>\n<p><\/p>\n<p>Faktisk er det muligt, og ingen kan v\u00e6re sikker mod dette. Det sker, n\u00e5r \u00e6ndringer i tabelstrukturen p\u00e5 en eller anden m\u00e5de er bundet til specifikke data fra databasen. Det er tydeligt, at hvis Petjas database kun er fyldt med testdata, kan den muligvis ikke d\u00e6kke alle problematiske sager. For eksempel, n\u00e5r en tabel slettes, viser det sig, at der er poster i andre tabeller med Foreign Key, der er relateret til poster i den slettede. Eller n\u00e5r datatypen af en kolonne \u00e6ndres, viser det sig, at ikke 100% af dataene kan konverteres til den nye type. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-1\">Hvordan man l\u00f8ser det<\/h4>\n<p><\/p>\n<ul>\n<li>Skrive s\u00e6rlige scripts, som anvendes \u00e9n gang sammen med migrationen og bringer data i den rette form. Dette er en generel l\u00f8sning p\u00e5 problemet med at overf\u00f8re data til nye strukturer efter migrationerne, men noget lignende kan ogs\u00e5 anvendes f\u00f8r, i s\u00e6rlige tilf\u00e6lde. En s\u00e5dan l\u00f8sning er naturligvis ikke altid tilg\u00e6ngelig, da det kan v\u00e6re farligt og endda \u00f8del\u00e6ggende at redigere data p\u00e5 live-servere. <\/li>\n<li>En anden vanskelig l\u00f8sning er at redigere det eksisterende changeset. Problematikken ligger i, at alle databaser, hvor det allerede er blevet anvendt i sin nuv\u00e6rende form, skal genskabes. Det er helt muligt, at hele backend-teamet tvinges til at k\u00f8re databasen lokalt fra bunden. <\/li>\n<li>Og den mest universelle l\u00f8sning er at overf\u00f8re datafejlen til udviklerens milj\u00f8 med en genskabelse af den samme situation og tilf\u00f8jelse af et nyt changeset, som kan omg\u00e5 problemet.<br \/>\n<img decoding=\"async\" alt=\"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/b5d28a940a7a35b6cd7a819a8e68f027.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ul>\n<p><\/p>\n<p>Generelt g\u00e6lder, at jo mere ens databasen er i forhold til produktionsserveren, desto mindre chance er der for, at migrationsproblemerne str\u00e6kker sig langt. Og selvf\u00f8lgelig, f\u00f8r du sender changesetet til depotet, b\u00f8r du overveje flere gange, om det vil \u00f8del\u00e6gge noget. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-3-liquibase-nachinaet-primenyatsya-uzhe-posle-vyhoda-v-prodakshn\">Situation 3. Liquibase begynder at blive anvendt efter produktionen er startet<\/h3>\n<p><\/p>\n<p>Antag, at teamlederen har bedt Peter om at implementere Liquibase i projektet, men projektet er allerede i produktion, og der er en eksisterende database-struktur.<\/p>\n<p><\/p>\n<p>Problemet er derfor, at dataene i tabellerne skal genskabes fra bunden p\u00e5 alle nye servere eller udviklermaskiner, mens det eksisterende milj\u00f8 skal forblive i en konsistent tilstand, klar til at modtage nye changesets. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-2\">Hvordan man l\u00f8ser det<\/h4>\n<p><\/p>\n<p>Der er ogs\u00e5 flere veje at g\u00e5 her:<\/p>\n<p><\/p>\n<ul>\n<li>Den f\u00f8rste og mest \u00e5benlyse er at have et separat script, der skal anvendes manuelt ved initialization af det nye milj\u00f8. <\/li>\n<li>Den anden \u2014 mindre \u00e5benlys, er at have en Liquibase-migration, der befinder sig i en anden Liquibase-kontekst, og anvende den. Du kan l\u00e6se mere om Liquibase-kontekst her: <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/contexts.html\">https:\/\/www.liquibase.org\/documentation\/contexts.html<\/a><\/noindex>. Generelt er det et interessant mekanisme, der kan anvendes med succes, f.eks. til testform\u00e5l. <\/li>\n<li>Den tredje vej best\u00e5r af flere trin. F\u00f8rst skal der oprettes en migration for de allerede eksisterende tabeller. Dern\u00e6st skal den anvendes i et bestemt milj\u00f8, og p\u00e5 den m\u00e5de opn\u00e5s dens hash-v\u00e6rdi. N\u00e6ste trin er at initialisere tomme Liquibase-tabeller p\u00e5 vores ikke-tomme server, og man kan manuelt inds\u00e6tte en post om en \"tilsyneladende anvendt\" changset i historik-tabellen med de allerede eksisterende \u00e6ndringer i databasen. P\u00e5 den m\u00e5de vil historikken p\u00e5 den eksisterende server starte fra version 2, mens alle nye milj\u00f8er vil opf\u00f8re sig analogt.<br \/>\n<img decoding=\"async\" alt=\"Hvordan man ikke skyder sig selv i foden ved brug af Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/78881ee56a6ee3ba4e0cd1089598c3c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"situaciya-4-migracii-stanovyatsya-ogromnymi-i-ne-uspevayut-vypolnyatsya\">Situation 4. Migrationer bliver enorme og n\u00e5r ikke at blive udf\u00f8rt.<\/h3>\n<p><\/p>\n<p>I begyndelsen af udviklingen af tjenesten bruges Liquibase normalt som en ekstern afh\u00e6ngighed, og alle migrationer behandles ved opstarten af applikationen. Men med tiden kan du st\u00f8de p\u00e5 f\u00f8lgende tilf\u00e6lde:<\/p>\n<p><\/p>\n<ul>\n<li>Migrationer bliver enorme og tager lang tid at udf\u00f8re.<\/li>\n<li>Der opst\u00e5r behov for migration i distribuerede milj\u00f8er, for eksempel p\u00e5 flere instanser af databaser samtidig.<br \/>\nI s\u00e5 fald vil for lang anvendelse af migrationer f\u00f8re til timeout ved opstart af applikationen. Desuden kan anvendelsen af migrationer for hver applikationsinstans separat f\u00f8re til, at forskellige servere ikke er synkroniserede. <\/li>\n<\/ul>\n<p><\/p>\n<h4 id=\"kak-reshat-3\">Hvordan man l\u00f8ser det<\/h4>\n<p><\/p>\n<p>I s\u00e5danne tilf\u00e6lde er dit projekt allerede stort, m\u00e5ske endda myndigt, og Liquibase begynder at fungere som et separat eksternt v\u00e6rkt\u00f8j. Problemet er, at Liquibase som bibliotek samles i en jar-fil og kan fungere b\u00e5de som en afh\u00e6ngighed inden for projektet og autonomt. <\/p>\n<p><\/p>\n<p>I autonom tilstand kan anvendelsen af migrationer overlades til dit CI\/CD-milj\u00f8 eller til de st\u00e6rke skuldre hos dine systemadministratorspecialister inden for implementering. Dette kr\u00e6ver kommandolinjen Liquibase. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/command_line.html\">https:\/\/www.liquibase.org\/documentation\/command_line.html<\/a><\/noindex>. I denne tilstand er det muligt at starte applikationen f\u00f8rst, efter at alle n\u00f8dvendige migrationer er blevet udf\u00f8rt.<\/p>\n<p><\/p>\n<h2 id=\"vyvod\">Output<\/h2>\n<p><\/p>\n<p>Der er faktisk langt flere feller, n\u00e5r man arbejder med DB-migrationer, og mange af dem kr\u00e6ver en kreativ tilgang. Det er vigtigt at forst\u00e5, at hvis v\u00e6rkt\u00f8jet anvendes korrekt, kan de fleste af disse feller undg\u00e5s. Personligt har jeg m\u00f8dt alle de n\u00e6vnte problemer i forskellige former, og nogle af dem var resultatet af mine egne fejl. Det sker hovedsageligt p\u00e5 grund af uopm\u00e6rksomhed, men nogle gange ogs\u00e5 p\u00e5 grund af kriminel manglende evne til at bruge v\u00e6rkt\u00f8jet.<\/p>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/epam_systems\/blog\/489198\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c. \u041a\u0430\u043a \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u043d\u0435 \u0432\u0441\u0435 \u043c\u043e\u043b\u043e\u0434\u044b\u0435 \u0447\u043b\u0435\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0443\u043c\u0435\u044e\u0442 \u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u042f \u043f\u0440\u043e\u0432\u0451\u043b \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0432\u043e\u0440\u043a\u0448\u043e\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u044e. \u0421\u0442\u0430\u0442\u044c\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u043e\u0432\u0435\u0442\u044b \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0445 \u0441\u0430\u043c\u044b\u0445 \u044f\u0432\u043d\u044b\u0445 \u043b\u043e\u0432\u0443\u0448\u0435\u043a, \u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":70974,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-70973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u043d\u0435 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0432 \u043d\u043e\u0433\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Liquibase | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-02-22T21:58:26+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-03T13:14:41+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Hvordan man undg\u00e5r at skyde sig selv i foden ved brug af Liquibase | ProHoster","description":"Aldrig har der v\u00e6ret, og her er vi igen! I et nyt projekt besluttede vi at bruge Liquibase fra starten for at undg\u00e5 problemer i fremtiden.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u043d\u0435 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0438\u0442\u044c \u0441\u0435\u0431\u0435 \u0432 \u043d\u043e\u0433\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Liquibase | ProHoster","og:description":"\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0438 \u0432\u043e\u0442 \u043e\u043f\u044f\u0442\u044c! \u041d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Liquibase \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c.","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-02-22T21:58:26+00:00","article:modified_time":"2020-03-03T13:14:41+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"70973","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:10:24","updated":"2022-09-28 08:39:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/70973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=70973"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/70973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/70974"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=70973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=70973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=70973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}