Nikdy to nebylo, a přesto znovu!
V dalším projektu jsme se rozhodli použít Liquibase od začátku, abychom v budoucnu předešli problémům. Jak se ukázalo, ne všichni mladí členové týmu vědí, jak ho správně používat. Uskutečnil jsem interní workshop, který jsem se rozhodl proměnit v článek.
Článek obsahuje užitečné rady a popis tří nejzřejmějších nástrah, do kterých se můžete dostat při práci s nástroji pro migraci relačních databází, zejména s Liquibase. Je určen pro Java vývojáře na úrovni Junior a Middle, pro zkušenější vývojáře může být zajímavý pro strukturalizaci a opakování toho, co pravděpodobně už vědí.

Liquibase a Flyway jsou hlavní soutěžící technologie pro řešení úkolů verzování relačních struktur ve světě Java. První je zcela bezplatná a ve skutečnosti je častěji vybírána pro použití, proto byl právě Liquibase zvolen hrdinou publikace. Nicméně některé z popsaných praktik mohou být univerzální, v závislosti na architektuře vaší aplikace.
Migrace relačních struktur je nevyhnutelně vzniklý způsob boje se slabou flexibilitou relačních datových skladů. V éře módy na OOP se styl práce s DB předpokládal tak, že jednou popíšeme schema a nebudeme ji více měnit. Ale realita je vždy taková, že se vše mění, a změny ve struktuře tabulek jsou potřeba docela často. Samozřejmě, že proces sám o sobě může být bolestivý a nepříjemný.
Nebudu se zde hlouběji zabývat popisem technologie a instrukcemi pro přidání knihovny do vašeho projektu, na toto téma bylo napsáno dost článků:
Kromě toho již byl skvělý článek na téma užitečných rad:
Rady
Chci se podělit o své rady a komentáře, které vznikly skrze pot, krev a bolest při řešení problémů s migrací.
1. Před prací se doporučuje ознакомиться s částí nejlepších praktik na Liquibase
sú popísané jednoduché, ale veľmi dôležité veci, bez ktorých používanie knižnice môže skomplikovať váš život. Napríklad, neštruktúrovaný prístup k správe changsetov skôr či neskôr povedie k zmätku a nefunkčným migráciám. Ak sa závislé zmeny štruktúry DB a logiky služieb nevydávajú súčasne, existuje veľká pravdepodobnosť, že to povedie k červeným testom alebo nefunkčnému prostrediu. Okrem toho, odporúčania na používanie Liquibase na oficiálnej stránke obsahujú bod o vývoji a kontrole rollback skriptov spolu so základnými skriptmi migrácie. A v článku nájdete príklady kódu týkajúceho sa migrácií a rollback mechanizmu.
2. Ak začnete používať nástroje migrácie - nedovoľte manuálne opravy v štruktúre databázy
Ako sa hovorí: „Raz Persil — navždy Persil“. Ak vaša databáza aplikácie začala byť spravovaná nástrojmi Liquibase — akékoľvek ručné zmeny okamžite vedú k nekonzistentnému stavu a úroveň dôvery v changsety klesá na nulu. Potenciálne riziká — niekoľko strávených hodín na obnovu databázy, v najhoršom prípade — zničený server. Ak má vaša tím DBA Architekta „starej školy“, trpezlivo a zamyslene mu vysvetlite, ako zle to skončí, ak jednoducho upraví databázu podľa svojho uváženia z podmieneného SQL Developer.
3. Ak bol changset už odoslaný do repozitára, vyhnite sa úpravám
Ak iný vývojár urobil pull a uplatnil changset, ktorý sa neskôr upraví, — určite vás spomenie v dobrom, keď dostane chybu pri spustení aplikácie. Ak sa úprava changsetu akýmkoľvek spôsobom prepustí do vývoja — bude potrebné ísť klzkou cestou hotfixov. Podstata problému spočíva vo validácii zmien podľa hash sumy — hlavný mechanizmus Liquibase. Pri úprave kódu changsetu sa zmení hash suma. Úpravy changsetov sú možné iba vtedy, ak existuje možnosť bez straty dát rozvinúť celú databázu od nuly. V takom prípade môže refaktoring SQL alebo XML kódu, naopak, uľahčiť život a spraviť migrácie čitateľnejšími. Príkladom môže byť situácia, keď bola pri štarte aplikácie schéma počiatočnej DB dohodnutá v rámci tímu.
4. Maj mať overené zálohy databáz, ak je to možné
Tu je asi všetko jasné. V prípade, že migrácia sa z nejakého dôvodu nevydarí, všetko sa dá vrátiť späť. V Liquibase existuje nástroj na vrátenie zmien, ale skripty na vrátenie píše tiež sám vývojár, a v týchto skriptoch môžu byť problémy s rovnakou pravdepodobnosťou ako v skriptoch hlavného changsetu. To znamená, že je užitočné mať zálohy pre istotu.
5. Používaj overené zálohy databáz vo vývoji, ak je to možné
Ak to nie je v rozpore zmluvami a ochranou osobných údajov, v databáze nie sú žiadne osobné údaje a nie je to také ťažké ako dve slnka — pred použitím migrácie na živých serveroch je možné skontrolovať, ako to funguje na vývojárskom stroji a takmer 100 % odhadnúť potenciálne problémy pri migrácii.
6. Komunikuj s ostatnými vývojármi v tíme
V správne organizovanom procese vývoja všetci v tíme vedia, kto na čom pracuje. V praxi to však často nie je tak, a preto, ak pripravuješ zmeny v štruktúre databázy v rámci svojej úlohy, je dobré informovať o tom celý tím. Ak niekto robí zmeny paralelne — mali by ste sa organizovať opatrne. S kolegami je dobré komunikovať aj po dokončení práce, nielen na začiatku. Mnoho potenciálnych problémov s changsetmi sa môže vyriešiť počas kódu kontroly.
7. Premýšľaj, čo robíš!
Zdalo by sa, že ide o samozrejmú radu, ktorú je možné uplatniť vo všetkých situáciách. Mnohé problémy by sa však dali predísť, ak by si vývojár ešte raz analyzoval, čo robí a aký to môže mať dopad. Práca s migráciami vždy vyžaduje osobitnú pozornosť a opatrnosť.
Pasce
Teraz sa pozrime na typické pasce, do ktorých sa dá spadnúť, ak sa nedodržiavajú vyššie uvedené rady, a čo vlastne robiť?
Situácia 1. Dvaja vývojári sa snažia súčasne pridať nové changsety

Václav a Peter chcú vytvoriť changset verzie 4, aniž by o sebe vedeli. Urobili zmeny v štruktúre databázy a vytvorili pull request s rôznymi súbormi changsetu. Nasleduje navrhnutý mechanizmus akcií:
Ako riešiť
- Niez akýmkoľvek spôsobom by sa mali kolegovia dohodnúť, v akom poradí by mali ísť ich changsety, predpokladajme, že Petrov by mal byť aplikovaný ako prvý.
- Jeden človek by mal pridať druhý k sebe a označiť changset Vašou verziou 5. To sa môže uskutočniť prostredníctvom Cherry Pick alebo starostlivého merge.
- Po zmenách je nevyhnutné skontrolovať validitu vykonaných akcií.
V skutočnosti mechanizmy Liquibase umožňujú mať v repozitári dva changsety verzie 4, takže môžete nechať všetko tak, ako je. To znamená, že jednoducho budete mať dve zmeny verzie 4 s rôznymi názvami. Pri tomto prístupe sa neskôr vo verziách databázy stáva veľmi ťažké sa orientovať.
Okrem toho, Liquibase, ako dom hobitov, skrýva mnoho tajomstiev. Jedným z nich je kľúč validCheckSum, ktorý sa objavil vo verzii 1.7 a umožňuje uviesť platnú hodnotu hash sumy pre konkrétny changset, bez ohľadu na to, čo je uložené v databáze. Dokumentácia hovorí nasledovné:
Pridajte checksum, ktorá sa považuje za platnú pre tento changSet, bez ohľadu na to, čo je uložené v databáze. Používa sa najmä vtedy, keď potrebujete zmeniť changSet a nechcete, aby sa na databázach, na ktorých už bežal, vyskytli chyby (toto sa neodporúča).
Áno, táto procedúra sa neodporúča. Ale niekedy mocný biely mág ovláda aj temné techniky.
Situácia 2. Migrácia, ktorá závisí od údajov.

Predpokladajme, že nemáte možnosť používať zálohy databáz z živých serverov. Peťa vytvoril changset, skontroloval ho lokálne a s plnou istotou svojej pravdy urobil pull request do develop. Vedúci projektu pre každú istotu skontroloval, či to Peťa skontroloval, a potom ho zlúčil. Ale nasadenie na develop serveri zlyhalo.
V skutočnosti to možné je a nikto nie je tomu chránený. K tomu dochádza v prípade, že modifikácie štruktúry tabuliek sú nejakým spôsobom viazané na konkrétne údaje z databázy. Je jasné, že ak je Peťova databáza zaplnená len testovacími údajmi, nemusí pokrývať všetky problémové prípady. Napríklad pri odstránení tabuľky sa zistí, že existujú záznamy v iných tabuľkách podľa Foreign Key, ktoré sú spojené so záznamami v odstraňovanej. Alebo pri zmene typu stĺpca sa zistí, že nie 100% údajov môže byť prevedených na nový typ.
Ako riešiť
- Napísať špeciálne skripty, ktoré budú jednokrát aplikované spolu s migráciou a upravia dáta do požadovanej podoby. Toto je všeobecná cesta k riešeniu problému s prenášaním dát do nových štruktúr už po aplikácii migrácií, ale niečo podobné sa môže aplikovať aj predtým, v špeciálnych prípadoch. Takáto cesta však samozrejme nie je vždy dostupná, pretože úprava dát na živých serveroch môže byť nebezpečná, a dokonca katastrofálna.
- Iná zložitá cesta — upraviť existujúci changset. Zložitostí je to, že všetky DB, kde bol vo svojom aktuálnom znení už aplikovaný, bude treba obnoviť. Je celkom možné, že celý backend tím bude nútený lokálne naštartovať DB od nuly.
- A najuniverzálnejšia cesta — preniesť problém s dátami na prostredie vývojára s reprodukciou tej istej situácie a pridanie nového changsetu, ktorý dovoľuje obísť problém pred tým, ktorý je zlomený.

Celkovo, čím viac je databáza po zložení dát podobná databáze produkčného servera, tým menšia je šanca, že problémy s migráciami prejdú ďaleko. A samozrejme, predtým, než sa pošle changset do repozitára, stojí za to niekoľkokrát premyslieť, či to niečo nerozbije.
Situácia 3. Liquibase sa začína aplikovať už po vydaní do produkcie.
Predpokladajme, že tímový líder požiadal Peta, aby pripojil do projektu Liquibase, avšak projekt už je v produkcii a existuje už existujúca štruktúra databázy.
Podľa toho je problém v tom, že na akýchkoľvek nových serveroch alebo strojoch vývojárov sa dáta tabuliek musia znovu vytvoriť od nuly, a už existujúce prostredie musí zostať v konzistentnom stave, pripravené prijímať nové changsety.
Ako riešiť
Existuje tu niekoľko ciest:
- Prvá a najzrejmejšia — mať samostatný skript, ktorý by mal byť aplikovaný ručne pri inicializácii nového prostredia.
- Druhá — menej zrejmá, mať migráciu Liquibase, ktorá sa nachádza v inom Liquibase kontexte a aplikovať ju. Podrobnejšie o Liquibase kontexte si môžete prečítať tu: . Celkovo ide o zaujímavý mechanizmus, ktorý môže byť úspešne aplikovaný, napríklad na testovanie.
- Tretí prístup pozostáva z niekoľkých krokov. Najprv musí byť vytvorená migrácia pre už existujúce tabuľky. Potom musí byť aplikovaná na nejakom prostredí a týmto spôsobom sa získa jej hash suma. Ďalším krokom je inicializovať na našom neprázdnom serveri prázdne tabuľky Liquibase a do tabuľky s históriou aplikovania changsetov môžeme manuálne vložiť záznam o „akoby aplikovanom“ changsete s už existujúcimi zmenami v databáze. Takto na už existujúcom serveri začne história od verzie 2 a všetky nové prostredia sa budú správať identicky.

Situácia 4. Migrácie sa stávajú obrovskými a nestíhajú sa vykonávať.
Na začiatku vývoja služby sa zvyčajne Liquibase používa ako externá závislosť a všetky migrácie sa spracovávajú pri štarte aplikácie. Avšak s časom sa môžete stretnúť s nasledujúcimi situáciami:
- Migrácie sa stávajú obrovskými a vykonávajú sa dlhý čas.
- Objavuje sa potrebnosť migrovať v distribuovaných prostrediach, povedzme, na niekoľkých inštanciách serverov DB súčasne.
V takom prípade príliš dlhé aplikovanie migrácií povedie k timeoutu pri štarte aplikácie. Okrem toho aplikovanie migrácií pre každú inštanciu aplikácie osobitne môže viesť k tomu, že rôzne servery sa ocitnú v nesynchronizovanom stave.
Ako riešiť
V takýchto prípadoch je váš projekt už veľký, možno dokonca dospelý, a Liquibase začína vystupovať ako samostatný externý nástroj. Faktom je, že Liquibase ako knižnica je zabalená do jar súboru a môže pracovať ako závislosť v rámci projektu, tak aj samostatne.
V samostatnom režime môžete preniesť aplikovanie migrácií na vaše CI/CD prostredie alebo na silné plecia vašich systémových administrátorov, špecialistov na nasadzovanie. Na to potrebujete príkazový riadok Liquibase. . V takom režime vzniká možnosť spustiť aplikáciu už po tom, čo boli vykonané všetky potrebné migrácie.
Záver
Skutočne existuje oveľa viac pascí pri práci s migráciami databáz a mnohé z nich si vyžadujú kreatívny prístup. Je dôležité chápať, že ak nástroj správne využijete, väčšinu týchto pascí dokážete obísť. Osobne som sa stretol so všetkými uvedenými problémami na rôznych úrovniach, a niektoré z nich boli výsledkom mojich chýb. Väčšinou sa to deje samozrejme z nepozornosti, ale niekedy aj kvôli kriminálnej nešikovnosti pri používaní nástroja.
Zdroj: habr.com


