portaldacalheta.pt
  • Основен
  • Пъргав
  • Иновация
  • Тенденции
  • Back-End
Наука За Данни И Бази Данни

Миграции на база данни: Превръщане на гъсеници в пеперуди



Потребителите не се интересуват какво има в софтуера, който използват; само че работи гладко, безопасно и ненатрапчиво. Разработчиците се стремят да направят това и един от проблемите, които се опитват да решат, е как да гарантират, че хранилището на данни е в състояние, подходящо за текущата версия на продукта. Софтуерът се развива и моделът му на данни може също да се промени с течение на времето, например да се коригира дизайнерски грешки . За да усложните проблема допълнително, може да имате редица тестови среди или клиенти, които мигрират към по-нови версии на продукта с различни темпове. Не можете просто да документирате структурата на магазина и какви манипулации са необходими, за да използвате лъскавата нова версия от една гледна точка.

Миграции на база данни: Превръщане на гъсеници в пеперуди



Веднъж се присъединих към проект с няколко бази данни със структури, които бяха актуализирани при поискване, директно от разработчиците. Това означаваше, че няма очевиден начин да се разбере какви промени трябва да се приложат за мигриране на структурата към най-новата версия и изобщо няма концепция за версиране! Това беше по време на ерата преди DevOps и в днешно време ще се счита за пълна бъркотия. Решихме да разработим инструмент, който да се използва за прилагане на всяка промяна към дадената база данни. Имаше миграции и ще документира промени в схемата. Това ни направи уверени, че няма да има случайни промени и състоянието на схемата ще бъде предвидимо.



В тази статия ще разгледаме как да приложим миграции на релационни бази данни и как да преодолеем съпътстващите проблеми.



колко github страници мога да имам

На първо място, какво представляват миграциите на бази данни? В контекста на тази статия, a миграция е набор от промени, които трябва да бъдат приложени към база данни. Създаването или пускането на таблица, колона или индекс са често срещани примери за миграции. Формата на вашата схема може да се промени драстично с течение на времето, особено ако разработката е започнала, когато изискванията все още са неясни. И така, в продължение на няколко етапа по пътя към издание, вашият модел на данни ще се е развил и може да се е превърнал в напълно различен от това, което беше в самото начало. Миграциите са само стъпки към целевото състояние.

За да започнем, нека изследваме какво имаме в нашата кутия с инструменти, за да избегнем преоткриването на това, което вече е направено добре.



Инструменти

Във всеки широко използван език има библиотеки, които помагат за улесняване на миграцията на бази данни. Например в случая с Java популярните опции са Liquibase и Flyway . Ще използваме Liquibase повече в примери, но концепциите се отнасят за други решения и не са обвързани с Liquibase.

Защо да си правим труда да използвам отделна библиотека за миграция на схеми, ако някои ORM вече предоставят възможност за автоматично надграждане на схема и да я накарат да съответства на структурата на картографираните класове? На практика такива автоматични миграции правят само прости промени в схемата, например създаване на таблици и колони и не могат да правят потенциално разрушителни неща като отпадане или преименуване на обекти на база данни. Така че неавтоматичните (но все пак автоматизирани) решения обикновено са по-добър избор, защото сте принудени сами да опишете логиката на мигриране и знаете какво точно ще се случи с вашата база данни.



Също така е много лоша идея да смесвате автоматизирани и ръчни модификации на схеми, защото може да създадете уникални и непредсказуеми схеми, ако ръчните промени се прилагат в грешен ред или изобщо не се прилагат, дори ако се изискват. След като инструментът бъде избран, използвайте го, за да приложите всички миграции на схеми.

Типични миграции на база данни

Типичните миграции включват създаване на последователности, таблици, колони, първични и външни ключове, индекси и други обекти на база данни. За най-често срещаните видове промени Liquibase предоставя отделни декларативни елементи за описване на това, което трябва да се направи. Би било твърде скучно да се чете за всяка тривиална промяна, поддържана от Liquibase или други подобни инструменти. За да получите представа как изглеждат наборите от промени, разгледайте следния пример, където създаваме таблица (декларациите на XML пространство от имена са пропуснати за краткост):



createTable

Както можете да видите, списъкът с промени е набор от набори от промени и наборите от промени се състоят от промени. Прости промени като UPDATE product SET code = 'new_' || code могат да се комбинират за изпълнение на по-сложни миграции; например, да предположим, че трябва да актуализирате кода на продукта за всички продукти. Лесно може да се постигне със следната промяна:

createTable

Ефективността ще пострада, ако имате милиони продукти. За да ускорим миграцията, можем да я пренапишем в следните стъпки:



  1. Създайте нова таблица за продукти с PRODUCT_TMP, точно както видяхме по-рано. На този етап е по-добре да създадете възможно най-малко ограничения. Нека назовем новата таблица PRODUCT_TMP.
  2. Население INSERT INTO ... SELECT ... с SQL под формата на sql използвайки addNotNullConstraint промяна.
  3. Създайте всички необходими ограничения (addUniqueConstraint, addForeignKeyConstraint, createIndex) и индекси (PRODUCT).
  4. Преименувайте PRODUCT_BAK таблица към нещо като renameTable. Liquibase може да го направи с PRODUCT_TMP.
  5. Преименуване PRODUCT до renameTable (отново, използвайки PRODUCT_BAK).
  6. По желание премахнете dropTable с ... .

Разбира се, по-добре е да избягвате подобни миграции, но е добре да знаете как да ги приложите, в случай че се натъкнете на един от онези редки случаи, когато имате нужда от него.

Ако смятате, че XML, JSON или YAML са твърде странни за задачата да опишат промените, тогава просто използвайте обикновен SQL и използвайте всички специфични функции на доставчика на база данни. Също така можете да внедрите всякаква потребителска логика в обикновена Java.



Начинът, по който Liquibase ви освобождава от писането на действително специфичен за базата данни SQL може да доведе до прекомерна увереност, но не бива да забравяте и за странностите на вашата целева база данни; например, когато създавате външен ключ, индексът може или не може да бъде създаден, в зависимост от използваната конкретна система за управление на база данни. В резултат на това може да се окажете в неприятна ситуация. Liquibase ви позволява да посочите, че набор от промени трябва да се изпълнява само за определен тип база данни, например PostgreSQL, Oracle или MySQL. Това прави възможно използването на едни и същи набори от агностични доставчици за различни бази данни и за други набори от промени, използвайки синтаксис и характеристики, специфични за доставчика. Следният набор от промени ще бъде изпълнен само ако се използва база данни на Oracle:

IDX__

Освен Oracle, Liquibase поддържа няколко други бази данни извън кутията.

Именуване на обекти на база данни

Всеки обект на база данни, който създавате, трябва да бъде наименуван. Не се изисква изрично да предоставяте име за някои видове обекти, например за ограничения и индекси. Но това не означава, че тези обекти няма да имат имена; техните имена така или иначе ще бъдат генерирани от базата данни. Проблемът възниква, когато трябва да се обърнете към този обект, за да го пуснете или промените. Затова е по-добре да им дадете изрични имена. Но има ли правила относно това кои имена да се дават? Отговорът е кратък: Бъдете последователни; например, ако сте решили да назовете индекси по този начин: CODE, тогава индекс за гореспоменатите IDX_PRODUCT_CODE колоната трябва да бъде наречена DATABASECHANGELOG.

Конвенциите за именуване са изключително противоречиви, така че няма да се допуснем да даваме изчерпателни инструкции тук. Бъдете последователни, спазвайте конвенциите на вашия екип или проект или просто ги измислете, ако няма такива.

Организиране на набори от промени

Първото нещо, за което трябва да вземете решение, е къде да съхранявате наборите промени. По принцип има два подхода:

  1. Съхранявайте наборите за промени с кода на приложението. Удобно е да го направите, защото можете да ангажирате и преглеждате наборите от промени и кода на приложението заедно.
  2. Дръжте наборите за промени и кода на приложението отделно , например в отделни хранилища на VCS. Този подход е подходящ, когато моделът от данни се споделя в няколко приложения и е по-удобно да се съхраняват всички набори от промени в специално хранилище и да не се разпръскват в множество хранилища, където кодът на приложението живее.

Където и да съхранявате наборите от промени, обикновено е разумно да ги разделите в следните категории:

  1. Независими миграции, които не засягат работещата система. Обикновено е безопасно да създавате нови таблици, последователности и т.н., ако разгърнатото в момента приложение все още не ги знае.
  2. Модификации на схемата, които променят структурата на магазина , например добавяне или пускане на колони и индекси. Тези промени не трябва да се прилагат, докато все още се използва по-стара версия на приложението, тъй като това може да доведе до заключвания или странно поведение поради промени в схемата.
  3. Бързи миграции, които вмъкват или актуализират малки количества данни. Ако се разполагат множество приложения, наборите от тази категория могат да бъдат изпълнени едновременно, без да се влошава производителността на базата данни.
  4. Потенциално бавни миграции, които вмъкват или актуализират много данни. Тези промени е по-добре да се прилагат, когато не се изпълняват други подобни миграции.

графично представяне на четирите категории

как да създадете консултативен съвет

Тези набори от миграции трябва да се изпълняват последователно, преди да се внедри по-нова версия на приложение. Този подход става още по-практичен, ако системата е съставена от няколко отделни приложения и някои от тях използват една и съща база данни. В противен случай си струва да отделите само тези набори от промени, които биха могли да бъдат приложени, без да се засягат работещите приложения, а останалите набори от промени могат да бъдат приложени заедно.

За по-прости приложения, пълният набор от необходими миграции може да се приложи при стартиране на приложението. В този случай всички набори от промени попадат в една категория и се изпълняват при всяко инициализиране на приложението.

На какъвто и етап да е избран да се приложи миграция, струва си да се спомене, че използването на една и съща база данни за множество приложения може да доведе до заключвания, когато се прилагат миграции. Liquibase (както много други подобни решения) използва две специални таблици за записване на своите метаданни: DATABASECHANGELOGLOCK и runOnChange='true'. Първият се използва за съхраняване на информация за приложени набори от промени, а вторият за предотвратяване на едновременни миграции в същата схема на базата данни. Така че, ако няколко приложения трябва да използват една и съща схема на базата данни по някаква причина, по-добре е да използвате имена, които не са по подразбиране за таблиците с метаданни, за да се избегнат заключвания.

Сега, когато структурата на високо ниво е ясна, трябва да решите как да организирате наборите от промени във всяка категория.

организация за промяна на извадка

Това до голяма степен зависи от конкретните изисквания за приложение, но следните точки обикновено са разумни:

  1. Съхранявайте регистрите на промените, групирани по версии на вашия продукт. Създайте нова директория за всяко издание и поставете в нея съответните файлове на промените. Имате root root дневник и включва дневници на промени, които съответстват на версии. В дневниците за промени на версията, включете други дневници с промени, съдържащи тази версия.
  2. Имайте конвенция за именуване на файлове с променливи и идентификатори на набори от промени - и я следвайте, разбира се.
  3. Избягвайте наборите от промени с много промени. Предпочитайте множество набори от промени пред един дълъг набор от промени.
  4. Ако използвате съхранени процедури и трябва да ги актуализирате, помислете за използването на createTable атрибут на набора от промени, в който се добавя тази съхранена процедура. В противен случай всеки път, когато се актуализира, ще трябва да създадете нов набор от промени с нова версия на съхранената процедура. Изискванията варират, но често е приемливо да не се проследява такава история.
  5. Помислете за смачкване на излишни промени преди обединяване на разклонения на функции. Понякога се случва, че в клон на функция (особено в дълготраен) по-късно наборите промени променят промените, направени в по-ранни набори промени. Например можете да създадете таблица и след това да решите да добавите още колони към нея. Струва си да добавите тези колони към първоначалните context='test' промяна, ако този клон на функцията все още не е обединен с основния клон.
  6. Използвайте същите дневници за промени, за да създадете тестова база данни. Ако се опитате да го направите, скоро може да разберете, че не всеки набор от промени е приложим за тестовата среда или че са необходими допълнителни набори от промени за тази специфична тестова среда. С Liquibase този проблем се решава лесно с помощта контексти . Просто добавете test атрибут към наборите от промени, които трябва да бъдат изпълнени само с тестове, и след това инициализирайте Liquibase с rollback контекстът е активиран.

Въртене назад

Подобно на други подобни решения, Liquibase поддържа мигрираща схема „нагоре“ и „надолу“. Но бъдете предупредени: Отмяна на миграциите може да не е лесно и не винаги си струва усилията. Ако сте решили да поддържате отмяна на миграции за вашето приложение, бъдете последователни и го правете за всеки набор от промени, който трябва да бъде отменен. С Liquibase отмяната на набора от промени се извършва чрез добавяне на createTable таг, който съдържа промени, необходими за извършване на връщане назад. Обмислете следния пример:

addColumn

Изричното връщане тук е излишно, защото Liquibase ще извърши същите действия за връщане. Liquibase може автоматично да върне повечето от поддържаните видове промени, например createIndex, DATABASECHANGELOG или DATABASECHANGELOG

Оправяне на миналото

Никой не е съвършен и всички грешим. Някои от тях могат да бъдат открити твърде късно, когато вече са приложени развалени промени. Нека да проучим какво би могло да се направи, за да спасим деня.

Ръчно актуализирайте базата данни

Включва бъркане с DATABASECHANGELOG и вашата база данни по следните начини:

  1. Ако искате да коригирате лоши набори от промени и да ги изпълните отново:
    • Премахване на редове от MD5SUM които съответстват на наборите от промени.
    • Премахнете всички странични ефекти, които са били въведени от наборите от промени; напр. възстановяване на таблица, ако е била изпусната.
    • Коригирайте лошите набори от промени.
    • Стартирайте миграции отново.
  2. Ако искате да коригирате лоши набори от промени, но пропуснете да ги прилагате отново:
    • Актуализация NULL чрез задаване на MD5SUM стойност на полето до runOnChange='true' за онези редове, които съответстват на лошите набори от промени.
    • Ръчно поправете грешката в базата данни. Например, ако е добавена колона с грешен тип, издайте заявка за модифициране на нейния тип.
    • Коригирайте лошите набори от промени.
    • Стартирайте миграции отново. Liquibase ще изчисли новата контролна сума и ще я запази в context. Коригираните набори от промени няма да се пускат отново.

Очевидно е лесно да се правят тези трикове по време на разработката, но става много по-трудно, ако промените се прилагат към множество бази данни.

дружество с ограничена отговорност c корпорация

Напишете коригиращи набори от промени

На практика този подход обикновено е по-подходящ. Може би се чудите, защо просто не редактирате оригиналния набор от промени? Истината е, че зависи от това какво трябва да се промени. Liquibase изчислява контролна сума за всеки набор от промени и отказва да приложи нови промени, ако контролната сума е нова за поне един от приложените по-рано набори от промени. Това поведение може да бъде персонализирано на база на промяна, като се посочи runOnChange атрибут. Контролната сума не се засяга, ако промените предпоставки или незадължителни атрибути на промяна (context, context='graveyard-changesets-never-run' и др.).

Сега, може би се чудите, как в крайна сметка коригирате наборите с грешки?

  1. Ако искате тези промени да продължат да се прилагат за нови схеми, просто добавете коригиращи набори от промени. Например, ако е добавена колона с грешен тип, модифицирайте нейния тип в новия набор от промени.
  2. Ако искате да се преструвате, че тези лоши набори от промени никога не са съществували, направете следното:
    • Премахнете наборите от промени или добавете changeSetExecuted атрибут със стойност, гарантираща, че никога повече няма да се опитате да приложите миграции с такъв контекст, например
    • Добавете нови набори от промени, които или ще върнат грешно направеното, или ще го поправят. Тези промени трябва да се прилагат само ако са били приложени лоши промени. Тя може да бъде постигната с предварителни условия, като например
      |_+_|
      . Не забравяйте да добавите коментар, обясняващ защо го правите.
    • Добавете нови набори от промени, които модифицират схемата по правилния начин.

Както виждате, поправянето на миналото е възможно, макар че не винаги може да е лесно.

Смекчаване на нарастващите болки

С напредването на възрастта на вашето приложение, неговият дневник на промени също се разраства, натрупвайки всяка промяна на схемата по пътя. Това е по дизайн и в това няма нищо по същество лошо. Дългите дневници на промените могат да бъдат съкратени чрез редовно смачкване на миграции, например след пускане на всяка версия на продукта. В някои случаи това би направило инициализирането на нова схема по-бързо.

илюстрация на смачкани дневници

Скуоширането не винаги е тривиално и може да предизвика регресии, без да носи много ползи. Друга чудесна възможност е използването на база данни за семена, за да се избегне изпълнението на всички набори от промени. Той е много подходящ за тестване на среди, ако трябва да имате база данни, подготвена възможно най-бързо, може би дори с някои тестови данни. Може да го възприемете като форма на смачкване за набори от промени: В даден момент (например след пускане на друга версия) правите дъмп на схемата. След възстановяване на сметището прилагате миграции както обикновено. Ще бъдат приложени само нови промени, защото по-старите вече са били приложени преди да направите сметката; следователно те бяха възстановени от сметището.

илюстрация на база данни за семена

Заключение

Умишлено избягвахме да се впуснем по-дълбоко в характеристиките на Liquibase, за да доставим кратка и точна статия, фокусирана върху развиващите се схеми като цяло. Надяваме се, че е ясно какви ползи и проблеми води до автоматизираното прилагане на миграции на схеми на бази данни и доколко всичко това се вписва в Култура на DevOps . Важно е дори добрите идеи да не се превръщат в догма. Изискванията варират и като инженери на бази данни , нашите решения трябва да насърчават придвижването на продукта напред, а не просто да се придържаме към препоръките на някой в ​​интернет.

Разбиране на основите

Какво е значението на схемата в базата данни?

Схемата на базата данни описва как са организирани данните в базата данни.

Каква е разликата между база данни и схема?

Схемата е част от база данни. Базата данни обикновено се състои от една или повече схеми. Също така е доста често да се нарича СУБД база данни. Обикновено от контекста става ясно дали говорим за контейнера за данни или за системата, която управлява този контейнер.

Какво е пример за схема?

Ако изграждате приложение за управление на обиколки, неговата схема на база данни ще съдържа обекти като авиокомпания, полет или град. Освен дефинирани от потребителя схеми, СУБД обикновено има „информационна схема“, която може да се използва за заявки за настройките и метаданните.

как да стартирате фонд за търсене

Какви са различните видове бази данни?

Освен релационни бази данни съществуват обектни, ориентирани към документи и йерархични бази данни.

Има ли начин за ускоряване на заявката?

Можете да оптимизирате бавна заявка, като я преструктурирате или промените схемата. СУБД обикновено може да ви даде план за изпълнение и да помогне да познаете какво забавя вашата заявка (напр. Неизползване на индекси или избиране на твърде много данни в подзаявки). В PostgreSQL можете да използвате EXPLAIN или EXPLAIN ANALYZE, за да разберете какво не е наред.

Каква е схемата в PostgreSQL?

В PostgreSQL може да имате няколко бази данни в един и същ клъстер; схемата е структурен елемент на базата данни. Това е контейнерът за таблици, изгледи, процедури и др. Схемите могат да се считат за директории в базата данни, но схемите не могат да съдържат други схеми.

Дълбок поглед върху JSON срещу XML, част 1: Историята на всеки стандарт

Технология

Дълбок поглед върху JSON срещу XML, част 1: Историята на всеки стандарт
Анализиране на ефекта от отрицателните лихвени проценти в пет икономики

Анализиране на ефекта от отрицателните лихвени проценти в пет икономики

Финансови Процеси

Популярни Публикации
ApeeScape разраства връзката си с Amazon Web Services, за да продължи да стимулира икономиката на талантите
ApeeScape разраства връзката си с Amazon Web Services, за да продължи да стимулира икономиката на талантите
Въведение в теорията и сложността на изчислимостта
Въведение в теорията и сложността на изчислимостта
Ръководство стъпка по стъпка за проектиране на персонализирани илюстрации без предишен опит
Ръководство стъпка по стъпка за проектиране на персонализирани илюстрации без предишен опит
Обяснено оптимизиране на ефективността на Magento
Обяснено оптимизиране на ефективността на Magento
Изчерпателно ръководство за дизайн на известия
Изчерпателно ръководство за дизайн на известия
 
Малки данни, големи възможности
Малки данни, големи възможности
Достъпност в мрежата: Защо стандартите W3C често се игнорират
Достъпност в мрежата: Защо стандартите W3C често се игнорират
Бъдещето на UX е нашето човечество
Бъдещето на UX е нашето човечество
Предвиждащ дизайн: Как да създадем магически потребителски опит
Предвиждащ дизайн: Как да създадем магически потребителски опит
Въведение в Python Microservices с Nameko
Въведение в Python Microservices с Nameko
Популярни Публикации
  • llc c or s corp
  • предназначение на таблото за настроение
  • забавни C++ програми
  • Пример за смесено целочислено линейно програмиране
  • рамкова архитектура на обектния модел на страницата
Категории
  • Пъргав
  • Иновация
  • Тенденции
  • Back-End
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt