Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase

Ніколі не было, і вось зноў!

На чарговым праекце мы вырашылі выкарыстоўваць Liquibase з самага пачатку, каб пазбегнуць праблем у будучыні. Як аказалася, не ўсе маладыя члены каманды ўмеюць яго правільна выкарыстоўваць. Я правёў унутраны воркшоп, які затым вырашыў ператварыць у артыкул.

Артыкул уключае ў сябе карысныя парады і апісанне трох самых відавочных пастак, у якія можна патрапіць, працуючы з прыладамі міграцыі рэляцыйных баз дадзеных, у прыватнасці Liquibase. Разлічана на Java распрацоўшчыкаў ўзроўню Junior і Middle, для больш дасведчаных распрацоўшчыкаў можа быць цікавая для структурызацыі і паўтарэння таго, што, хутчэй за ўсё, ужо вядома.

Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase

Liquibase і Flyway – асноўныя канкуруючыя тэхналогіі для рашэння задач кантролю версій рэляцыйных структур у свеце Java. Першая з'яўляецца цалкам бясплатнай, на практыцы гушчару выбіраецца для выкарыстання менавіта яна, таму менавіта Liquibase абраны героем публікацыі. Тым не менш некаторыя з апісаных практык могуць быць універсальнымі, у залежнасці ад архітэктуры вашага дадатку.

Міграцыі рэляцыйных структур - гэта змушана які з'явіўся спосаб барацьбы са слабой гнуткасцю рэляцыйных сховішчаў дадзеных. У эпоху моды на ААП стыль працы з БД меў на ўвазе, што мы адзін раз апішам схему і не будзем яе больш чапаць. Але рэальнасць заўсёды такая, што ўсё мяняецца, і змены ў структуры табліц патрабуюцца дастаткова часта. Натуральна, працэс сам па сабе бывае балючы і непрыемны.

Не буду паглыбляцца ў апісанне тэхналогіі і інструкцыі па даданні бібліятэкі ў свой праект, на гэтую тэму было напісана дастаткова артыкулаў:

Акрамя таго, ужо быў выдатны артыкул на тэму карысных парадаў:

Саветы

Жадаю падзяліцца сваімі парадамі і каментарамі, якія нарадзіліся праз пот, кроў і боль рашэння праблем з міграцыяй.

1. Перад працай трэба азнаёміцца ​​з раздзелам лепшых практык на сайце Liquibase

Там апісаны простыя, але вельмі важныя рэчы, без якіх выкарыстанне бібліятэкі можа ўскладніць вам жыццё. Да прыкладу, неструктурны падыход да кіравання чэнджсетамі рана ці позна прывядзе да блытаніны і паламаных міграцый. Калі выкочваць якія залежаць сябар ад сябра змены структуры БД і логікі сэрвісаў не адначасова, гэта значыць вялікая верагоднасць, што гэта прывядзе да чырвоных тэстаў ці паламанаму асяроддзю. Акрамя таго, рэкамендацыі па выкарыстанні Liquibase на афіцыйным сайце змяшчаюць пункт пра распрацоўку і праверку rollback скрыптоў разам з асноўнымі скрыптамі міграцыі. Ну і ў артыкуле https://habr.com/ru/post/178665/ ёсць прыклады кода, які тычыцца міграцый і rollback механізму.

2. Калі пачалі выкарыстоўваць сродкі міграцыі - не дапускайце мануальных выпраўленняў у структуры базы

Як гаворыцца: "Адзін раз Persil - заўсёды Persil". Калі база вашага прыкладання пачала кіравацца сродкамі Liquibase - любыя ручныя змены маментальна прыводзяць да некансістэнтнага стану, і ўзровень даверу чэнджсетам становіцца роўны нулю. Патэнцыйныя рызыкі - некалькі выдаткаваных гадзін на аднаўленне базы, пры горшым раскладзе - забіты сервер. Калі ў вашай камандзе ёсць DBA Architect "старой загартоўкі", цярпліва і ўдумліва растлумачце яму, як усё будзе дрэнна, калі ён проста адрэдагуе базу па сваім разуменні з умоўнага SQL Developer.

3. Калі чэнджсэт ужо быў запушаны ў рэпазітар, пазбягайце рэдагавання

Калі іншы распрацоўшчык зрабіў pull і ўжыў ченджсет, які пасля будзе адрэдагаваны, - ён абавязкова памяне вас добрым словам, калі атрымае памылку пры старце прыкладання. Калі рэдагаванне ченджсета нейкім чынам працячэ ў дэвэлап — давядзецца ісці слізкай дарожкай хотфіксаў. Сутнасць праблемы ўпіраецца ў валідацыю змен па хэш-суме - асноўны механізм Liquibase. Пры рэдагаванні кода ченджсета змяняецца хэш-сума. Рэдагаванне чэнджсетаў магчыма толькі тады, калі прысутнічае магчымасць без страты дадзеных разгарнуць усю базу з нуля. У такім выпадку рэфактарынг SQL або XML кода можа, наадварот, палегчыць жыццё, зрабіць міграцыі больш чытэльнымі. Прыкладам можа быць сітуацыя, калі на старце дадатку схема зыходнай БД ўзгаднялася ўнутры каманды.

4. Май правераныя бэкапы баз дадзеных, калі гэта магчыма

Тут, думаю, усё зразумела. Калі раптам міграцыя прайшла няўдала, усё можна будзе вярнуць назад. У Liquibase ёсць прылада адкату змен, але скрыпты для адкату піша таксама сам распрацоўнік, і ў іх могуць быць праблемы з такой жа верагоднасцю, як і ў скрыптах асноўнага ченджсета. Гэта азначае, што перастрахоўвацца з бэкапамі карысна ў любым выпадку.

5. Выкарыстоўвай правераныя бэкапы баз дадзеных у распрацоўцы, калі гэта магчыма

Калі гэта не супярэчыць дамовам і privacy, у базе няма персанальных дадзеных, і яна не важыць як два сонца – перад ужываннем на жывых серверах міграцыі можна праверыць, як яно спрацуе на машыне распрацоўніка, і вылічыць амаль 100% патэнцыйных праблем пры міграцыі.

6. Май зносіны з іншымі распрацоўшчыкамі ў камандзе

У правільна арганізаваным працэсе распрацоўкі ўсё ў камандзе ведаюць, хто чым заняты. У рэальнасці часта гэта не так, таму, калі ў рамках сваёй задачы рыхтуеш змены ў структуры БД, пажадана дадаткова апавясціць аб гэтым усю каманду. Калі хтосьці робіць змены паралельна - вам варта акуратна арганізавацца. З калегамі варта размаўляць і па завяршэнні працы, не толькі на старце. Шмат патэнцыйных праблем з чэнджсетамі можа вырашыцца на этапе code review.

7. Думай, што робіш!

Здавалася б, відавочная рада, дастасавальная да любых сітуацый. Аднак многіх праблем удалося б пазбегнуць, калі б распрацоўшчык яшчэ раз прааналізаваў, што ён робіць і на што гэта можа паўплываць. Праца з міграцыямі заўсёды патрабуе дадатковай увагі і акуратнасці.

пасткі

Давайце зараз разгледзім тыповыя пасткі, у якія можна патрапіць, калі не прытрымлівацца парад вышэй, і што, уласна, рабіць-то?

Сітуацыя 1. Два распрацоўшчыкі спрабуюць адначасова дадаваць новыя чэнджсеты

Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase
Вася і Пеця жадаюць стварыць ченджсет версіі 4, не ведаючы сябар пра сябра. Яны зрабілі змены ў структуры БД, і выкацілі pull request, з рознымі файламі ченджсета. Далей прапануецца наступны механізм дзеянняў:

Як вырашаць

  1. Нейкім чынам калегі павінны дамовіцца, у якім парадку павінны ісці іх ченджсеты, дапусцім, Пецін павінен быць ужыты першы.
  2. Хтосьці адзін павінен падліць другі да сябе і пазначыць чэнджсет Васі версіяй 5. Гэта можа быць зроблена праз Cherry Pick або акуратны мердж.
  3. Пасля змен абавязкова трэба праверыць валіднасць зробленых дзеянняў.
    Насамрэч механізмы Liquibase дазволяць мець у рэпазітары два чэнджсэта версіі 4, таму можна пакінуць усё як ёсць. Гэта значыць, у вас проста будзе дзве змены версіі 4 з рознымі назвамі. Пры такім падыходзе пасля ў версіях базы дадзеных становіцца вельмі складана арыентавацца.

Акрамя таго, Liquibase, як дамы хобітаў, захоўвае ў сабе шмат сакрэтаў. Адным з іх з'яўляецца ключ validCheckSum, які з'явіўся з версіі 1.7 і дазваляе паказаць валіднае значэнне хэш-сумы для вызначанага чэнджсета па-за залежнасцю ад таго, што захоўваецца ў базе дадзеных. Дакументацыя https://www.liquibase.org/documentation/changeset.html кажа наступнае:

Add a checksum that is valided for this changeSet, regardless of what is stored in the database. Used primárne, keď budete potrebovať зміну зміни і не з'яўляцца errors thrown on databases on which it has already run (no no recommended procedure)

Так-так, такая працэдура не рэкамендуецца. Але часам моцны светлы чараўнік валодае і цёмнымі тэхнікамі.

Сітуацыя 2. Міграцыя, якая залежыць ад дадзеных

Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase

Дапусцім, у вас няма магчымасці выкарыстоўваць рэзервовыя копіі баз з жывых сервераў. Пеця стварыў чэнджсэт, праверыў яго лакальна і з поўнай упэўненасцю сваёй правасці зрабіў pull request у дэвэлап. Лід праекта на ўсялякі выпадак удакладніў, ці праверыў яго Пеця, і затым уліў. Але разгортванне на дэвэлап серверы ўпала.

Насамрэч такое магчыма, і ад гэтага ніхто не застрахаваны. Гэта адбываецца ў тым выпадку, калі мадыфікацыі структуры табліц нейкім чынам завязаны на канкрэтныя даныя з БД. Відавочна, што калі база Пеці запоўнена толькі тэставымі дадзенымі, то яна можа не пакрываць усе праблемныя кейсы. Напрыклад, пры выдаленні табліцы высвятляецца, што ёсць запісы ў іншых табліцах па Foreign Key, злучаныя з запісамі ў выдалянай. Ці пры змене тыпу калонкі высвятляецца, што не 100% дадзеных могуць быць пераўтвораны да новага тыпу.

Як вырашаць

  • Напісаць спецыяльныя скрыпты, якія будуць аднаразова прымяняцца разам з міграцыяй і прыводзіць даныя ў належны выгляд. Гэта агульны шлях вырашэння праблемы пераносу даных у новыя структуры ўжо пасля прымянення міграцый, але нешта падобнае можа быць прыменена і да, у прыватных выпадках. Такі шлях, вядома, не заўсёды даступны, бо рэдагаваць дадзеныя на жывых серверах можа быць небяспечна і нават пагібельна.
  • Іншы складаны шлях - адрэдагаваць наяўны ченджсет. Складанасць у тым, што ўсе БД, дзе ён у наяўным выглядзе ўжо быў ужыты, давядзецца аднаўляць. Цалкам магчыма, што ўся бэкэнд-каманда вымушана будзе лакальна накаціць БД з нуля.
  • І самы ўніверсальны шлях – перанос праблемы з дадзенымі на environment распрацоўніка з узнаўленнем той жа сітуацыі і даданне новага ченджсета, да зламанага, які дазволіць абыйсці праблему.
    Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase

У цэлым, чым больш база па складзе дадзеных падобная на базу прадакшн сервера, тым менш шанец, што праблемы з міграцыямі працякуць далёка. І, вядома, перш чым адправіць чэнджсэт у рэпазітар, варта некалькі разоў падумаць, ці не зламае ён што-небудзь.

Сітуацыя 3. Liquibase пачынае прымяняцца ўжо пасля выхаду ў прадакшн

Выкажам здагадку, тымлід папрасіў Пецю падлучыць у праект Liquibase, аднак праект ужо ў прадакшэне і маецца ўжо існая структура базы.

Адпаведна, праблема складаецца ў тым, каб на любых новых серверах ці машынах распрацоўнікаў дадзеныя табліцы павінны ўзнаўляцца з нуля, а ўжо існае асяроддзе павінна застацца ў кансістэнтным стане, быўшы гатовай прымаць новыя чэнджсеты.

Як вырашаць

Тут таксама ёсць некалькі шляхоў:

  • Першы і самы відавочны - мець асобны скрыпт, які павінен быць ужыты ўручную пры ініцыялізацыі новага асяроддзя.
  • Другі - менш відавочны, мець Liquibase міграцыю, якая знаходзіцца ў іншым Liquibase Context, і прымяняць яе. Падрабязней пра Liquibase Context можна прачытаць тут: https://www.liquibase.org/documentation/contexts.html. У цэлым гэта цікавы механізм, які можа быць паспяхова ўжыты, напрыклад, для тэставання.
  • Трэці шлях складаецца з некалькіх крокаў. Спачатку павінна быць створана міграцыя для ўжо наяўных табліц. Затым яна павінна быць ужытая на нейкім environment'е і такім чынам будзе атрымана яе хэш-сума. Наступным крокам варта праініцыялізаваць на нашым не пустым серверы пустыя Liquibase табліцы, і ў табліцу з гісторыяй ужывання ченджсетаў можна мануальна пакласці запіс аб "нібыта ўжытым" ченджсеты з ужо наяўнымі ў базе зменамі. Такім чынам, на ўжо існуючым сэрвэры адлік гісторыі пойдзе з версіі 2, а ўсе новыя environments будуць паводзіць сябе ідэнтычна.
    Як не стрэліць сабе ў нагу, выкарыстоўваючы Liquibase

Сітуацыя 4. Міграцыі становяцца вялізнымі і не паспяваюць выконвацца

У пачатку распрацоўкі сэрвісу, як правіла, Liquibase выкарыстоўваецца як знешняя залежнасць, і ўсе міграцыі апрацоўваюцца пры старце дадатку. Аднак з цягам часу вы можаце наткнуцца на наступныя кейсы:

  • Міграцыі становяцца вялізнымі і выконваюцца доўгі час.
  • З'яўляецца неабходнасць міграцыі ў размеркаваных асяроддзях, дапусцім, на некалькіх інстансах сервераў БД адначасова.
    У такім разе занадта доўгае ўжыванне міграцый прывядзе да таймаўту пры старце прыкладання. Акрамя таго, ужыванне міграцый для кожнага інстанса прыкладання асобна можа прывесці да таго, што розныя серверы апынуцца ў ня сінхронным стане.

Як вырашаць

У такіх выпадках ваш праект ужо вялікі, магчыма нават паўналетні, і Liquibase пачынае выступаць як асобная вонкавая прылада. Справа ў тым, што Liquibase як бібліятэка збіраецца ў jar файл, і можа працаваць як залежнасць усярэдзіне праекту, так і аўтаномна.

У аўтаномным рэжыме можна ўскласці прымяненне міграцый на вашу CI / CD асяроддзе або на моцныя плечы вашых сістэмных адміністратараў спецыялістаў па разгортванні. Для гэтага спатрэбіцца камандны радок Liquibase https://www.liquibase.org/documentation/command_line.html. У такім рэжыме з'яўляецца магчымасць рабіць запуск прыкладання ўжо пасля таго, як усе неабходныя міграцыі былі праведзены.

Выснова

Насамрэч пастак пры працы з міграцыямі БД можа быць значна большым, і многія з іх патрабуюць творчага падыходу. Важна разумець, што калі правільна выкарыстоўваць прыладу, то большасць з гэтых пастак атрымаецца пазбегнуць. Канкрэтна мне даводзілася ў розных відах сутыкацца з усімі пералічанымі праблемамі, а некаторыя з іх былі вынікам маіх вушакоў. У асноўным гэта адбываецца, вядома, па няўважлівасці, але часам - з прычыны злачыннага няўмення выкарыстоўваць інструмент.

Крыніца: habr.com

Дадаць каментар