
Në këtë artikull, do të shpjegojmë se si të zgjidhni problemet e përputhshmërisë së bazave të të dhënave gjatë procesit të deplojes. Do të tregojmë se çfarë mund të ndodhi me aplikacionet tuaja në prodhim nëse provoni të kryeni deplojnë pa përgatitje të mëparshme. Pastaj, do të kalojmë përmes fazave të ciklit të jetës së aplikacionit, të cilat janë të nevojshme për të pasur kohë të mirë për zero (shënim: vazhdimi — zero downtime). Rezultati i operacioneve tona do të jetë aplikimi i modifikimit të papërshtatshëm të bazës së të dhënave në një mënyrë që është përshtatshme për prapavijën.
Nëse dëshironi të merrni një pasqyrë të shembujve të kodit nga artikulli, mund t'i gjeni në .
Hyrje
Zero downtime deployment
Çfarë është kjo mistere zero downtime deployment? Можно сказать, это когда ваше приложение развернуто так, что вы можете успешно вводить новую версию приложения на продакшн, в то время как пользователь не замечает его недоступности. С точки зрения пользователя и компании, это наилучший из возможных сценариев деплоя, поскольку таким образом можно вводить новые функции и устранять ошибки без перебоев в работе.
Si ta arrijmë këtë? Ka disa mënyra, ja një prej tyre:
- deployoni versionin nr. 1 të shërbimit tuaj
- kryeni migrimin e bazës së të dhënave
- deployoni versionin nr. 2 të shërbimit tuaj paralelisht me versionin nr. 1
- sa herë që të shihni se versioni nr. 2 funksionon siç duhet, hiqni versionin nr. 1
- kaluar!
E lehtë, apo jo? Fatkeqësisht, nuk është aq e thjeshtë, dhe ne do ta shqyrtojmë më vonë. Tani, le të shqyrtojmë një proces tjetër të zakonshëm të deplojes — redhen blu jeshile.
A keni dëgjuar ndonjëherë për ? С Cloud Foundry это чрезвычайно легко сделать. Просто гляньте на , ku e përshkruajmë këtë më në detaje. Duke bërë një përmbledhje të shkurtër, le të përmbledhim se si të kryejmë blue green deployment:
- sigurohuni që të keni dy kopje të kodit tuaj produksion (“blu” dhe “jeshile”);
- drejtoni gjithë trafikun në ambientin blu, dmth. që adresat URL të produksionit të tregojnë aty;
- deployoni dhe testoni të gjitha ndryshimet e aplikacionit në ambientin jeshil;
- kini adresat URL nga blu në ambientin jeshil
Blue green deployment — është një qasje që ju lejon të introduktoni lehtësisht funksionalitete të reja, pa u shqetësuar që prodhimi do të dështojë. Kjo lidhet me faktin se edhe nëse diçka ndodh, mund ta riktheheni lehtësisht në ambientin e mëparshëm, thjesht duke ‘ndryshuar ndriçimin’.
Pas leximit të gjithë më sipër, mund të pyesni: Çfarë lidhjeje ka zero downtime me blue green deployment?
Epo, kanë shumë të përbashkëta, pasi mbështetjeja e dy kopjeve të të njëjtit ambient kërkon përpjekje të dyfishta për mirëmbajtjen e tyre. Kjo është arsyeja pse disa ekipe, siç thotë , ndjekin një variacion të këtij qasjes:
një variant tjetër është përdorimi i të njëjtës bazë të të dhënave, duke e krijuar kalimin blu-jeshil për shtresat web dhe domain. Në një qasje të tillë, bazat e të dhënave shpesh mund të bëhen problem, veçanërisht kur duhet të ndryshoni skemën e saj për të mbështetur një version të ri të softuerit.
Dhe këtu arrijmë në problemin kryesor të këtij artikulli. Baza e të dhënave. Le të heqim një herë tjetër një vështrim në këtë frazë.
kryeni migrimin e bazës së të dhënave.
Tani duhet t’i bëni vetes pyetjen — çfarë ndodh nëse ndryshimi i bazës së të dhënave është përshtatshëm? A nuk do të prishë versionin tim të parë të aplikacionit? Në fakt, pikërisht kjo do të ndodhte...
Prandaj, edhe pse ka përfitime të mëdha zero downtime / blue green deployment, kompanitë tendencojnë të ndjekin procesin më të sigurt për deplojen e aplikacioneve të tyre:
- përgatitni një paketë me versionin e ri të aplikacionit
- ndaloni aplikacionin që është duke funksionuar
- në të njëjtën kohë ekzekutoni skriptet për migrimin e bazës së të dhënave
- depononi dhe ç aktivizoni versionin e ri të aplikacionit
Në këtë artikull, do të përshkruajmë në detaje se si mund të punoni me bazën e të dhënave dhe kodin për të shfrytëzuar përfitimet e zero downtime deployment.
Problemet me bazën e të dhënave
Nëse keni një aplikacion pa gjendje, i cili nuk ruan asnjë të dhënë në bazën e të dhënave, mund të merrni zero downtime deployment menjëherë. Fatkeqësisht, shumica e softuerëve duhet të ruajnë të dhëna diku. Kjo është arsyeja pse duhet të mendoni mirë para se të bëni një ndryshim në skemë. Para se të thellohemi në detaje se si të ndryshoni skemën në mënyrë që të mund të kryhet deploy pa ndërprerje, le të përqendrohemi së pari në skemën e menaxhimit të versioneve.
Skema e menaxhimit të versioneve
Në këtë artikull, do të përdorim si një mjet për menaxhimin e versioneve (shënim: flasim për migrime të bazës së të dhënave). Natyrisht, gjithashtu do të shkruajmë një aplikacion Spring Boot, i cili ka mbështetje të integruar për Flyway dhe do të kryejë migrimin e skemës gjatë konfigurimit të kontekstit të aplikacionit. Duke përdorur Flyway, mund të ruani skriptet e migrimit në dosjen e projekteve tuaja (me default në classpath:db/migration). Këtu mund të shihni një shembull të tillë të skedarëve të migrimit
└── db
└── migration
├── V1__init.sql
├── V2__Add_surname.sql
├── V3__Final_migration.sql
└── V4__Remove_lastname.sqlNë këtë shembull, ne shohim 4 skenare migrimi, të cilat, nëse nuk janë përfunduar më parë, do të kryhen një pas një kur të nisni aplikacionin. Le të shqyrtojmë një nga skedarët (V1__init.sql) si një shembull.
KRIJO TABELËN PERSON (
id BIGINT GJENERUAR NGA DEFAULT SI IDENTITET,
first_name varchar(255) not null,
last_name varchar(255) not null
);
futo në PERSON (first_name, last_name) vlera ('Dave', 'Syer');E gjithë kjo flet për vete: mund ta përdorni SQL për të përcaktuar se si duhet të ndryshojë baza juaj e të dhënave. Për më shumë informacion në lidhje me Spring Boot dhe Flyway, shihni .
Duke përdorur mjetin e menaxhimit të versioneve me Spring Boot, ju merrni 2 përfitime të mëdha:
- ndani ndryshimet e bazës së të dhënave nga ndryshimet në kod
- migroni bazën e të dhënave së bashku me lëshimin e aplikacionit tuaj, dmth. procesi juaj i deployment-it është i lehtësuar
Zgjidhja e problemeve me bazën e të dhënave
Në seksionin e ardhshëm të artikullit ne do të përqendrohemi në shqyrtimin e dy qasjeve për ndryshimet e bazës së të dhënave.
- përputhshmëria e prapme
- përputhshmëria përpara
E para do të shqyrtohet si një paralajmërim, se nuk duhet të bëni nxjerrje të papërgjegjshme pa përgatitje... E dyta ofron një zgjidhje, se si mund të bëni deployment pa ndalesa dhe njëkohësisht të ruani përputhshmërinë përpara.
Projekti ynë, mbi të cilin do të punojmë, do të jetë një aplikacion i thjeshtë Spring Boot Flyway, në të cilin ka Person me first_name dhe last_name në bazën e të dhënave (shënim: Person është tabela, dhe first_name dhe last_name është fusha në të). Ne duam të riemërtojmë last_name në surname.
Supozime
Para se të thellohemi në detaje, është e nevojshme të përcaktojmë disa supozime në lidhje me aplikacionet tona. Rezultati kryesor, që duam të arrijmë, do të jetë një proces mjaft i thjeshtë.
Shënim. Këshillë profesionale. Thjeshtimi i proceseve mund t'ju kursejë shumë para në mbështetje (sa më shumë njerëz të punojnë në kompaninë tuaj, aq më shumë keni mundësi të kurseni)!
Nuk duhet të bëni kthimin e bazës së të dhënave
Kjo e lehtëson procesin e lëshimit (disa kthime të bazës së të dhënave janë praktikisht të pamundura, për shembull kthimi i fshirjes). Ne preferojmë të rikthejmë vetëm aplikacionet. Në këtë mënyrë, edhe nëse keni baza të të dhënash të ndryshme (p.sh., SQL dhe NoSQL), pipeline juaj i lëshimit do të duket i njëjtë.
Duhet të ketë GJITHMONË mundësinë për të kthyer aplikacionin një version mbrapa (jo më shumë)
Kthimi duhet të bëhet vetëm në rast nevoje. Nëse në versionin aktual ka një gabim, i cili nuk është i lehtë për tu rregulluar, ne duhet të jemi në gjendje të kthehemi në versionin më të fundit funksional. Ne supozojmë se ky version më i fundit funksional është ai paraardhës. Mbështetja e përputhshmërisë midis kodit dhe bazës së të dhënave për më shumë se një lëshim do të ishte jashtëzakonisht e vështirë dhe e shtrenjtë.
Shënim. Për lexueshmëri më të madhe, brenda këtij artikulli ne do të ndryshojmë versionin e mërthit të aplikacionit.
Hapi 1: Shtimi i bazës
Versioni i aplikacionit: 1.0.0
Versioni i DB: v1
Komentari
Ky do të jetë gjendja fillestare e aplikacionit.
Ndryshimet në DB
DB përmban last_name.
KRIJO TABELËN PERSON (
id BIGINT GJENERUAR NGA DEFAULT SI IDENTITET,
first_name varchar(255) not null,
last_name varchar(255) not null
);
futo në PERSON (first_name, last_name) vlera ('Dave', 'Syer');Ndryshimet në kod
Aplikacioni ruan të dhënat Person në last_name:
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastname) {
this.lastName = lastname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName
+ "]";
}
}Ri-emërti i kolonës që nuk është i përputhshëm
Le të shohim një shembull, se si të ndryshoni emrin e kolonës:
Kujdes. Shembulli në vazhdim do të çojë qëllimisht në thyerjen e funksionalitetit. Ne e shfaqim këtë për të demonstruar problemin e përputhshmërisë së bazës së të dhënave.
Versioni i aplikacionit: 2.0.0.BAD
Versioni i DB: v2bad
Komentari
Ndryshimet aktuale NUK na lejojnë të drejtojmë dy ekzemplarë (të vjetër dhe të ri) njëkohësisht. Pra, lëshimi pa ndalesa do të jetë i vështirë për t'u arritur (nëse merret parasysh supozimet, në fakt është e pamundur).
Testimi A/B
Situata aktuale është se kemi një aplikacion versioni 1.0.0, të instaluar në prodhimin, dhe DB v1. Ne duhet të lëshojmë një ekzemplar të dytë të aplikacionit, versioni 2.0.0.BAD, dhe të azhurnojmë bazën e të dhënave në v2bad.
Hapat:
- u lëshua një ekzemplar i ri i aplikacionit versioni
2.0.0.BAD, i cili azhurnon bazën e të dhënave nëv2bad - në bazën e të dhënave
v2badkolonalast_namenuk ekziston më - është ndryshuar nësurname - azhurimi i bazës së të dhënave dhe aplikacionit kaloi me sukses, dhe disa ekzemplarë funksionojnë në
1.0.0, të tjerë në2.0.0.BAD. Të gjitha lidheshin me DBv2bad - të gjithë ekzemplarët e versionit
1.0.0do të fillojnë të japin gabime, sepse do të përpiqen të fusin të dhëna në kolonënlast_nameqë nuk ekziston më - të gjithë ekzemplarët e versionit
2.0.0.BADdo të funksionojnë pa probleme
Siç e shihni, nëse bëjmë ndryshime që nuk janë të përputhshme për bazën e të dhënave dhe aplikacionin, testimi A/B nuk është i mundur.
Kthimi aplikacionit
Le të supozojmë, se pas përpjekjes për të realizuar lëshimin A/B (shënim: ndoshta këtu autori kishte parasysh testimin A/B) ne vendosëm që na nevojitej të kthejmë aplikacionin në versionin 1.0.0. Supozoni se nuk duam të bëjmë kthimin e bazës së të dhënave.
Hapat:
- ndalem eksperimentin e aplikacionit versioni
2.0.0.BAD - baza e të dhënave është akoma
v2bad - për shkak se versioni
1.0.0nuk kupton se çfarë ështësurname, ne do të shohim gabime - ka mësuar të shpëtojë, ne nuk mund të kthehemi më
Si e keni parë, nëse bëjmë ndryshime të pakompatueshme mbrapa në DB dhe aplikacion, nuk mund të kthehemi në versionin e mëparshëm.
Logs të ekzekutimit të skriptit
Scenario i pakompatueshëm mbrapa:
01) Ekzekutoni 1.0.0
02) Prisni që aplikacioni (1.0.0) të ngarkohet
03) Gjeneroni një person duke thirrur POST localhost:9991/person për versionin 1.0.0
04) Ekzekutoni 2.0.0.BAD
05) Prisni që aplikacioni (2.0.0.BAD) të ngarkohet
06) Gjeneroni një person duke thirrur POST localhost:9991/person për versionin 1.0.0 <-- kjo duhet të dështojë
07) Gjeneroni një person duke thirrur POST localhost:9992/person për versionin 2.0.0.BAD <-- kjo duhet të kalojë
Duke nisur aplikacionin në versionin 1.0.0
Gjeneroni një person në versionin 1.0.0
Duke dërguar një post në 127.0.0.1:9991/person. Kjo është përgjigjja:
{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}
Duke nisur aplikacionin në versionin 2.0.0.BAD
Gjeneroni një person në versionin 1.0.0
Duke dërguar një post në 127.0.0.1:9991/person. Kjo është përgjigjja:
curl: (22) URL-ja e kërkuar ktheu gabim: 500 Gabim NdërmjetësNdryshimet në DB
Skripti i migrimit, i cili riemëron last_name në surname
Skripti origjinal Flyway:
KRIJO TABELËN PERSON (
id BIGINT GJENERUAR NGA DEFAULT SI IDENTITET,
first_name varchar(255) not null,
last_name varchar(255) not null
);
futo në PERSON (first_name, last_name) vlera ('Dave', 'Syer');Skripti, i cili riemëron last_name.
-- Ky ndryshim është në mënyrë pakompatibile mbrapa - nuk mund të bëni testim A/B
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;Ndryshimet në kod
Ne kemi ndryshuar emrin e fushës lastName në surname.
Riemërimi i kolonës në një mënyrë pakompatibile
Kjo është situata më e zakonshme me të cilën mund të përballemi. Na nevojitet të bëjmë ndryshime të pakompatueshme mbrapa. Ne e kemi provuar tashmë se për të bërë deploy pa ndërprerje, nuk duhet të aplikojmë thjesht migrimin e bazës së të dhënave pa hapa të tjerë. Në këtë pjesë të artikullit, ne do të kryejmë 3 deploy-e të aplikacionit së bashku me migrimet e bazës së të dhënave për të arritur rezultatin e dëshiruar dhe njëkohësisht të ruajmë pasqyrimin e prapavijës.
Shënim. Kujtojmë se kemi DB versioni
v1. Ajo përmban kolonatfirst_namedhelast_name. Ne duhet të ndryshojmëlast_namenësurname. Ne gjithashtu kemi aplikacionin versioni1.0.0,i cili ende nuk përdorsurname.
Hapi 2: Shtoni surname
Versioni i aplikacionit: 2.0.0
Versioni i DB: v2
Komentari
Duke shtuar një kolonë të re dhe duke kopjuar përmbajtjen e saj, ne krijojmë ndryshime të pakompatueshme mbrapa në DB. Në të njëjtën kohë, nëse kthejmë JAR-in ose kemi një JAR të vjetër në punë, ai nuk do të dështojë gjatë ekzekutimit.
Lëshoni versionin e ri
Hapat:
- mënyra për të migruar DB, për të krijuar kolonën e re
surname. Tani DB juaj versioniv2 - kopjoni të dhënat nga
last_namenësurname. Kërkojmë vëmendje, që nëse keni shumë nga këto të dhëna, duhet të shqyrtoni migimin në grupe! - shkruani kodin, ku përdoren TË DY dhe e re, dhe kolona e vjetër. Tani aplikacioni juaj versioni lexoni vlerën nga kolona
2.0.0 - , nëse nuk është
surname, ose nga lnullast_name, nësenuk është përcaktuar. Mund të hiqnisurnamegetLastName()nga Kodi, pasi ai do të kthejënë kthimin e aplikacionit tuaj menullNëse përdorni Spring Boot Flyway, këto dy hapa do të kryhen gjatë fillimit të versionit të aplikacionit.3.0.0deri në2.0.0.
Nëse ekzekutoni mjetin për menaxhimin e versioneve të bazës së të dhënave manualisht, do t'ju duhet të bëni këtë për dy veprime të ndryshme (së pari azhurnoni versionin e db manualisht, pastaj lëshoni aplikacionin e ri). 2.0.0 Kujtoni që kolonat e sapo krijuara
Është e rëndësishme. NUK DUHET Nuk duhet të jetë NOT NULL. Nëse bëni kthimin prapa, aplikacioni i vjetër nuk e di për kolonën e re dhe nuk do ta vendosë gjatë
Futni.Por nëse e shtoni këtë kufizim, dhe DB juaj ështëv2, do të kërkohet vendosja e vlerës së kolonës së re. Kjo do të çon në shkelje të kufizimeve.Është e rëndësishme. Duhet të hiqni metodën
nga Kodi, pasi ai do të kthejë, pasi në versionin3.0.0në kod nuk ka konceptin e kolonëslast_name. Kjo do të thotë që do të vendosen null. Ju mund ta lini metodën dhe të shtoni kontrolle përnull, por zgjidhja më e mirë do të ishte të siguroheni që në logjikëngetSurname()zgjodhët vlerën e duhur të padëshirueshme.
Testimi A/B
Situata aktuale është se kemi një aplikacion versioni 1.0.0, e stanndardizuar në prodhim, dhe DB në v1. Duhet të lëshojmë një ekzemplar të dytë të aplikacionit versioni 2.0.0, i cili do të azhurnojë bazën e të dhënave në v2.
Hapat:
- u lëshua një ekzemplar i ri i aplikacionit versioni
2.0.0, i cili azhurnon bazën e të dhënave nëv2 - ndërkohë disa kërkesa u përpunuan nga ekzemplarët e versionit
1.0.0 - azhurimi kaloi me sukses, dhe tani keni disa ekzemplarë funksionues të aplikacionit versioni
1.0.0dhe versionet e tjera2.0.0.Të gjitha komunikojnë me DB nëv2 - versioni
1.0.0nuk përdor kolonën surname në DB, ndërsa versioni2.0.0e përdor. Ato nuk pengojnë njëra-tjetrën, dhe nuk duhet të ketë gabime. - versioni
2.0.0ruan të dhënat si në kolonën e vjetër ashtu edhe në atë të re, duke siguruar pasqyrimin mbrapa
Është e rëndësishme. Nëse keni ndonjë kërkesë që numëron elemente në bazë të vlerave nga kolona e vjetër / e re, duhet të kujtoni se tani keni dublim vlerash (për shkak të migrimit në vazhdim). Për shembull, nëse dëshironi të numëroni përdoruesit, emri i të cilëve (pavarësisht se si quhet kolona) fillon me letrën
A, atëherë deri në përfundimin e migrimit të të dhënave (kolona e vjetër) mund të keni të dhëna të paqëndrueshme, nëse ekzekutoni një kërkesë për kolonën e re.→e reTani kemi aplikacionin versioni
Kthimi aplikacionit
dhe bazën e të dhënave në 2.0.0 kthejeni aplikacionin tuaj në versionin v2.
Hapat:
- nuk përdor kolonën
1.0.0. - versioni
1.0.0në DB, prandaj kthimi duhet të jetë i suksesshëm.surnameNdryshimet e DB
DB përmban një kolonë me emrin
Skripti origjinal Flyway: last_name.
Skripti i shtimit
KRIJO TABELËN PERSON (
id BIGINT GJENERUAR NGA DEFAULT SI IDENTITET,
first_name varchar(255) not null,
last_name varchar(255) not null
);
futo në PERSON (first_name, last_name) vlera ('Dave', 'Syer');Skript për shtimin surname.
Kujdes. Kujtoni se nuk duhet të shtoni asnjë kufizim NOT NULL në kolonën që po shtohet. Nëse riktheni JAR-in, versioni i vjetër nuk do të dijë për kolonën e shtuar dhe automatikisht do t'i caktuar asaj vlerën NULL. Nëse ka një kufizim të tillë, aplikacioni i vjetër do të thyehet.
-- VËREJTJE: Ky fushë nuk mund të ketë kufizimin NOT NULL sepse nëse rikthehemi, versioni i vjetër nuk do ta dijë për këtë fushë
-- dhe gjithmonë do ta caktojë atë në NULL
ALTER TABLE PERSON ADD surname varchar(255);
-- NË KËTË RAST MENDOJMË SE ËSHTË NJË MIGRIM I SHPEJTË - ND otherwise DO TË KISHE NEVOJË PËR TË MIGRUAR NË GRUPA
UPDATE PERSON SET PERSON.surname = PERSON.last_nameNdryshimet në kod
Ne ruajmë të dhënat si në last_name, si dhe në surname. Ndërkohë lexojmë nga last_name, pasi kjo kolonë është më e rëndësishmja. Në procesin e deploimit, disa kërkesa mund të jenë përpunuar nga një instancë e aplikacionit që ende nuk është përditësuar.
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String surname;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* Reading from the new column if it's set. If not the from the old one.
*
* When migrating from version 1.0.0 -> 2.0.0 this can lead to a possibility that some data in
* the surname column is not up to date (during the migration process lastName could have been updated).
* In this case one can run yet another migration script after all applications have been deployed in the
* new version to ensure that the surname field is updated.
*
* However it makes sense since when looking at the migration from 2.0.0 -> 3.0.0. In 3.0.0 we no longer
* have a notion of lastName at all - so we don't update that column. If we rollback from 3.0.0 -> 2.0.0 if we
* would be reading from lastName, then we would have very old data (since not a single datum was inserted
* to lastName in version 3.0.0).
*/
public String getSurname() {
return this.surname != null ? this.surname : this.lastName;
}
/**
* Storing both FIRST_NAME and SURNAME entries
*/
public void setSurname(String surname) {
this.lastName = surname;
this.surname = surname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName + ", surname=" + this.surname
+ "]";
}
}Hapi 3: Fshirja e last_name nga kodi
Versioni i aplikacionit: 3.0.0
Versioni i DB:v3
Komentari
Shënim përkthe: Duket se në artikullin origjinal autori ka kopjuar gabimisht tekstin nga ky bllok nga hapi 2. Në këtë hap duhet të bëhen ndryshime në kodin e aplikacionit, të orientuara drejt heqjes së funksionalitetit që përdor kolonën last_name.
Duke shtuar një kolonë të re dhe duke kopjuar përmbajtjen e saj, krijuam ndryshime të përshtatshme të BD-së. Nëse do të rikthejmë JAR-in ose kemi një JAR të vjetër që funksionon, ai nuk do të dështojë gjatë ekzekutimit.
Kthimi aplikacionit
Aktualisht kemi aplikacionin version 3.0.0 dhe bazën e të dhënave v3. Versioni 3.0.0 nuk ruan të dhënat në last_name. Kjo do të thotë se në surname ruhet informata më aktuale.
Hapat:
- nuk përdor kolonën
2.0.0. - versioni
2.0.0përdor dhelast_namedhesurname. - versioni
2.0.0do të marrësurname, nëse ai nuk është null, përndryshe —last_name
Ndryshimet në DB
Nuk ka ndryshime strukturore në BD. Skripti në vijim ekzekuton migrimin përfundimtar të të dhënave të vjetra:
-- NË KËTË RAST MENDOJMË SE ËSHTË NJË MIGRIM I SHPEJTË - NË ND otherwise DO TË KISHE NEVOJË PËR TË MIGRUAR NË GRUPA
-- PO ASHTU NUK PO KONTROLLONI Nëse NUK PO SHTONI ENTRIT TË EKZISTUAR. DUHEMI TË KRAHASOJME
-- VERSIONET E ENTRIVE PËR TË SIGURUAR QË NËSE KA NJË ENTRI ME NJË NUMËR TË LART VERSIONI
-- NE NUK DO TË SHTOJMË ATË.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;
-- HEQJA E KUFIZIMIT NOT NULL; NDI otherwise DO TË PROVOJME TË SHTOJME VLERË NULL TË LAST_NAME
-- ME KUFIZIM NOT_NULL.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;Ndryshimet në kod
Shënim përkthe: Përshkrimi i këtij blloku gjithashtu ka qenë gabimisht i kopjuar nga autori nga hapi 2. Sipas logjikës së tregimit të artikullit, ndryshimet në kodin në këtë hap duhet të jenë të orientuara drejt heqjes së elementeve që punojnë me kolonën last_name.
Ne ruajmë të dhënat si në last_name, si dhe në surname. Për më tepër, ne lexojmë nga kolona last_name, pasi ajo është më e rëndësishmja. Në procesin e shpërndarjes, disa kërkesa mund të përpunohen nga një instancë që ende nuk është përditësuar.
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.flyway;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String surname;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return this.surname;
}
public void setSurname(String lastname) {
this.surname = lastname;
}
@Override
public String toString() {
return "Person [firstName=" + this.firstName + ", surname=" + this.surname
+ "]";
}
}Hapi 4: Fshirja e last_name nga BD
Versioni i aplikacionit: 4.0.0
Versioni i DB: v4
Komentari
Pasi versioni 3.0.0 nuk përdori kolonën last_name, gjatë ekzekutimit nuk do të ndodhë ndonjë gjë e keqe nëse rikthehemi në 3.0.0 pas heqjes së kolonës nga baza e të dhënave.
Logs të ekzekutimit të skriptit
Do ta bëjmë në këtë mënyrë:
01) Ekzekuto 1.0.0
02) Prit për aplikacionin (1.0.0) që të ngrihet
03) Gjenero një person duke thirrur POST localhost:9991/person në versionin 1.0.0
04) Ekzekuto 2.0.0
05) Prit për aplikacionin (2.0.0) që të ngrihet
06) Gjenero një person duke thirrur POST localhost:9991/person në versionin 1.0.0
07) Gjenero një person duke thirrur POST localhost:9992/person në versionin 2.0.0
08) Vrit aplikacionin (1.0.0)
09) Ekzekuto 3.0.0
10) Prit për aplikacionin (3.0.0) që të ngrihet
11) Gjenero një person duke thirrur POST localhost:9992/person në versionin 2.0.0
12) Gjenero një person duke thirrur POST localhost:9993/person në versionin 3.0.0
13) Vrit aplikacionin (3.0.0)
14) Ekzekuto 4.0.0
15) Prit për aplikacionin (4.0.0) që të ngrihet
16) Gjenero një person duke thirrur POST localhost:9993/person në versionin 3.0.0
17) Gjenero një person duke thirrur POST localhost:9994/person në versionin 4.0.0
Duke filluar aplikacionin në versionin 1.0.0
Gjeneroni një person në versionin 1.0.0
Dërgimi i një postimi në 127.0.0.1:9991/person. Kjo është përgjigjja:
{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}
Duke filluar aplikacionin në versionin 2.0.0
Gjeneroni një person në versionin 1.0.0
Dërgimi i një postimi në 127.0.0.1:9991/person. Kjo është përgjigjja:
{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}
Gjeneroni një person në versionin 2.0.0
Dërgimi i një postimi në 127.0.0.1:9992/person. Kjo është përgjigjja:
{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}
Vrit aplikacionin 1.0.0
Duke filluar aplikacionin në versionin 3.0.0
Gjeneroni një person në versionin 2.0.0
Dërgimi i një postimi në 127.0.0.1:9992/person. Kjo është përgjigjja:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}
Gjeneroni një person në versionin 3.0.0
Dërgimi i një postimi në 127.0.0.1:9993/person. Kjo është përgjigjja:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}
Vrit aplikacionin 2.0.0
Duke filluar aplikacionin në versionin 4.0.0
Gjeneroni një person në versionin 3.0.0
Dërgimi i një postimi në 127.0.0.1:9993/person. Kjo është përgjigjja:
{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}
Gjeneroni një person në versionin 4.0.0
Dërgimi i një postimi në 127.0.0.1:9994/person. Kjo është përgjigjja:
{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}Ndryshimet e BD
Sa për v3 ne thjesht heqim kolonën last_name dhe shtojmë kufizimet që mungojnë.
-- HEQJA E KOLONËS
ALTER TABLE PERSON DROP last_name;
-- SHTIMI I KUFIZIMEVE
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;Ndryshimet në kod
Nuk ka ndryshime në kod.
Përfundim
Ne e kemi realizuar me sukses një ndryshim të prapë të emrit të kolonës, duke realizuar disa shpërndarje të përshtatshme. Më poshtë është një përmbledhje e veprimeve të kryera:
- depoja e aplikacionit version
1.0.0mev1skemat e BD (emri i kolonës =last_name) - depoja e aplikacionit version
2.0.0,që ruan të dhënat nëlast_namedhesurname. Aplikacioni lexon ngalast_name. BD-ja është në versioninv2, duke përfshirë kolonat silast_name, ashtu edhesurname. surnameështë një kopje e l, nëse. (VËREJTJE: kjo kolona nuk duhet të ketë kufizimin not null) - depoja e aplikacionit version
3.0.0, e cila ruan të dhënat vetëm nësurnamedhe lexon nga surname. Sa i përket DB, ndodhi migrimi i funditlast_namenësurname. Po ashtu, kufizimi NOT NULL heqet ngalast_name. DB tani është në versioninv3 - depoja e aplikacionit version
4.0.0— nuk bëhen asnjë ndryshim në kod. Dërgimi i bazës së të dhënavev4, e cila fshinlast_name. Këtu mund të shtoni çdo kufizim të munguar në DB.
Duke ndjekur këtë qasje, gjithmonë mund të ktheheni një version prapa, pa e prishur kompatibilitetin e DB / aplikacionit.
Kodi
Të gjithë kodin e përdorur në këtë artikull e gjeni në . Më poshtë përshkrim shtesë.
Projektet
Pas klonimit të repositorit, do të shihni strukturën e mëposhtme të dosjeve.
├── boot-flyway-v1 - 1.0.0 version e aplikacionit me v1 të skemës
├── boot-flyway-v2 - 2.0.0 version e aplikacionit me v2 të skemës (e përputhshme me prapa - aplikacioni mund të rikthehet)
├── boot-flyway-v2-bad - 2.0.0.BAD version e aplikacionit me v2bad të skemës (e pa përputhshme - aplikacioni nuk mund të rikthehet)
├── boot-flyway-v3 - 3.0.0 version e aplikacionit me v3 të skemës (aplikacioni mund të rikthehet)
└── boot-flyway-v4 - 4.0.0 version e aplikacionit me v4 të skemës (aplikacioni mund të rikthehet)Skripte
Mund të ekzekutoni skriptet e përshkruara në skriptet më poshtë, të cilat demonstrojnë ndryshimet e përputhshme dhe të pa përputhshme në DB.
Për të parë rastin me ndryshimet e përputhshme, ekzekutoni:
./scripts/scenario_backward_compatible.shDhe për të parë rastin me ndryshimet e pa përputhshme, ekzekutoni:
./scripts/scenario_backward_incompatible.shSample Flyway Spring Boot
Të gjitha shembujt janë marrë nga Spring Boot Sample Flyway.
Mund të shikoni në http://localhost:8080/flyway, aty është lista e skripteve.
Ky shembull gjithashtu përfshin konsolën H2 (në adresën http://localhost:8080/h2-console), që ju mundëson të shihni gjendjen e bazës së të dhënave (URL jdbc për default — jdbc:h2:mem:testdb).
Shtesë
Shihni gjithashtu artikuj të tjerë në blogun tonë:
Burimi: habr.com
