Kunagi ei ole olnud, ja nüüd jälle!
Uuel projektil otsustasime alustada Liquibase'i kasutamist, et tulevikus probleeme vältida. Selgus, et mitte kõik noored meeskonnaliikmed ei oska seda õigesti kasutada. Ma korraldasin sisemise töötuba, mille otsustasin hiljem artikliks ümber kirjutada.
Artikkel sisaldab kasulikke näpunäiteid ja kirjeldust kolmest kõige silmatorkavamast lõksust, millesse võib sattuda, töötades relatsiooniliste andmebaaside migreerimise tööriistadega, sealhulgas Liquibase'iga. Suunatud Java arendajatele tasemel Junior ja Middle, võivad kogenumad arendajad leida seda huvitavaks struktuuri ja korduse mõttes, mis on tõenäoliselt juba tuttav.

Liquibase ja Flyway on peamised konkureerivad tehnoloogiad relatsiooniliste struktuuride versioonihalduse probleemide lahendamiseks Java maailmas. Esimene on täiesti tasuta ja seda valitakse praktikas sagedamini, seetõttu on Liquibase valitud selle väljaande peategelaseks. Siiski võivad mõned kirjeldatud praktikad olla universaalsed, sõltuvalt teie rakenduse arhitektuurist.
Relaatsioonistruktuuride migreerimine on sunnitud meetod, et võidelda relatsiooniliste andmehoidlate madala paindlikkuse vastu. OOP ajastul eeldas andmebaaside kasutamine, et me kirjeldame skeemi üks kord ja ei puutu sellesse enam. Kuid reaalsus on alati selline, et kõik muutub, ning tabelite struktuuris on muutused piisavalt tihti vajalikud. Loomulikult on see protsess sageli valulik ja ebameeldiv.
Ei hakka süvenema tehnoloogia ja juhiste kirjeldamisse, kuidas biblioteeki oma projektis kasutada; selle teema kohta on juba piisavalt artikleid kirjutatud:
Lisaks on juba olnud suurepärane artikkel kasulike nõuannete teemal:
Nõuanded
Soovin jagada oma nõuandeid ja kommentaare, mis on sündinud probleemide lahendamise kaudu, mis on seotud migreerimisega, verd, higi ja valu.
1. Enne töö alustamist tutvuge parimate praktikate jaotisega aadressil Liquibase
on kirjeldatud lihtsaid, kuid väga olulisi asju, ilma milleta raamatukogu kasutamine võib teile elu keerulisemaks muuta. Näiteks struktuuri mittesüsteemne lähenemine muudetud kogumite haldamisele toob varem või hiljem segadust ja katkenud migratsioone. Kui sõltuvad andmebaasi struktuuri ja teenuste loogika muutused ei toimu samaaegselt, on suur tõenäosus, et see toob kaasa punased testid või rikutud keskkonna. Lisaks sisaldavad Liquibase'i kasutamise soovitused ametlikul saidil punkti rollback skriptide väljatöötamise ja kontrollimise kohta koos põhiskriptidega migratsiooniks. Ja artiklis on näited koodist, mis puudutavad migratsioone ja rollback mehhanismi.
2. Kui olete hakanud kasutama migratsiooni tööriistu, vältige käsitsi parandusi andmebaasi struktuuris.
Nagu öeldakse: "Üks kord Persil — alati Persil". Kui teie rakenduse andmebaasi hakkab haldama Liquibase, siis igasugune käsitsi muudatus toob koheselt kaasa järjepidevuse rikkumise ning muudatuste usaldusväärsus langeb nulli. Potentsiaalne oht on mitu tundi, mis kulub andmebaasi taastamiseks, halvemal juhul — serveri rike. Kui teie meeskonnas on „vana kooli“ DBA arhitekt, siis selgitage talumatult ja põhjalikult, kui halvasti läheb, kui ta lihtsalt toimetab andmebaasi oma äranägemise järgi, kasutades navigeeritavat SQL arendajat.
3. Kui muudatuskomplekt on juba hoidlasse pushitud, vältige redigeerimist
Kui mõni teine arendaja teeb pull'i ja rakendab muutuste komplekti, mida hiljem muudetakse, siis kindlasti meenutab ta sind head sõnaga, kui ta saab rakenduse käivitamisel vea. Kui muutuste komplekti muutmine jõuab kuidagi arendusse, tuleb minna libedale teele kiirparanduste tegemiseks. Probleemi olemus seisneb muudatuste valideerimise kontrollimises rakendades hash-summat — see on Liquibase'i peamine mehhanism. Muutuste komplekti koodi muutmisel muutub hash-summa. Muutuste komplekti redigeerimine on võimalik ainult siis, kui on olemas võimalus ilma andmete kaota, käivitada kogu andmebaas nullist. Sellisel juhul võib SQL-i või XML-i koodi refaktoreerimine vastupidi elu lihtsamaks teha, muutes migreerimised loetavamaks. Näiteks võib välja tuua olukorra, kus rakenduse käivitamisel oli algse andmebaasi skeem meeskonnas kooskõlastatud.
4. Hoia kontrollitud andmebaasi varukoopiaid, kui see on võimalik
Siin on kõik selge. Kui migratsioon peaks ebaõnnestuma, saab kõik alati tagasi pöörata. Liquibase'il on muudatuste tagasisööte tööriist, kuid tagasipöördumisskriptid kirjutab samuti arendaja ning nendes võivad esineda probleemid sama tõenäosusega kui põhichanget set'i skriptides. See tähendab, et varukoopiate tegemine on kasulik igal juhul.
5. Kasuta arenduses usaldusväärseid andmebaasi varukoopiaid, kui see on võimalik.
Kui see ei ole lepingutega ja privaatsusega vastuolus, andmebaasis ei ole isikuandmeid ning see ei kaalu nagu kaks päikest — enne eluserveritel migratsiooni rakendamist saab kontrollida, kuidas see arendaja masinas töötab, ja tuvastada peaaegu 100% potentsiaalsed probleemid migratsiooni ajal.
6. Suhtle meeskonna teiste arendajatega.
Korrektselt korraldatud arendusprotsessis teavad kõik meeskonnas, kes millega tegeleb. Kuid reaalsuses pole see sageli nii, seetõttu, kui oma ülesande raames valmistad ette muudatusi andmebaasi struktuuris, on soovitatav teavitada sellest kogu meeskonda. Kui keegi teeb muudatusi samal ajal — tuleks ettevaatlikult korraldada. Kolleegidega tasub suhelda ka pärast töö valmimist, mitte ainult alguses. Paljusid potentsiaalseid probleeme chengset'idega saab lahendada code review etapis.
7. Mõtle, mida teed!
Tundub iseenesestmõistetav soovitus, mis kehtib igas olukorras. Siiski oleks paljusid probleeme saanud vältida, kui arendaja oleks veel kord analüüsinud, mida ta teeb ja millist mõju see võib avaldada. Migratsioonide töötlemine nõuab alati täiendavat tähelepanu ja hoolikust.
Küünesed
Vaatame nüüd tüüpilisi küüsi, kuhu võite sattuda, kui ei järgita ülaltoodud soovitusi, ja mida tegelikult teha?
Situatsioon 1. Kaks arendajat püüavad samal ajal uusi chengset'e lisada

Vassil ja Petja soovivad luua versiooni 4 muudatusetappide komplekti, teadmata üksteisest. Nad on teinud muudatusi andmebaasi struktuuris ja esitanud pull requesti erinevate muudatusfailidega. Järgmine tegevusmehhanism on nagu järgmine:
Kuidas lahendada
- Kolleegid peavad kuidagi kokku leppima, millises järjekorras nende muudatusetapid peaksid käima, hüpoteetiliselt peaks Petja muudatus olema esimesena kasutusele võetud.
- Keegi peab oma muudatustele lisama teise ja tähistama Vassili muudatust versiooniga 5. Seda saab teha kas Cherry Picki või ettevaatliku ühendamise kaudu.
- Pärast muudatusi tuleb kindlasti kontrollida tehtud tegevuste kehtivust.
Tegelikult võimaldavad Liquibase mehhanismid hoida hoidlas kahte versiooni 4 muudatusetappide komplekti, seega võib kõik jätta nii, nagu on. Teisisõnu, teil on lihtsalt kaks versiooni 4 muudatust erinevate nimedega. Sellise lähenemisega muutub hiljem andmebaasi versioonides navigeerimine väga keeruliseks.
Lisaks sellele sisaldab Liquibase, nagu hobbitite kodu, palju saladusi. Üks neist on võtme validCheckSum, mis ilmus versiooniga 1.7 ja võimaldab määrata kehtiva hash-summa väärtuse konkreetse muudatuskomplekti jaoks sõltumata sellest, mis andmebaasis talletatakse. Dokumentatsioon ütleb järgmist:
Lisa kontrollsumma, mida peetakse selle muudatuskomplekti jaoks kehtivaks, sõltumata sellest, mis andmebaasis on talletatud. Peamiselt kasutatakse olukordades, kus pead muutma muudatuskomplekti ja ei soovi, et andmebaasides, kus see on juba käinud, tekiks vigu (see pole soovitatav protseduur).
Jah, selline protseduur ei ole soovitatav. Kuid mõnikord valdab tugev heledaid nõidu ka tumedaid tehnikaid.
Situation 2. Migration that depends on data.

Oletame, et sul pole võimalik kasutada varukoopiaid elavatelt serveritelt. Peeter lõi muudatuskomplekti, kontrollis seda kohaliku arenduse käigus ja tegi täieliku usaldusega pull-requesti dev-keskkonda. Projekti juht küsis igaks juhuks, kas Peeter on selle üle kontrollinud, ja seejärel liitis. Kuid juurutamine dev-serveris kukkus läbi.
Tegelikult on see võimalik ja sellest keegi ei pääse. See juhtub siis, kui tabelite struktuuri muutmine on mingil moel seotud andmetega andmebaasis. On ilmne, et kui Petja andmebaas on täidetud ainult testandmetega, siis võib see mitte katta kõiki probleemseid juhtumeid. Näiteks, kui tabel kustutatakse, võib selguda, et teistes tabelites on Foreign Key seosed, mis on seotud kustutatavate kirjetega. Või kui veeru tüüp muutub, võib avastada, et kõik andmed ei pruugi uude tüüpi konverteeritavad olla.
Kuidas lahendada
- Kirjutada spetsiaalsed skriptid, mis rakenduvad ühekordselt koos migreerimisega ja viivad andmed nõutud vormi. See on üldine tee andmete edastamise probleemide lahendamiseks uutesse struktuuridesse juba pärast migreerimiste rakendamist, kuid midagi sellist võib rakendada ka enne, erandlike juhtumite korral. Selline tee ei pruugi siiski alati kergesti kätte saada, kuna andmete redigeerimine elus serverites võib olla ohtlik ja isegi hukatuslik.
- Teine keeruline tee on redigeerida olemasolevat muudatuskomplekti. Probleem on selles, et kõik andmebaasid, kus see olemasolevas vormis juba rakendatud on, tuleb taastada. On täiesti võimalik, et kogu backend-meeskond peab kohalikult andmebaasi nullist üles seadma.
- Ja kõige universaalsem tee on andmeprobleemi ümber tõstmine arendaja keskkonda, luues sama olukorra ja lisades uue muudatuskomplekti, kuni katkise, mis võimaldab probleemi vältida.

Üldiselt, mida rohkem andmete koosseis on sarnane tootmisserveri andmebaasile, seda väiksem on tõenäosus, et migratsiooniprobleemid ulatuvad kaugele. Ja loomulikult, enne kui saadate muudatuskomplekti ladustamisele, tasub paar korda mõelda, kas see ei riku midagi.
Situatsioon 3. Liquibase hakkab rakenduma juba pärast tootmisse minekut
Oletame, et meeskonnajuhataja palus Petjal projektis Liquibase käivitada, kuid projekt on juba tootmises ja olemasolev andmebaasi struktuur on juba olemas.
Seega on probleem selles, et igasugustes uutes serverites või arendajate masinates tuleb nende tabelite andmed luua algusest peale, samas kui juba olemasolev keskkond peab jääma konsistentseks ja valmis uute muudatuste vastuvõtmiseks.
Kuidas lahendada
Siin on mitmeid lähenemisviise:
- Esimene ja kõige ilmsem lahendus on omada eraldi skripti, mida tuleb käsitsi rakendada uue keskkonna käivitamisel.
- Teine, vähem ilmne lahendus, on kasutada Liquibase'i migratsiooni, mis asub teises Liquibase'i kontekstis, ja rakendada seda. Rohkem teavet Liquibase'i konteksti kohta saab lugeda siit: . Üldiselt on see huvitav mehhanism, mida saab edukalt kasutada näiteks testimiseks.
- Kolmas tee koosneb mitmest sammust. Esiteks peab olema loodud migreerimine juba olemasolevatele tabelitele. Seejärel tuleb see rakendada mingisuguses keskkonnas ja sel moel saadakse selle hash-summa. Järgmine samm on alustada meie mitte-tühjal serveril tühjade Liquibase tabelite loomist, ja ajalooliste muudatuste tabelisse saab käsitsi lisada kirje "nagu oleks rakendatud" muudatusest koos juba andmebaasis olemasolevate muudatustega. Nii hakkab ajaloo arvestus olemasoleval serveril minema versioonist 2, samas kui kõik uued keskkonnad toimivad samamoodi.

Situatsioon 4. Migratsioonid muutuvad tohutuks ja ei jõua läbi viia
Teenuse arendamise alguses kasutatakse tavaliselt Liquibase't välise sõltuvusena, ja kõik migratsioonid töödeldakse rakenduse käivitamisel. Kuid aja jooksul võite kohtuda järgmiste juhtumitega:
- Migratsioonid muutuvad tohutuks ja kestavad pikka aega.
- Tekkib vajadus migratsiooniks jaotatud keskkondades, näiteks samal ajal mitmes andmebaasi serveri instantsis.
Sel juhul võib migratsioonide liiga pikaajaline rakendamine viia rakenduse käivitamisel ajutiseks katkestamiseks. Lisaks võib migratsioonide rakendamine iga rakenduse instantsi eraldi põhjustada erinevate serverite sünkroonimata olekuid.
Kuidas lahendada
Sellistes olukordades on teie projekt juba suur, võib-olla isegi täiskasvanu eas, ja Liquibase hakkab toimima kui eraldi väline tööriist. Asi on selles, et Liquibase koguneb mooduliks jar failiks ning võib töötada nii sõltuvusena projekti sees kui ka iseseisvalt.
Iseseisvas režiimis saab migratsioonide rakendamise ülesande usaldada teie CI/CD keskkonnale või teie süsteemiadministraatorite kindlatele õlgadele. Selleks on vajalik Liquibase käsurea kasutamine . Sellises režiimis on võimalus käivitada rakendus juba pärast kõigi vajalike migratsioonide sooritamist.
Kokkuvõte
Tegelikult võib andmebaasi migratsioonide käigus olla palju rohkem lõkse ja paljusid neist tuleb loominguliselt käsitleda. Oluline on mõista, et õige tööriista kasutamise korral on enamik neist lõksudest vältimatud. Ma olen isiklikult kohtunud kõikide loetletud probleemidega, mõned neist olid ka minu enda eksimuste tagajärg. Peamiselt tekib see loomulikult hooletuse tõttu, kuid mõnel juhul ka tööriista kuritarvitamise tõttu.
Allikas: habr.com


