{"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\/pl\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","title":{"rendered":"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z Liquibase","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Nigdy wcze\u015bniej nie by\u0142o i zn\u00f3w to si\u0119 zdarzy\u0142o!<\/p>\n<p><\/p>\n<p>W naszym najnowszym projekcie zdecydowali\u015bmy si\u0119 wdro\u017cy\u0107 Liquibase od samego pocz\u0105tku, aby unikn\u0105\u0107 problem\u00f3w w przysz\u0142o\u015bci. Okaza\u0142o si\u0119, \u017ce nie wszyscy m\u0142odsze cz\u0142onkowie zespo\u0142u potrafi\u0105 go w\u0142a\u015bciwie u\u017cywa\u0107. Zorganizowa\u0142em wewn\u0119trzne warsztaty, kt\u00f3re postanowi\u0142em zamieni\u0107 w artyku\u0142. <\/p>\n<p><\/p>\n<p>Artyku\u0142 zawiera przydatne wskaz\u00f3wki oraz opis trzech najcz\u0119stszych pu\u0142apek, w kt\u00f3re mo\u017cna wpa\u015b\u0107 pracuj\u0105c z narz\u0119dziami do migracji relacyjnych baz danych, w szczeg\u00f3lno\u015bci Liquibase. Jest skierowany do programist\u00f3w Java na poziomie Junior i Middle, ale mo\u017ce by\u0107 interesuj\u0105cy r\u00f3wnie\u017c dla bardziej do\u015bwiadczonych programist\u00f3w w celu uporz\u0105dkowania i powt\u00f3rzenia tego, co najprawdopodobniej ju\u017c wiedz\u0105. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z 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 i Flyway to g\u0142\u00f3wne konkurencyjne technologie do zarz\u0105dzania wersjami struktur relacyjnych w \u015bwiecie Java. Pierwsza z nich jest ca\u0142kowicie bezp\u0142atna i w praktyce jest cz\u0119\u015bciej wybierana do u\u017cycia, dlatego Liquibase zosta\u0142o bohaterem tego publikacji. Niemniej jednak, niekt\u00f3re z opisanych praktyk mog\u0105 by\u0107 uniwersalne, w zale\u017cno\u015bci od architektury twojego aplikacji. <\/p>\n<p><\/p>\n<p>Migracje struktur relacyjnych s\u0105 wymuszonym sposobem radzenia sobie z nisk\u0105 elastyczno\u015bci\u0105 relacyjnych magazyn\u00f3w danych. W czasach mody na OOP praca z bazami danych polega\u0142a na tym, \u017ce raz opisali\u015bmy schemat i nie zmieniali\u015bmy go wi\u0119cej. Jednak rzeczywisto\u015b\u0107 zawsze jest taka, \u017ce wszystko si\u0119 zmienia, a zmiany w strukturze tabel s\u0105 do\u015b\u0107 cz\u0119ste. Oczywi\u015bcie, sam proces bywa bolesny i nieprzyjemny. <\/p>\n<p><\/p>\n<p>Nie b\u0119d\u0119 zag\u0142\u0119bia\u0107 si\u0119 w opis technologii i instrukcje dotycz\u0105ce dodawania biblioteki do swojego projektu, na ten temat napisano ju\u017c wystarczaj\u0105co du\u017co artyku\u0142\u00f3w:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460377\/\">U\u017cycie Liquibase do zarz\u0105dzania struktur\u0105 bazy danych w aplikacji Spring Boot. Cz\u0119\u015b\u0107 1<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/460907\/\">U\u017cycie Liquibase do zarz\u0105dzania struktur\u0105 bazy danych w aplikacji Spring Boot. Cz\u0119\u015b\u0107 2<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436994\/\">Liquibase i Maven<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/330662\/\">Podej\u015bcia do wersjonowania zmian w bazach danych<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/271719\/\">Spring MVC\/Security, REST, Hibernate, Liquibase uruchamiamy w dw\u00f3ch linijkach<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<p>Ponadto by\u0142a ju\u017c \u015bwietna artyku\u0142 na temat przydatnych wskaz\u00f3wek:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/179425\/\">U\u017cycie Liquibase bez b\u00f3lu g\u0142owy. 10 wskaz\u00f3wek z do\u015bwiadcze\u0144 realnej deweloperki<\/a><\/noindex><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"sovety\">Porady<\/h2>\n<p><\/p>\n<p>Chc\u0119 podzieli\u0107 si\u0119 swoimi wskaz\u00f3wkami i komentarzami, kt\u00f3re narodzi\u0142y si\u0119 w wyniku trudno\u015bci, b\u00f3lu i wysi\u0142ku przy rozwi\u0105zywaniu problem\u00f3w z migracj\u0105.<\/p>\n<p><\/p>\n<h3 id=\"1--pered-rabotoy-sleduet-oznakomitsya-s-razdelom-luchshih-praktik-na-saytehttpswwwliquibaseorgbestpracticeshtml-liquibase\">1. Przed przyst\u0105pieniem do pracy warto zapozna\u0107 si\u0119 z sekcj\u0105 najlepszych praktyk na <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">stronie<\/a><\/noindex> Liquibase<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/bestpractices.html\">Tam<\/a><\/noindex> opisano s\u0105 proste, ale bardzo wa\u017cne rzeczy, bez kt\u00f3rych korzystanie z biblioteki mo\u017ce znacz\u0105co utrudni\u0107 \u017cycie. Na przyk\u0142ad, niestrukturalne podej\u015bcie do zarz\u0105dzania changsetami pr\u0119dzej czy p\u00f3\u017aniej prowadzi do nieporozumie\u0144 i uszkodzonych migracji. Je\u015bli zmiany w strukturze bazy danych i logice us\u0142ug nie s\u0105 wprowadzane jednocze\u015bnie, istnieje du\u017ce prawdopodobie\u0144stwo, \u017ce doprowadzi to do b\u0142\u0119d\u00f3w w testach lub uszkodzenia \u015brodowiska. Ponadto, zalecenia dotycz\u0105ce korzystania z Liquibase na oficjalnej stronie zawieraj\u0105 punkt dotycz\u0105cy opracowywania i sprawdzania skrypt\u00f3w rollback wraz z podstawowymi skryptami migracji. A tak\u017ce w artykule <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/178665\/\">https:\/\/habr.com\/ru\/post\/178665\/<\/a><\/noindex> s\u0105 przyk\u0142ady kodu dotycz\u0105cego migracji i mechanizmu rollback. <\/p>\n<p><\/p>\n<h3 id=\"2-esli-nachali-ispolzovat-sredstva-migracii--ne-dopuskayte-manualnyh-ispravleniy-v-strukture-bazy\">2. Je\u015bli zacz\u0105\u0142e\u015b u\u017cywa\u0107 narz\u0119dzi do migracji \u2013 nie dokonuj r\u0119cznych poprawek w strukturze bazy.<\/h3>\n<p><\/p>\n<p>Jak m\u00f3wi\u0105: \u201eJeden raz Persil \u2014 zawsze Persil\u201d. Je\u015bli baza twojej aplikacji zacz\u0119\u0142a by\u0107 zarz\u0105dzana przez Liquibase \u2014 wszelkie r\u0119czne zmiany natychmiast prowadz\u0105 do niesp\u00f3jnego stanu, a poziom zaufania do changset\u00f3w staje si\u0119 r\u00f3wny zeru. Potencjalne ryzyko to kilka straconych godzin na przywracanie bazy, w najgorszym przypadku \u2014 uszkodzony serwer. Je\u015bli w twoim zespole jest DBA Architekt \u201estarej daty\u201d, cierpliwie i przemy\u015blanie wyja\u015bnij mu, jak \u017ale si\u0119 to sko\u0144czy, je\u015bli po prostu edytuje baz\u0119 wed\u0142ug w\u0142asnego uznania z u\u017cyciem SQL Developer. <\/p>\n<p><\/p>\n<h3 id=\"3-esli-chendzhset-uzhe-byl-zapushen-v-repozitoriy-izbegayte-redaktirovaniya\">3. Je\u015bli changset zosta\u0142 ju\u017c wprowadzony do repozytorium, unikaj edytowania.<\/h3>\n<p><\/p>\n<p>Je\u015bli inny programista zrobi\u0142 pull i zastosowa\u0142 changset, kt\u00f3ry nast\u0119pnie zostanie edytowany \u2014 na pewno wspomni o tobie ciep\u0142ym s\u0142owem, gdy napotka b\u0142\u0105d przy uruchamianiu aplikacji. Je\u015bli edytowanie changsetu w jakikolwiek spos\u00f3b przejdzie do \u015brodowiska deweloperskiego \u2014 trzeba b\u0119dzie uwa\u017ca\u0107 na pu\u0142apki hotfix\u00f3w. Istota problemu sprowadza si\u0119 do walidacji zmian na podstawie sumy kontrolnej \u2014 podstawowego mechanizmu Liquibase. Podczas edytowania kodu changsetu zmienia si\u0119 suma kontrolna. Edytowanie changset\u00f3w jest mo\u017cliwe tylko wtedy, gdy istnieje mo\u017cliwo\u015b\u0107 bez utraty danych przywr\u00f3cenia ca\u0142ej bazy od zera. W takim przypadku refaktoryzacja kodu SQL lub XML mo\u017ce wr\u0119cz u\u0142atwi\u0107 \u017cycie, czyni\u0105c migracje bardziej czytelnymi. Przyk\u0142adem mo\u017ce by\u0107 sytuacja, gdy na starcie aplikacji schemat pocz\u0105tkowej bazy danych zosta\u0142 uzgodniony w zespole. <\/p>\n<p><\/p>\n<h3 id=\"4--imey-proverennye-bekapy-baz-dannyh-esli-eto-vozmozhno\">4. Miej niezawodne kopie zapasowe baz danych, je\u015bli to mo\u017cliwe<\/h3>\n<p><\/p>\n<p>My\u015bl\u0119, \u017ce wszystko jest tutaj jasne. W przypadku, gdy migracja nie powiedzie si\u0119, wszystko mo\u017cna b\u0119dzie przywr\u00f3ci\u0107. W Liquibase istnieje narz\u0119dzie do wycofywania zmian, ale skrypty do wycofania r\u00f3wnie\u017c pisze sam programista, i mog\u0105 wyst\u0119powa\u0107 w nich problemy z tak\u0105 sam\u0105 prawdopodobno\u015bci\u0105, jak w skryptach g\u0142\u00f3wnego zestawu zmian. Oznacza to, \u017ce warto mie\u0107 kopie zapasowe w ka\u017cdym przypadku. <\/p>\n<p><\/p>\n<h3 id=\"5-ispolzuy-proverennye-bekapy-baz-dannyh-v-razrabotke-esli-eto-vozmozhno\">5. U\u017cywaj niezawodnych kopii zapasowych baz danych w rozwijaniu, je\u015bli to mo\u017cliwe<\/h3>\n<p><\/p>\n<p>Je\u015bli nie jest to sprzeczne z umowami i prywatno\u015bci\u0105, w bazie nie ma danych osobowych, a nie wa\u017cy ona jak dwa s\u0142o\u0144ca \u2014 przed zastosowaniem migracji na serwerach produkcyjnych mo\u017cna sprawdzi\u0107, jak to dzia\u0142a na maszynie dewelopera i zidentyfikowa\u0107 prawie 100% potencjalnych problem\u00f3w podczas migracji. <\/p>\n<p><\/p>\n<h3 id=\"6-obschaysya-s-drugimi-razrabotchikami-v-komande\">6. Komunikuj si\u0119 z innymi programistami w zespole<\/h3>\n<p><\/p>\n<p>W prawid\u0142owo zorganizowanym procesie tworzenia oprogramowania wszyscy w zespole wiedz\u0105, kto nad czym pracuje. W rzeczywisto\u015bci cz\u0119sto tak nie jest, dlatego, je\u015bli w ramach swojej zadania wprowadzasz zmiany w strukturze bazy danych, warto dodatkowo powiadomi\u0107 o tym ca\u0142y zesp\u00f3\u0142. Je\u015bli kto\u015b wprowadza zmiany r\u00f3wnolegle \u2014 powinni\u015bcie si\u0119 zorganizowa\u0107. Warto rozmawia\u0107 z kolegami tak\u017ce po zako\u0144czeniu pracy, nie tylko na pocz\u0105tku. Wiele potencjalnych problem\u00f3w z zestawami zmian mo\u017cna rozwi\u0105za\u0107 na etapie przegl\u0105du kodu. <\/p>\n<p><\/p>\n<h3 id=\"7-dumay-chto-delaesh\">7. My\u015bl, co robisz!<\/h3>\n<p><\/p>\n<p>To oczywista rada, kt\u00f3ra ma zastosowanie w ka\u017cdej sytuacji. Jednak wiele problem\u00f3w da\u0142oby si\u0119 unikn\u0105\u0107, gdyby programista raz jeszcze przeanalizowa\u0142, co robi i jakie to mo\u017ce mie\u0107 wp\u0142yw. Praca z migracjami zawsze wymaga dodatkowej uwagi i staranno\u015bci. <\/p>\n<p><\/p>\n<h2 id=\"lovushki\">Pu\u0142apki<\/h2>\n<p><\/p>\n<p>Zobaczmy teraz typowe pu\u0142apki, w kt\u00f3re mo\u017cna wpa\u015b\u0107, je\u015bli nie b\u0119dziesz stosowa\u0107 si\u0119 do powy\u017cszych rad, i co w takim razie robi\u0107?<\/p>\n<p><\/p>\n<h3 id=\"situaciya-1-dva-razrabotchika-pytayutsya-odnovremenno-dobavlyat-novye-chendzhsety\">Sytuacja 1. Dw\u00f3ch programist\u00f3w pr\u00f3buje jednocze\u015bnie doda\u0107 nowe zestawy zmian<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/20706fc970510bc06634fa001a4c7ceb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nWania i Petya chc\u0105 stworzy\u0107 zestaw zmian wersji 4, nie wiedz\u0105c o sobie nawzajem. Wprowadzili zmiany w strukturze bazy danych i wys\u0142ali pull request, z r\u00f3\u017cnymi plikami zestaw\u00f3w zmian. Nast\u0119pnie sugeruje si\u0119 nast\u0119puj\u0105cy mechanizm dzia\u0142ania:<\/p>\n<p><\/p>\n<h4 id=\"kak-reshat\">Jak rozwi\u0105za\u0107<\/h4>\n<p><\/p>\n<ol>\n<li>W jaki\u015b spos\u00f3b koledzy musz\u0105 si\u0119 um\u00f3wi\u0107, w jakiej kolejno\u015bci powinny i\u015b\u0107 ich zestawy zmian, niech b\u0119dzie, \u017ce zestaw Peti powinien by\u0107 zastosowany jako pierwszy. <\/li>\n<li>Kto\u015b musi umie\u015bci\u0107 drugi zestaw danych u siebie i oznaczy\u0107 changset Wasy wersj\u0105 5. Mo\u017cna to zrobi\u0107 poprzez Cherry Pick lub staranny merge. <\/li>\n<li>Po wprowadzeniu zmian nale\u017cy sprawdzi\u0107 poprawno\u015b\u0107 dokonanych dzia\u0142a\u0144.<br \/>\nFaktycznie, mechanizmy Liquibase pozwalaj\u0105 mie\u0107 w repozytorium dwa changsety wersji 4, wi\u0119c mo\u017cna zostawi\u0107 wszystko jak jest. Oznacza to, \u017ce b\u0119dziecie mieli po prostu dwa zmiany wersji 4 o r\u00f3\u017cnych nazwach. Przy takim podej\u015bciu w kolejnych wersjach bazy danych staje si\u0119 bardzo trudno si\u0119 orientowa\u0107. <\/li>\n<\/ol>\n<p><\/p>\n<p>Ponadto, Liquibase, jak dom hobbit\u00f3w, skrywa wiele tajemnic. Jedn\u0105 z nich jest klucz validCheckSum, kt\u00f3ry pojawi\u0142 si\u0119 w wersji 1.7 i pozwala okre\u015bli\u0107 poprawn\u0105 warto\u015b\u0107 sumy kontrolnej dla danego changsetu, niezale\u017cnie od tego, co jest zapisane w bazie danych. Dokumentacja <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/changeset.html\">https:\/\/www.liquibase.org\/documentation\/changeset.html<\/a><\/noindex> m\u00f3wi nast\u0119puj\u0105co:<\/p>\n<p><\/p>\n<blockquote><p>Dodaj sum\u0119 kontroln\u0105, kt\u00f3ra jest uznawana za wa\u017cn\u0105 dla tego zestawu zmian, niezale\u017cnie od tego, co jest zapisane w bazie danych. U\u017cywane g\u0142\u00f3wnie, gdy potrzebujesz zmieni\u0107 zestaw zmian i nie chcesz, aby wyst\u0105pi\u0142y b\u0142\u0119dy w bazach danych, na kt\u00f3rych ju\u017c dzia\u0142a\u0142 (niezalecana procedura).<\/p><\/blockquote>\n<p>Tak, taka procedura nie jest zalecana. Ale czasami silny jasny mag pos\u0142uguje si\u0119 tak\u017ce ciemnymi technikami. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-2-migraciya-kotoraya-zavisit-ot-dannyh\">Sytuacja 2. Migracja, kt\u00f3ra zale\u017cy od danych.<\/h3>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/31a6eebb55278c0631115bf16483c7b8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Za\u0142\u00f3\u017cmy, \u017ce nie masz mo\u017cliwo\u015bci u\u017cycia kopii zapasowych baz z \u017cywych serwer\u00f3w. Piotr stworzy\u0142 changset, sprawdzi\u0142 go lokalnie i z pe\u0142n\u0105 pewno\u015bci\u0105 swojej racji zrobi\u0142 pull request do dev. Lider projektu dla pewno\u015bci zapyta\u0142, czy Piotr to sprawdzi\u0142, a nast\u0119pnie zintegrowa\u0142. Ale wdro\u017cenie na serwerze dev spad\u0142o.<\/p>\n<p><\/p>\n<p>Faktycznie, to jest mo\u017cliwe i nikt nie jest na to ubezpieczony. Dzieje si\u0119 tak, gdy zmiany struktury tabel s\u0105 w jaki\u015b spos\u00f3b powi\u0105zane z konkretnymi danymi w BD. Oczywiste jest, \u017ce je\u015bli baza Piotra jest wype\u0142niona tylko danymi testowymi, mo\u017ce nie obejmowa\u0107 wszystkich problematycznych przypadk\u00f3w. Na przyk\u0142ad, przy usuwaniu tabeli okazuje si\u0119, \u017ce s\u0105 wpisy w innych tabelach powi\u0105zane z zapisami w usuwanej przez Foreign Key. Lub przy zmianie typu kolumny okazuje si\u0119, \u017ce nie 100% danych mo\u017ce zosta\u0107 przekszta\u0142conych na nowy typ. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-1\">Jak rozwi\u0105za\u0107<\/h4>\n<p><\/p>\n<ul>\n<li>Napisanie specjalnych skrypt\u00f3w, kt\u00f3re b\u0119d\u0105 stosowane jednorazowo w po\u0142\u0105czeniu z migracj\u0105 i przekszta\u0142ca\u0107 dane w odpowiedni spos\u00f3b. To og\u00f3lny spos\u00f3b rozwi\u0105zania problemu przenoszenia danych do nowych struktur ju\u017c po zastosowaniu migracji, ale co\u015b podobnego mo\u017ce by\u0107 r\u00f3wnie\u017c zastosowane przed, w szczeg\u00f3lnych przypadkach. Taki spos\u00f3b, oczywi\u015bcie, nie zawsze jest dost\u0119pny, poniewa\u017c edytowanie danych na \u017cywych serwerach mo\u017ce by\u0107 niebezpieczne i wr\u0119cz katastrofalne. <\/li>\n<li>Inny trudny spos\u00f3b polega na edytowaniu istniej\u0105cego changsetu. Problem polega na tym, \u017ce wszystkie bazy danych, w kt\u00f3rych by\u0142 on ju\u017c zastosowany w obecnej formie, b\u0119d\u0105 musia\u0142y by\u0107 przywr\u00f3cone. Jest ca\u0142kiem mo\u017cliwe, \u017ce ca\u0142y zesp\u00f3\u0142 backendowy b\u0119dzie musia\u0142 lokalnie uruchomi\u0107 bazy danych od zera. <\/li>\n<li>Najbardziej uniwersalnym sposobem jest przeniesienie problemu z danymi do \u015brodowiska dewelopera, odtwarzaj\u0105c t\u0119 sam\u0105 sytuacj\u0119 i dodanie nowego changsetu przed zepsutym, kt\u00f3ry pozwoli na obej\u015bcie problemu.<br \/>\n<img decoding=\"async\" alt=\"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z Liquibase\" src=\"\/wp-content\/uploads\/2020\/02\/b5d28a940a7a35b6cd7a819a8e68f027.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ul>\n<p><\/p>\n<p>Og\u00f3lnie im bardziej baza danych jest podobna do bazy z serwera produkcyjnego, tym mniejsze szanse, \u017ce problemy z migracjami b\u0119d\u0105 si\u0119 rozwija\u0107 daleko. I oczywi\u015bcie, zanim wy\u015blesz changset do repozytorium, warto kilka razy si\u0119 zastanowi\u0107, czy nie z\u0142amie on czego\u015b. <\/p>\n<p><\/p>\n<h3 id=\"situaciya-3-liquibase-nachinaet-primenyatsya-uzhe-posle-vyhoda-v-prodakshn\">Sytuacja 3. Liquibase zaczyna by\u0107 stosowane ju\u017c po wdro\u017ceniu do produkcji.<\/h3>\n<p><\/p>\n<p>Za\u0142\u00f3\u017cmy, \u017ce lider zespo\u0142u poprosi\u0142 Piotra o wprowadzenie Liquibase do projektu, jednak projekt jest ju\u017c w produkcji i istnieje ju\u017c struktura bazy.<\/p>\n<p><\/p>\n<p>W zwi\u0105zku z tym problem polega na tym, \u017ce na jakichkolwiek nowych serwerach lub maszynach deweloper\u00f3w dane z tych tabel musz\u0105 by\u0107 odtwarzane od zera, a ju\u017c istniej\u0105ce \u015brodowisko musi pozosta\u0107 w sp\u00f3jnym stanie, gotowym do przyjmowania nowych changset\u00f3w. <\/p>\n<p><\/p>\n<h4 id=\"kak-reshat-2\">Jak rozwi\u0105za\u0107<\/h4>\n<p><\/p>\n<p>Istnieje tutaj kilka sposob\u00f3w:<\/p>\n<p><\/p>\n<ul>\n<li>Pierwszy i najbardziej oczywisty \u2014 mie\u0107 oddzielny skrypt, kt\u00f3ry musi by\u0107 zastosowany r\u0119cznie przy inicjalizacji nowego \u015brodowiska. <\/li>\n<li>Drugi \u2014 mniej oczywisty, mie\u0107 migracj\u0119 Liquibase, kt\u00f3ra znajduje si\u0119 w innym kontek\u015bcie Liquibase i j\u0105 stosowa\u0107. Wi\u0119cej o kontek\u015bcie Liquibase mo\u017cna przeczyta\u0107 tutaj: <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/contexts.html\">https:\/\/www.liquibase.org\/documentation\/contexts.html<\/a><\/noindex>. Og\u00f3lnie rzecz bior\u0105c, to interesuj\u0105cy mechanizm, kt\u00f3ry mo\u017ce by\u0107 skutecznie stosowany, na przyk\u0142ad do testowania. <\/li>\n<li>Trzeci spos\u00f3b sk\u0142ada si\u0119 z kilku krok\u00f3w. Najpierw nale\u017cy stworzy\u0107 migracj\u0119 dla ju\u017c istniej\u0105cych tabel. Nast\u0119pnie musi ona zosta\u0107 zastosowana w jakim\u015b \u015brodowisku, a w ten spos\u00f3b zostanie uzyskany jej hash. Kolejnym krokiem jest zainicjowanie pustych tabel Liquibase na naszym niepustym serwerze, a do tabeli z histori\u0105 zastosowania change set\u00f3w mo\u017cna r\u0119cznie doda\u0107 wpis o \"jakoby zastosowanym\" change secie z ju\u017c istniej\u0105cymi w bazie zmianami. W ten spos\u00f3b na ju\u017c istniej\u0105cym serwerze historia rozpocznie si\u0119 od wersji 2, a wszystkie nowe \u015brodowiska b\u0119d\u0105 si\u0119 zachowywa\u0107 identycznie.<br \/>\n<img decoding=\"async\" alt=\"Jak nie strzeli\u0107 sobie w stop\u0119 korzystaj\u0105c z 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\">Sytuacja 4. Migracje staj\u0105 si\u0119 ogromne i nie zd\u0105\u017caj\u0105 si\u0119 wykona\u0107.<\/h3>\n<p><\/p>\n<p>Na pocz\u0105tku rozwoju us\u0142ugi, zazwyczaj, Liquibase jest u\u017cywany jako zewn\u0119trzna zale\u017cno\u015b\u0107, a wszystkie migracje s\u0105 przetwarzane przy starcie aplikacji. Jednak z czasem mo\u017cesz natkn\u0105\u0107 si\u0119 na nast\u0119puj\u0105ce przypadki:<\/p>\n<p><\/p>\n<ul>\n<li>Migracje staj\u0105 si\u0119 ogromne i trwaj\u0105 d\u0142ugo.<\/li>\n<li>Pojawia si\u0119 potrzeba migracji w rozproszonych \u015brodowiskach, na przyk\u0142ad, na kilku instancjach baz danych jednocze\u015bnie.<br \/>\nW takim przypadku zbyt d\u0142ugie zastosowanie migracji spowoduje timeout przy starcie aplikacji. Ponadto zastosowanie migracji dla ka\u017cdej instancji aplikacji z osobna mo\u017ce prowadzi\u0107 do tego, \u017ce r\u00f3\u017cne serwery b\u0119d\u0105 w niesynchronizowanym stanie. <\/li>\n<\/ul>\n<p><\/p>\n<h4 id=\"kak-reshat-3\">Jak rozwi\u0105za\u0107<\/h4>\n<p><\/p>\n<p>W takich przypadkach Tw\u00f3j projekt jest ju\u017c du\u017cy, by\u0107 mo\u017ce nawet dojrza\u0142y, a Liquibase zaczyna pe\u0142ni\u0107 rol\u0119 oddzielnego, zewn\u0119trznego narz\u0119dzia. Chodzi o to, \u017ce Liquibase jako biblioteka jest pakowana do pliku jar i mo\u017ce dzia\u0142a\u0107 zar\u00f3wno jako zale\u017cno\u015b\u0107 wewn\u0105trz projektu, jak i autonomicznie. <\/p>\n<p><\/p>\n<p>W trybie autonomicznym mo\u017cna powierzy\u0107 zastosowanie migracji Twojemu \u015brodowisku CI\/CD lub zaufanym r\u0119kom Twoich administrator\u00f3w system\u00f3w\/specjalist\u00f3w ds. wdro\u017ce\u0144. Wymagana b\u0119dzie komenda Liquibase. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/documentation\/command_line.html\">https:\/\/www.liquibase.org\/documentation\/command_line.html<\/a><\/noindex>. W takim trybie pojawia si\u0119 mo\u017cliwo\u015b\u0107 uruchomienia aplikacji dopiero po tym, jak wszystkie niezb\u0119dne migracje zosta\u0142y przeprowadzone.<\/p>\n<p><\/p>\n<h2 id=\"vyvod\">Wnioski<\/h2>\n<p><\/p>\n<p>W rzeczywisto\u015bci pu\u0142apek przy migracjach baz danych mo\u017ce by\u0107 znacznie wi\u0119cej, a wiele z nich wymaga kreatywnego podej\u015bcia. Wa\u017cne jest, aby zrozumie\u0107, \u017ce je\u015bli narz\u0119dzie jest u\u017cywane prawid\u0142owo, to wi\u0119kszo\u015b\u0107 tych pu\u0142apek mo\u017cna unikn\u0105\u0107. Osobi\u015bcie spotka\u0142em si\u0119 z ka\u017cd\u0105 z wymienionych problem\u00f3w w r\u00f3\u017cnych sytuacjach, a niekt\u00f3re z nich by\u0142y wynikiem moich b\u0142\u0119d\u00f3w. Z regu\u0142y zdarza si\u0119 to z braku uwagi, ale czasami \u2013 z powodu przest\u0119pczej niekompetencji w korzystaniu z narz\u0119dzia.<\/p>\n<p>\u0179r\u00f3d\u0142o: <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.1.1 - 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\/pl\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\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\/pl\/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\udd47Jak nie strzeli\u0107 sobie w stop\u0119, u\u017cywaj\u0105c Liquibase | ProHoster","description":"Nigdy tego nie by\u0142o, a oto znowu! W kolejnym projekcie postanowili\u015bmy u\u017cy\u0107 Liquibase od samego pocz\u0105tku, aby unikn\u0105\u0107 problem\u00f3w w przysz\u0142o\u015bci.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/kak-ne-vystrelit-sebe-v-nogu-ispolzuya-liquibase","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","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\/pl\/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\/pl\/wp-json\/wp\/v2\/posts\/70973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=70973"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/70973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/70974"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=70973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=70973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=70973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}