Dan l-artikolu jispjega fid-dettall kif issolvi kwistjonijiet ta' kompatibilità tad-database fl-iskjerament. Aħna ngħidulek x'jista' jiġri mill-applikazzjonijiet tal-produzzjoni tiegħek jekk tipprova tuża mingħajr preparazzjoni preliminari. Imbagħad ser ngħaddu mill-istadji taċ-ċiklu tal-ħajja tal-applikazzjoni li huma meħtieġa biex ikollhom żero waqfien (madwar. korsija: aktar - żero waqfien). Ir-riżultat tal-operazzjonijiet tagħna se jkun li napplikaw il-bidla tad-database inkompatibbli b'lura b'mod kompatibbli b'lura.
Jekk trid tifhem l-eżempji tal-kodiċi mill-artiklu, tista’ ssibhom fuq GitHub.
Introduzzjoni
Skjerament żero ta' waqfien
Liema mistika skjerament żero ta' waqfien? Tista 'tgħid li dan huwa meta l-applikazzjoni tiegħek tiġi skjerata b'tali mod li tista' tintroduċi b'suċċess verżjoni ġdida tal-applikazzjoni għall-produzzjoni, filwaqt li l-utent ma jindunax li din ma tkunx disponibbli. Mill-perspettiva tal-utent u tal-kumpanija, dan huwa l-aħjar xenarju ta’ skjerament possibbli għaliex jippermetti li jiġu introdotti karatteristiċi ġodda u li l-bugs jiġu ffissati mingħajr tfixkil.
Kif tikseb dan? Hemm diversi modi, hawn wieħed minnhom:
tuża l-verżjoni Nru 1 tas-servizz tiegħek
twettaq migrazzjoni tad-database
Uża l-verżjoni #2 tas-servizz tiegħek b'mod parallel mal-verżjoni #1
malli tara li l-verżjoni Nru 2 taħdem kif suppost, neħħi l-verżjoni Nru 1
sar!
Faċli, hux? Sfortunatament, mhuwiex daqshekk sempliċi, u aħna ser inħarsu lejn dan fid-dettall aktar tard. Issa ejja niċċekkjaw proċess ieħor ta' skjerament pjuttost komuni - iskjerament blu aħdar.
Qatt smajt biha skjerament blu aħdar? Cloud Foundry tagħmel dan estremament faċli. Ħares lejn dan l-artikolu, fejn niddeskrivu dan f'aktar dettall. Biex niġbru fil-qosor, ejjew infakkruk kif tagħmel iskjerament blu aħdar:
tiżgura li żewġ kopji tal-kodiċi tal-produzzjoni tiegħek ("blu" u "aħdar") jaħdmu;
jidderieġi t-traffiku kollu lejn l-ambjent blu, i.e. sabiex l-URLs tal-produzzjoni jindikaw hemm;
tiskjera u tittestja l-bidliet kollha fl-applikazzjoni f'ambjent ekoloġiku;
jaqilbu l-urls minn ambjent blu għal aħdar
L-iskjerament tal-aħdar blu huwa approċċ li jippermettilek tintroduċi faċilment karatteristiċi ġodda mingħajr ma tinkwieta dwar it-tkissir tal-produzzjoni. Dan huwa dovut għall-fatt li anki jekk jiġri xi ħaġa, tista 'faċilment terġa' lura għall-ambjent ta 'qabel billi sempliċement "tqabbad swiċċ."
Wara li taqra dak kollu ta 'hawn fuq, tista' tistaqsi l-mistoqsija: X'għandu x'jaqsam żero waqfien mal-iskjerament tal-Blue green?
Ukoll, għandhom ħafna komuni, peress li ż-żamma ta 'żewġ kopji tal-istess ambjent teħtieġ id-doppju tal-isforz biex jinżammu. Huwa għalhekk li xi timijiet jippretendu Martin Fowler, segwi varjazzjoni ta' dan l-approċċ:
Għażla oħra hija li tuża l-istess database, li toħloq swiċċijiet blu-aħdar għas-saffi tal-web u tad-dominju. F'dan l-approċċ, id-database ħafna drabi tista 'tkun problema, speċjalment meta jkollok bżonn tibdel l-iskema tagħha biex tappoġġja verżjoni ġdida tas-softwer.
U hawn niġu għall-problema ewlenija f'dan l-artikolu. Database. Ejja nagħtu ħarsa oħra lejn din il-frażi.
twettaq migrazzjoni tad-database.
Issa trid tistaqsi lilek innifsek il-mistoqsija - x'jiġri jekk il-bidla fid-database ma tkunx kompatibbli b'lura? L-ewwel verżjoni tiegħi tal-app mhux se tinkiser? Fil-fatt, dan huwa eżattament dak li se jiġri...
Għalhekk, anke minkejja l-benefiċċji kbar ta’ żero waqfien / skjerament aħdar blu, il-kumpaniji għandhom it-tendenza li jsegwu l-proċess aktar sikur li ġej għall-iskjerament tal-applikazzjonijiet tagħhom:
ipprepara pakkett b'verżjoni ġdida tal-applikazzjoni
jagħlaq applikazzjoni li qed taħdem
run skripts biex jemigraw id-database
skjerament u tniedi verżjoni ġdida tal-applikazzjoni
F'dan l-artikolu, aħna ser nagħtu dettalji dwar kif tista 'taħdem mad-database u l-kodiċi tiegħek biex tieħu vantaġġ mill-iskjerament żero ta' waqfien.
Kwistjonijiet ta' database
Jekk għandek applikazzjoni mingħajr stat li ma taħżen l-ebda dejta fid-database, tista 'tikseb skjerament żero ta' waqfien minnufih. Sfortunatament, il-biċċa l-kbira tas-softwer jeħtieġ li jaħżen id-dejta x'imkien. Huwa għalhekk li għandek taħseb darbtejn qabel ma tagħmel xi tibdil fiċ-ċirkwit. Qabel ma nidħlu fid-dettalji ta 'kif nibdlu l-iskema sabiex l-iskjerament mingħajr perijodi ta' waqfien ikun possibbli, ejja l-ewwel niffukaw fuq l-iskema tal-verżjoni.
Skema ta' verżjoni
F'dan l-artikolu se nużaw Flyway bħala għodda għall-kontroll tal-verżjoni (madwar. Traduzzjoni: qed nitkellmu dwar migrazzjonijiet tad-database). Naturalment, aħna se niktbu wkoll applikazzjoni Spring Boot li għandha l-appoġġ Flyway inkorporat u se twettaq migrazzjoni ta 'skema waqt li twaqqaf il-kuntest tal-applikazzjoni. Meta tuża Flyway, tista' taħżen skripts tal-migrazzjoni fil-folder tal-proġetti tiegħek (b'mod awtomatiku fi classpath:db/migration). Hawnhekk tista 'tara eżempju ta' fajls ta 'migrazzjoni bħal dawn
F'dan l-eżempju naraw 4 skripts ta 'migrazzjoni li, jekk ma jkunux esegwiti qabel, se jiġu eżegwiti wieħed wara l-ieħor meta tibda l-applikazzjoni. Ejja nħarsu lejn wieħed mill-fajls (V1__init.sql) bħala eżempju.
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Kollox huwa perfettament li jispjega lilu nnifsu: tista 'tuża SQL biex tiddefinixxi kif id-database tiegħek għandha tiġi modifikata. Għal aktar informazzjoni dwar Spring Boot u Flyway, iċċekkja Rebbiegħa Boot Docs.
Billi tuża għodda ta 'kontroll tas-sors ma' Spring Boot, ikollok 2 benefiċċji kbar:
inti tissepara l-bidliet fid-database minn bidliet fil-kodiċi
Il-migrazzjoni tad-database sseħħ flimkien mat-tnedija tal-applikazzjoni tiegħek, i.e. il-proċess tal-iskjerament tiegħek huwa ssimplifikat
Issolvi problemi fid-database
Fit-taqsima li jmiss tal-artikolu, aħna ser niffukaw fuq inħarsu lejn żewġ approċċi għall-bidliet fid-database.
inkompatibbiltà b'lura
kompatibilità b'lura
L-ewwel wieħed se jitqies bħala twissija li m'għandekx twettaq żero skjerament ta 'waqfien mingħajr preparazzjoni preliminari... It-tieni waħda toffri soluzzjoni dwar kif tista' twettaq skjerament mingħajr perijodi ta 'waqfien u fl-istess ħin iżżomm kompatibilità b'lura.
Il-proġett tagħna li se nkunu qed naħdmu fuqu se jkun applikazzjoni sempliċi Spring Boot Flyway li għandha Person с first_name и last_name fid-database (madwar. traduzzjoni: Person hija tabella u first_name и last_name - dawn huma l-oqsma fiha). Irridu nbiddlu l-isem last_name в surname.
Suppożizzjonijiet
Qabel ma nidħlu fid-dettalji, hemm ftit suppożizzjonijiet li rridu nagħmlu dwar l-applikazzjonijiet tagħna. Ir-riżultat ewlieni li rridu niksbu se jkun proċess pjuttost sempliċi.
In-nota. Negozju PRO-TIP. Is-simplifikazzjoni tal-proċessi tiegħek tista 'tiffranka ħafna flus fuq l-appoġġ (aktar ma jkollok nies jaħdmu għall-kumpanija tiegħek, aktar tista' tiffranka flus)!
Ebda ħtieġa li rollback id-database
Dan jissimplifika l-proċess tal-iskjerament (xi rollbacks tad-database huma kważi impossibbli, bħal rollback tat-tħassir). Nippreferu li nerġgħu lura biss l-applikazzjonijiet. Dan il-mod, anki jekk għandek databases differenti (pereżempju, SQL u NoSQL), il-pipeline tal-iskjerament tiegħek se jidher l-istess.
Għandu DEJJEM ikun possibbli li l-applikazzjoni terġa' lura verżjoni waħda lura (mhux aktar)
It-tkeċċija għandha ssir biss meta jkun meħtieġ. Jekk ikun hemm xi bug fil-verżjoni attwali li ma tissewwax faċilment, għandna nkunu nistgħu nerġgħu lura għall-aħħar verżjoni tax-xogħol. Nassumu li din l-aħħar verżjoni tax-xogħol hija dik preċedenti. Iż-żamma tal-kodiċi u l-kompatibilità tad-database għal aktar minn tnedija waħda tkun estremament diffiċli u għalja.
In-nota. Għal aktar leġibilità, f'dan l-artikolu ser nibdlu l-verżjoni ewlenija tal-applikazzjoni.
Pass 1: Stat Inizjali
Verżjoni tal-App: 1.0.0
Verżjoni tad-DB: v1
Kumment
Dan se jkun l-istat inizjali tal-applikazzjoni.
Tibdil tad-database
DB fih last_name.
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Tibdil fil-kodiċi
L-applikazzjoni taħżen id-dejta tal-Persuna fi 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
+ "]";
}
}
Tibdil tal-kolonna b'lura inkompatibbli
Ejja nħarsu lejn eżempju ta' kif tibdel isem kolonna:
Attenzjoni. L-eżempju li ġej se jkisser l-affarijiet intenzjonalment. Aħna nuru dan biex nuru l-problema tal-kompatibilità tad-database.
Verżjoni tal-App: 2.0.0.BAD
Verżjoni tad-DB: v2bad
Kumment
Il-bidliet attwali MHUX jippermettulna nħaddmu żewġ istanzi (qodma u ġodda) fl-istess ħin. Għalhekk, l-iskjerament żero ta 'waqfien se jkun diffiċli biex jinkiseb (jekk jitqiesu s-suppożizzjonijiet, huwa fil-fatt impossibbli).
Ittestjar A/B
Is-sitwazzjoni attwali hija li għandna verżjoni tal-applikazzjoni 1.0.0, skjerati fil-produzzjoni, u database v1. Għandna bżonn niskjeraw it-tieni istanza tal-applikazzjoni, verżjoni 2.0.0.BAD, u aġġorna d-database għal v2bad.
Passi:
tiġi skjerata istanza ġdida tal-applikazzjoni tal-verżjoni 2.0.0.BADli jaġġorna d-database għal v2bad
fid-database v2bad kolonna last_name m'għadux jeżisti - inbidel għal surname
Id-database u l-aġġornament tal-applikazzjoni rnexxew u xi każijiet qed jaħdmu 1.0.0, oħrajn - in 2.0.0.BAD. Kollox huwa konness mad-database v2bad
l-istanzi kollha tal-verżjoni 1.0.0 se jibdew jitfgħu l-iżbalji għax jippruvaw idaħħlu d-dejta fil-kolonna last_nameli m’għadux jeżisti
l-istanzi kollha tal-verżjoni 2.0.0.BAD se taħdem mingħajr problemi
Kif tistgħu taraw, jekk nagħmlu bidliet lura inkompatibbli fid-database u l-applikazzjoni, l-ittestjar A/B huwa impossibbli.
Applikazzjoni rollback
Ejja nassumu li wara li ppruvaw nagħmlu skjerament A/B (madwar. per.: l-awtur probabbilment fisser ittestjar A/B hawn) iddeċidejna li għandna bżonn nerġgħu lura l-applikazzjoni għall-verżjoni 1.0.0. Ejja ngħidu li ma rridux nerġgħu lura d-database.
mill-verżjoni 1.0.0 ma jifhimx x'inhu surname, se naraw żbalji
l-infern inqala’, ma nistgħux immorru lura aktar
Kif tistgħu taraw, jekk nagħmlu bidliet lura inkompatibbli fid-database u l-applikazzjoni, ma nistgħux nirritornaw għall-verżjoni preċedenti.
Reġistri tal-eżekuzzjoni tal-iskript
Backward incompatible scenario:
01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0.BAD
05) Wait for the app (2.0.0.BAD) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0 <-- this should fail
07) Generate a person by calling POST localhost:9992/person to version 2.0.0.BAD <-- this should pass
Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}
Starting app in version 2.0.0.BAD
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
curl: (22) The requested URL returned error: 500 Internal Server Error
Generate a person in version 2.0.0.BAD
Sending a post to 127.0.0.1:9995/person. This is the response:
{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}
Tibdil tad-database
Iskrittura tal-migrazzjoni li tibdel l-isem last_name в surname
Sors Skript tal-Flyway:
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Iskrittura li tibdel l-isem last_name.
-- This change is backward incompatible - you can't do A/B testing
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;
Tibdil fil-kodiċi
Bdilna l-isem tal-qasam lastName fuq surname.
Tibdil-isem ta' kolonna b'mod kompatibbli b'lura
Din hija l-aktar sitwazzjoni komuni li nistgħu niltaqgħu magħhom. Irridu nagħmlu bidliet inkompatibbli b'lura. Diġà ppruvajna li għal skjerament mingħajr perijodi ta' waqfien, m'għandniex sempliċement napplikaw il-migrazzjoni tad-database mingħajr passi addizzjonali. F'din it-taqsima tal-artikolu, se nwettqu 3 skjeramenti tal-applikazzjoni flimkien ma 'migrazzjonijiet tad-database biex niksbu r-riżultat mixtieq filwaqt li nżommu kompatibilità b'lura.
In-nota. Ftakar li għandna database tal-verżjoni v1. Fiha kolonni first_name и last_name. Irridu nbiddlu last_name fuq surname. Għandna wkoll verżjoni tal-app 1.0.0, li għadu mhux użat surname.
Pass 2: Żid kunjom
Verżjoni tal-App: 2.0.0
Verżjoni tad-DB: v2
Kumment
Billi żżid kolonna ġdida u tikkopja l-kontenut tagħha, noħolqu bidliet fid-database kompatibbli b'lura. Fl-istess ħin, jekk inġibu lura l-JAR jew ikollna JAR antik jaħdem, ma jinkiserx waqt l-eżekuzzjoni.
Qed inwasslu verżjoni ġdida
Passi:
twettaq migrazzjoni tad-database biex toħloq kolonna ġdida surname. Issa l-verżjoni tad-DB tiegħek v2
kopja tad-data minn last_name в surname. Oqgħod attentli jekk għandek ħafna minn din id-dejta, għandek tikkunsidra l-migrazzjoni tal-lott!
ikteb il-kodiċi fejn jintużaw IT-TNEJN и ġdidU il-qodma kolonna. Issa l-verżjoni tal-app tiegħek 2.0.0
aqra l-valur mill-kolonna surname, jekk ma jkunx null, jew minn last_name, jekk surname mhux speċifikat. Tista' tħassar getLastName() mill-kodiċi, peress li se joħroġ null meta tirreġġa' lura l-applikazzjoni tiegħek minn 3.0.0 li 2.0.0.
Jekk qed tuża Spring Boot Flyway, dawn iż-żewġ passi se jsiru waqt l-istartjar tal-verżjoni 2.0.0 applikazzjonijiet. Jekk tħaddem l-għodda tal-verżjoni tad-database manwalment, ikollok tagħmel żewġ affarijiet differenti biex tagħmel dan (l-ewwel taġġorna l-verżjoni db manwalment u mbagħad tuża l-applikazzjoni l-ġdida).
Huwa importanti. Ftakar li l-kolonna maħluqa ġdida MA GĦANDUX jkun MHUX NULL. Jekk tagħmel rollback, l-applikazzjoni l-antika ma tkunx taf dwar il-kolonna l-ġdida u mhux se tinstallaha matul Insert. Imma jekk iżżid dan ir-restrizzjoni u db tiegħek se jkun v2, dan ikun jeħtieġ l-issettjar tal-valur tal-kolonna l-ġdida. Li se jwassal għal ksur tar-restrizzjonijiet.
Huwa importanti. Għandek tneħħi l-metodu getLastName(), għax fil-verżjoni 3.0.0 M'hemm l-ebda kunċett ta 'kolonna fil-kodiċi last_name. Dan ifisser li null se jiġi stabbilit hemmhekk. Tista 'tħalli l-metodu u żżid kontrolli għal null, iżda soluzzjoni ħafna aħjar tkun li jiġi żgurat li fil-loġika getSurname() għażilt il-valur korrett mhux żero.
Ittestjar A/B
Is-sitwazzjoni attwali hija li għandna verżjoni tal-applikazzjoni 1.0.0, skjerat fuq il-produzzjoni, u d-database fi v1. Għandna bżonn niskjeraw it-tieni istanza tal-applikazzjoni tal-verżjoni 2.0.0li se taġġorna d-database għal v2.
Passi:
tiġi skjerata istanza ġdida tal-applikazzjoni tal-verżjoni 2.0.0li jaġġorna d-database għal v2
sadanittant xi talbiet ġew ipproċessati mill-istanzi tal-verżjoni 1.0.0
l-aġġornament kien ta' suċċess u għandek diversi każijiet ta' tħaddim tal-applikazzjoni tal-verżjoni 1.0.0 u verżjonijiet oħra 2.0.0. Kulħadd jikkomunika mad-database fi v2
verżjoni 1.0.0 ma jużax il-kolonna tal-kunjom fid-database, iżda l-verżjoni 2.0.0 użi. Ma jinterferixxux ma 'xulxin, u m'għandux ikun hemm żbalji.
verżjoni 2.0.0 jaħżen id-dejta kemm fil-kolonna l-antika kif ukoll fil-ġdida, u tiżgura kompatibilità b'lura
Huwa importanti. Jekk għandek xi mistoqsijiet li jgħoddu oġġetti bbażati fuq valuri mill-kolonna l-antika/ġdida, għandek tiftakar li issa għandek valuri duplikati (x'aktarx li għadhom qed jemigraw). Pereżempju, jekk trid tgħodd in-numru ta' utenti li l-kunjom tagħhom (tkun xi tkun tissejjaħ il-kolonna) beda bl-ittra A, imbagħad sakemm titlesta l-migrazzjoni tad-dejta (old → new kolonna) jista’ jkollok dejta inkonsistenti jekk tistaqsi kolonna ġdida.
Applikazzjoni rollback
Issa għandna verżjoni tal-app 2.0.0 u database fi v2.
Passi:
erġa' lura l-applikazzjoni tiegħek għall-verżjoni 1.0.0.
verżjoni 1.0.0 ma jużax kolonna fid-database surname, għalhekk ir-rollback għandu jkun ta 'suċċess
DB bidliet
Id-database fiha kolonna msemmija last_name.
Skript tas-sors tal-Flyway:
CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);
insert into PERSON (first_name, last_name) values ('Dave', 'Syer');
Żid skript surname.
Attenzjoni. Ftakar li MA TISTA' ŻID xi restrizzjoni MHUX NULL mal-kolonna li qed iżżid. Jekk tirritorna l-JAR, il-verżjoni l-antika ma jkollha ebda idea dwar il-kolonna miżjuda u awtomatikament tissettjaha għal NULL. Jekk ikun hemm tali limitazzjoni, l-applikazzjoni l-antika sempliċiment tinkiser.
-- NOTE: This field can't have the NOT NULL constraint cause if you rollback, the old version won't know about this field
-- and will always set it to NULL
ALTER TABLE PERSON ADD surname varchar(255);
-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
UPDATE PERSON SET PERSON.surname = PERSON.last_name
Tibdil fil-kodiċi
Aħna naħżnu data bħala last_name, u fi surname. Fl-istess ħin naqraw minn last_name, peress li din il-kolonna hija l-aktar rilevanti. Matul il-proċess ta' skjerament, xi talbiet setgħu ġew ipproċessati minn istanza ta' applikazzjoni li għadha ma ġietx aġġornata.
/*
* 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
+ "]";
}
}
Pass 3: Tneħħi last_name mill-kodiċi
Verżjoni tal-App: 3.0.0
Verżjoni tad-DB:v3
Kumment
Nota per.: Apparentement, fl-artiklu oriġinali l-awtur ikkuppja bi żball it-test ta’ din il-blokka mill-pass 2. F’dan il-pass, għandhom isiru bidliet fil-kodiċi tal-applikazzjoni mmirati biex titneħħa l-funzjonalità li tuża l-kolonna last_name.
Billi żżid kolonna ġdida u kkuppjat il-kontenut tagħha, ħloqna bidliet fid-database kompatibbli b'lura. Barra minn hekk, jekk inġibu lura l-JAR jew ikollna JAR antik jaħdem, mhux se jinkiser waqt l-eżekuzzjoni.
Applikazzjoni rollback
Bħalissa għandna verżjoni tal-app 3.0.0 u database v3. Verżjoni 3.0.0 ma jiffrankax id-data għal last_name. Dan ifisser li fi surname tinħażen l-aktar informazzjoni aġġornata.
Passi:
erġa' lura l-applikazzjoni tiegħek għall-verżjoni 2.0.0.
verżjoni 2.0.0 użi u last_name и surname.
verżjoni 2.0.0 se tieħu surname, jekk ma jkunx żero, inkella -last_name
Tibdil tad-database
M'hemm l-ebda tibdil strutturali fid-database. L-iskrittura li ġejja titwettaq biex twettaq il-migrazzjoni finali tad-dejta l-antika:
-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
-- ALSO WE'RE NOT CHECKING IF WE'RE NOT OVERRIDING EXISTING ENTRIES. WE WOULD HAVE TO COMPARE
-- ENTRY VERSIONS TO ENSURE THAT IF THERE IS ALREADY AN ENTRY WITH A HIGHER VERSION NUMBER
-- WE WILL NOT OVERRIDE IT.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;
-- DROPPING THE NOT NULL CONSTRAINT; OTHERWISE YOU WILL TRY TO INSERT NULL VALUE OF THE LAST_NAME
-- WITH A NOT_NULL CONSTRAINT.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;
Tibdil fil-kodiċi
Nota per.: Id-deskrizzjoni ta 'dan il-blokk ġiet ukoll ikkupjata bi żball mill-awtur mill-pass 2. Skont il-loġika tal-artiklu, il-bidliet fil-kodiċi f'dan il-pass għandhom ikunu mmirati biex ineħħu minnu elementi li jaħdmu mal-kolonna last_name.
Aħna naħżnu data bħala last_name, u fi surname. Barra minn hekk, naqraw mill-kolonna last_name, peress li hija l-aktar rilevanti. Matul il-proċess tal-iskjerament, xi talbiet jistgħu jiġu pproċessati minn istanza li għadha ma ġietx aġġornata.
/*
* 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
+ "]";
}
}
Pass 4: Tneħħi last_name mid-database
Verżjoni tal-App: 4.0.0
Verżjoni tad-DB: v4
Kumment
Minħabba l-fatt li l-kodiċi tal-verżjoni 3.0.0 ma użax il-kolonna last_name, xejn ħażin ma jiġri waqt l-eżekuzzjoni jekk nerġgħu lura għal 3.0.0 wara li tneħħi kolonna mid-database.
Reġistri tal-eżekuzzjoni tal-iskript
We will do it in the following way:
01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0
05) Wait for the app (2.0.0) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0
07) Generate a person by calling POST localhost:9992/person to version 2.0.0
08) Kill app (1.0.0)
09) Run 3.0.0
10) Wait for the app (3.0.0) to boot
11) Generate a person by calling POST localhost:9992/person to version 2.0.0
12) Generate a person by calling POST localhost:9993/person to version 3.0.0
13) Kill app (3.0.0)
14) Run 4.0.0
15) Wait for the app (4.0.0) to boot
16) Generate a person by calling POST localhost:9993/person to version 3.0.0
17) Generate a person by calling POST localhost:9994/person to version 4.0.0
Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}
Starting app in version 2.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:
{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}
Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:
{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}
Killing app 1.0.0
Starting app in version 3.0.0
Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}
Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}
Killing app 2.0.0
Starting app in version 4.0.0
Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:
{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}
Generate a person in version 4.0.0
Sending a post to 127.0.0.1:9994/person. This is the response:
{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}
DB bidliet
Relattivament v3 aħna biss neħħi l-kolonna last_name u żid ir-restrizzjonijiet nieqsa.
-- REMOVE THE COLUMN
ALTER TABLE PERSON DROP last_name;
-- ADD CONSTRAINTS
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;
Tibdil fil-kodiċi
M'hemm l-ebda tibdil fil-kodiċi.
Output
Aħna applikajna b'suċċess bidla fl-isem tal-kolonna inkompatibbli b'lura billi wettaqna diversi skjeramenti kompatibbli b'lura. Hawn taħt hawn sommarju tal-azzjonijiet imwettqa:
skjerament tal-verżjoni tal-applikazzjoni 2.0.0, li jaħżen id-data fi last_name и surname. L-applikazzjoni taqra minn last_name. Id-database hija fil-verżjoni v2li jkun fihom kolonni simili last_nameU surname. surname hija kopja ta' last_name. (NOTA: Din il-kolonna m'għandux ikollha restrizzjoni mhux nulla)
skjerament tal-verżjoni tal-applikazzjoni 3.0.0, li jaħżen id-dejta biss surname u jaqra mill-kunjom. Fir-rigward tad-database, qed isseħħ l-aħħar migrazzjoni last_name в surname. Limitazzjoni wkoll MHUX NULL imneħħija minn last_name. Id-database issa tinsab fil-verżjoni v3
skjerament tal-verżjoni tal-applikazzjoni 4.0.0 - ma jsir l-ebda tibdil fil-kodiċi. Skjerament tad-database v4, li tneħħi last_name. Hawnhekk tista 'żżid kwalunkwe restrizzjoni nieqsa fid-database.
Billi ssegwi dan l-approċċ, tista 'dejjem terġa' lura verżjoni waħda mingħajr ma tikser il-kompatibilità tad-database/applikazzjoni.
Kodiċi
Il-kodiċi kollu użat f'dan l-artikolu huwa disponibbli fuq GitHub. Hawn taħt hawn deskrizzjoni addizzjonali.
Proġetti
Wara li tikklona r-repożitorju, se tara l-istruttura tal-folder li ġejja.
├── boot-flyway-v1 - 1.0.0 version of the app with v1 of the schema
├── boot-flyway-v2 - 2.0.0 version of the app with v2 of the schema (backward-compatible - app can be rolled back)
├── boot-flyway-v2-bad - 2.0.0.BAD version of the app with v2bad of the schema (backward-incompatible - app cannot be rolled back)
├── boot-flyway-v3 - 3.0.0 version of the app with v3 of the schema (app can be rolled back)
└── boot-flyway-v4 - 4.0.0 version of the app with v4 of the schema (app can be rolled back)
Skripts
Tista' tmexxi l-iskripts deskritti fl-iskripts hawn taħt, li juru bidliet kompatibbli b'lura u inkompatibbli fid-database.
biex tara il-każ b'bidliet kompatibbli b'lura, run:
./scripts/scenario_backward_compatible.sh
U biex tara każ b'bidliet inkompatibbli b'lura, run:
./scripts/scenario_backward_incompatible.sh
Ir-Rebbiegħa Boot Sample Flyway
L-eżempji kollha huma meħuda minn Spring Boot Sample Flyway.
Tista' tagħti ħarsa lejn http://localhost:8080/flyway, hemm lista ta 'skripts.
Dan l-eżempju jinkludi wkoll il-console H2 (at http://localhost:8080/h2-console) sabiex tkun tista' tara l-istatus tad-database (URL jdbc default huwa jdbc:h2:mem:testdb).