
Ovaj članak detaljno objašnjava kako riješiti probleme s kompatibilnošću baza podataka prilikom implementacije. Objasnit ćemo što se može dogoditi s vašim aplikacijama u produkciji ako pokušate implementirati bez prethodne pripreme. Nakon toga ćemo proći kroz faze životnog ciklusa aplikacije koje su potrebne za postizanje nultog vremena zastoja (napomena: dalje - zero downtime). Rezultat naših operacija bit će primjena promjene baze podataka koja nije kompatibilna unatrag na kompatibilan način.
Ako želite proučiti primjere koda iz članka, pronaći ćete ih na .
Uvod
Zero downtime deployment
Što je to mistično zero downtime deployment? Можно сказать, это когда ваше приложение развернуто так, что вы можете успешно вводить новую версию приложения на продакшн, в то время как пользователь не замечает его недоступности. С точки зрения пользователя и компании, это наилучший из возможных сценариев деплоя, поскольку таким образом можно вводить новые функции и устранять ошибки без перебоев в работе.
Kako to postići? Postoji nekoliko načina, evo jednog od njih:
- implementirajte verziju br. 1 vašeg servisa
- izvršite migraciju baze podataka
- implementirajte verziju br. 2 vašeg servisa paralelno s verzijom br. 1
- kada vidite da verzija br. 2 radi kako treba, uklonite verziju br. 1
- spremno!
Lako, zar ne? Nažalost, nije tako jednostavno, a kasnije ćemo to detaljnije razmotriti. A sada hajde da provjerimo još jedan prilično često korišten proces implementacije - blue green deployment.
Jeste li ikada čuli za ? С Cloud Foundry это чрезвычайно легко сделать. Просто гляньте на , gdje to detaljnije opisujemo. Ukratko, ponovimo kako raditi blue green deployment:
- osigurajte rad dviju kopija vašeg produkcijskog koda (“blue” i “green”);
- usmjerite sav promet prema blue okruženju, tj. da URL adrese produkcije upućuju tamo;
- implementirajte i testirajte sve promjene aplikacije u green okruženju;
- prebacite URL adrese s blue na green okruženje
Blue green deployment je pristup koji vam omogućuje lako uvođenje novih funkcija, bez brige da će produkcija biti pokvarena. To je zato što, čak i ako nešto pođe po zlu, možete lako preći na prethodno okruženje jednostavno ‘prebacivanjem prekidača’.
Nakon što ste pročitali sve gore navedeno, mogli biste se zapitati: Kakve veze zero downtime ima s blue green implementacijom?
Pa, imaju prilično mnogo zajedničkog, budući da podrška dvjema kopijama istog okruženja zahtijeva dvostruke napore za njihovo održavanje. Zato neke ekipe, kako tvrdi , drže se varijacije ovog pristupa:
druga opcija uključuje korištenje iste baze podataka, stvarajući plavo-zelene preklopnike za web i domenske slojeve. U takvom pristupu baze podataka često mogu predstavljati problem, posebno kada trebate promijeniti njezinu shemu kako biste podržali novu verziju softvera.
I ovdje dolazimo do glavnog problema u ovom članku. Baza podataka. Pogledajmo ponovno ovu frazu.
izvršite migraciju baze podataka.
Sada biste se trebali zapitati — što ako promjena baze podataka nije kompatibilna? Hoće li moja prva verzija aplikacije propasti? Zapravo, to će se i dogoditi...
Dakle, čak i unatoč ogromnim prednostima zero downtime / blue green deployment-a, tvrtke se sklone pridržavati sljedećeg sigurnijeg procesa implementacije svojih aplikacija:
- pripremiti paket s novom verzijom aplikacije
- isključiti pokrenutu aplikaciju
- pokrenuti skripte za migraciju baze podataka
- implementirati i pokrenuti novu verziju aplikacije
U ovom ćemo članku detaljno opisati kako možete raditi s bazom podataka i kodom kako biste iskoristili prednosti zero downtime deployment-a.
Problemi s bazom podataka
Ako imate stateless aplikaciju koja ne pohranjuje nikakve podatke u Bazi podataka, možete odmah dobiti zero downtime deployment. Nažalost, velika većina softvera mora negdje pohraniti podatke. Zato trebate dvaput razmisliti prije nego što izvršite bilo kakve promjene u shemi. Prije nego što se duboko zaronimo u detalje kako promijeniti shemu na način koji omogućuje implementaciju bez zastoja, prvo se usredotočimo na shemu upravljanja verzijama.
Shema upravljanja verzijama
U ovom ćemo članku koristiti kao alat za upravljanje verzijama (napomena: radi se o migracijama baze podataka). Naravno, također ćemo napisati Spring Boot aplikaciju koja ima ugrađenu podršku za Flyway i izvršava migraciju sheme tijekom postavljanja konteksta aplikacije. Kada koristite Flyway, možete pohraniti skripte migracije u mapu vaših projekata (po defaultu u classpath:db/migration). Ovdje možete vidjeti primjer takvih datoteka migracije
└── db
└── migration
├── V1__init.sql
├── V2__Add_surname.sql
├── V3__Final_migration.sql
└── V4__Remove_lastname.sqlU ovom primjeru vidimo 4 scenarija migracije koji, ako nisu ranije izvršeni, bit će izvršeni jedan za drugim prilikom pokretanja aplikacije. Pogledajmo jednu od datoteka (V1__init.sql) kao primjer.
KREIRAJ TABLICU OSOBA (
id BIGINT GENERIRAN PO ZADANOJ POSTAVCI KAO IDENTITET,
ime varchar(255) ne može biti NULL,
prezime varchar(255) ne može biti NULL
);
umetni u OSOBA (ime, prezime) vrijednosti ('Dave', 'Syer');Sve savršeno govori samo za sebe: možete koristiti SQL za definiranje kako vaša baza podataka treba biti promijenjena. Za više informacija o Spring Bootu i Flywayu, pogledajte .
Korištenjem alata za upravljanje verzijama sa Spring Bootom, dobivate dvije velike prednosti:
- odvajate promjene u bazi podataka od promjena u kodu
- migracija baze podataka se događa zajedno s puštanjem vaše aplikacije, tj. vaš proces implementacije se pojednostavljuje
Rješavanje problema s bazom podataka
U sljedećem dijelu članka usredotočit ćemo se na dva pristupa promjenama u bazi podataka.
- povratna nekompatibilnost
- povratna kompatibilnost
Prvi će biti razmatran kao upozorenje da ne trebate provoditi zero downtime deployment bez prethodne pripreme… Drugi nudi rješenje kako možete izvršiti implementaciju bez zastoja i istovremeno održavati povratnu kompatibilnost.
Naš projekt na kojem ćemo raditi bit će jednostavna aplikacija Spring Boot Flyway koja ima Osoba s ime i prezime u bazi podataka (napomena: Osoba je tablica, aime i prezime – to su polja unutar nje). Želimo preimenovati prezime u prezime.
Pretpostavke
Prije nego što se upustimo u detalje, potrebno je postaviti nekoliko pretpostavki u vezi s našim aplikacijama. Glavni rezultat koji želimo postići bit će prilično jednostavan proces.
Napomena. Business PRO-TIP. Pojednostavljenje procesa može vam uštedjeti puno novca na održavanju (što više ljudi radi u vašoj tvrtki, više novca možete uštedjeti)!
Ne trebate raditi povrat baze podataka
To pojednostavljuje proces implementacije (neki povrati baze podataka su praktički nemogući, na primjer povrat brisanja). Preferiramo vraćanje samo aplikacija. Tako, čak i ako imate različite baze podataka (npr. SQL i NoSQL), vaš deployment pipeline će izgledati jednako.
Treba imati SVAKADA mogućnost vraćanja aplikacije na jednu verziju unatrag (ne više)
Povratak se treba izvoditi samo po potrebi. Ako trenutna verzija ima grešku koju nije lako ispraviti, trebamo imati mogućnost ponovnog vraćanja na posljednju radnu verziju. Pretpostavljamo da je ta posljednja radna verzija prethodna. Održavanje kompatibilnosti koda i baze podataka za više od jednog izdanja bilo bi izuzetno teško i skupo.
Napomena. Za veću čitljivost, u okviru ovog članka promijenit ćemo glavnu verziju aplikacije.
Korak 1: Izvorno stanje
Verzija aplikacije: 1.0.0
Verzija Baze podataka: v1
Komentar
Ovo će biti izvorno stanje aplikacije.
Promjene Baze podataka
Baza podataka sadrži last_name.
KREIRAJ TABLICU OSOBA (
id BIGINT GENERISAN PO ZADATKU KAO IDENTITET,
first_name varchar(255) NOT NULL,
last_name varchar(255) NOT NULL
);
umetni u OSOBE (first_name, last_name) vrijednosti ('Dave', 'Syer');Promjene koda
Aplikacija skladišti podatke o osobi u prezime:
/*
* 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
+ "]";
}
}Povratno nekompatibilno preimenovanje stupca
Razmotrimo primjer kako promijeniti ime stupca:
Pažnja. Sljedeći primjer namjerno će dovesti do pogreške. Prikazujemo to kako bismo demonstrirali problem kompatibilnosti baze podataka.
Verzija aplikacije: 2.0.0.BAD
Verzija Baze podataka: v2bad
Komentar
Trenutne promjene NE dopuštaju nam pokretanje dva instanca (stare i nove) istovremeno. Stoga će zero downtime deployment biti teško postići (uzimajući u obzir pretpostavke, to je zapravo nemoguće).
A/B testiranje
Trenutna situacija je takva da imamo aplikaciju verzije 1.0.0, razvijena u produkciji, i Baza podataka v1. Moramo rasporediti drugi primjerak aplikacije, verzije 2.0.0.BAD, i ažurirati bazu podataka na v2bad.
Koraci:
- raspoređen je novi primjerak aplikacije verzije
2.0.0.BAD, koji ažurira bazu podataka nav2bad - u bazi podataka
v2badstupacprezimeviše ne postoji — promijenjen je naprezime - ažuriranje baze podataka i aplikacije je uspješno prošlo, i neki primjerci rade u
1.0.0, drugi — u2.0.0.BAD. Svi su povezani s bazom podatakav2bad - svi primjerci verzije
1.0.0počet će davati greške, jer će pokušati umetnuti podatke u stupacprezime, koji više ne postoji - svi primjerci verzije
2.0.0.BADće raditi bez problema
Kao što vidite, ako napravimo povratno nekompatibilne promjene u bazi podataka i aplikaciji, A/B testiranje je nemoguće.
Povrat aplikacije
Pretpostavimo da nakon pokušaja izvršiti A/B deployment (napomena: vjerovatno je autor ovdje mislio na A/B testiranje) odlučimo da trebamo vratiti aplikaciju na verziju 1.0.0. Pretpostavimo da ne želimo napraviti povratak baze podataka.
Koraci:
- zaustavljamo instancu aplikacije verzije
2.0.0.BAD - baza podataka je još uvijek
v2bad - jer verzija
1.0.0ne razumije što jeprezime, vidjet ćemo pogreške - pakao je pobijedio, više se ne možemo vratiti
Kao što vidite, ako napravimo unatrag nespojive promjene u BDP i aplikaciji, ne možemo se vratiti na prethodnu verziju.
Logovi izvođenja skripte
Scenarij unatrag nespojiv:
01) Pokrenite 1.0.0
02) Pričekajte da se aplikacija (1.0.0) pokrene
03) Generirajte osobu pozivom POST localhost:9991/person na verziju 1.0.0
04) Pokrenite 2.0.0.BAD
05) Pričekajte da se aplikacija (2.0.0.BAD) pokrene
06) Generirajte osobu pozivom POST localhost:9991/person na verziju 1.0.0 <-- ovo bi trebalo propasti
07) Generirajte osobu pozivom POST localhost:9992/person na verziju 2.0.0.BAD <-- ovo bi trebalo proći
Pokretanje aplikacije u verziji 1.0.0
Generiranje osobe u verziji 1.0.0
Slanje posta na 127.0.0.1:9991/person. Ovo je odgovor:
{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}
Pokretanje aplikacije u verziji 2.0.0.BAD
Generiranje osobe u verziji 1.0.0
Slanje posta na 127.0.0.1:9991/person. Ovo je odgovor:
curl: (22) Zahtjevani URL vratio grešku: 500 Interna greška poslužitelja
Generiranje osobe u verziji 2.0.0.BAD
Slanje posta na 127.0.0.1:9995/person. Ovo je odgovor:
{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}Promjene Baze podataka
Skripta za migraciju koja preimenuje prezime u prezime
Izvorna Flyway skripta:
KREIRAJ TABLICU OSOBA (
id BIGINT GENERISAN PO ZADATKU KAO IDENTITET,
first_name varchar(255) NOT NULL,
last_name varchar(255) NOT NULL
);
umetni u OSOBE (first_name, last_name) vrijednosti ('Dave', 'Syer');Skripta koja preimenuje prezime.
-- Ova promjena je unatrag nespojiva - ne možete provoditi A/B testiranje
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;Promjene koda
Promijenili smo ime polja lastName na prezime.
Preimenovanje stupca unatrag kompatibilnim načinom
Ovo je najčešća situacija s kojom se možemo susresti. Moramo provesti unatrag nespojive promjene. Već smo dokazali da za implementaciju bez zastoja ne bismo trebali samo primjenjivati migraciju baze podataka bez dodatnih radnji. U ovom dijelu članka napravit ćemo 3 implementacije aplikacije zajedno s migracijama baze podataka kako bismo postigli željeni rezultat i zadržali unatrag kompatibilnost.
Napomena. Podsjetimo se da imamo BDP verzije
v1. Sadrži stupceimeiprezime. Moramo promijenitiprezimenaprezime. Također imamo aplikaciju verzije1.0.0,koja još ne koristiprezime.
Korak 2: Dodavanje surname
Verzija aplikacije: 2.0.0
Verzija Baze podataka: v2
Komentar
Dodajući novi stupac i kopirajući njegov sadržaj, stvaramo unatrag kompatibilne promjene u BDP-u. U isto vrijeme, ako vratimo JAR ili imamo radni stari JAR, neće se pokvariti tijekom izvođenja.
Objavljujemo novu verziju
Koraci:
- izvršite migraciju BDP-a, kako biste stvorili novi stupac
prezime. Sada je vaša BDP verzijav2 - kopirajte podatke iz
prezimeuprezime. Napominjemo, što ako imate puno ovih podataka, trebali biste razmotriti paketnu migraciju! - napisite kod gdje se koriste OBA i novi, i stari stupac. Sada vaša aplikacija verzije
2.0.0 - pročitajte vrijednost iz stupca
prezime, ako nijenull, ili iz last_name, akoprezimenije zadano. Možete uklonitigetLastName()iz koda, jer će vraćatinullpri vraćanju vaše aplikacije s3.0.0do2.0.0.
Ako koristite Spring Boot Flyway, ova dva koraka će se izvršiti prilikom pokretanja verzije 2.0.0 aplikacije. Ako ručno pokrećete alat za upravljanje verzijama baze podataka, morat ćete napraviti ta dva različita koraka (prvo ručno ažurirajte verziju baze podataka, a zatim postavite novu aplikaciju).
Važno. Zapamtite da novi stupac NE SMIJE biti NOT NULL. Ako radite vraćanje, stara aplikacija ne zna za novi stupac i neće ga postaviti tijekom
Insert.Ali ako dodate ovo ograničenje, a vaša baza podataka će bitiv2, to će zahtijevati postavljanje vrijednosti novog stupca. Što će dovesti do kršenja ograničenja.Važno. Trebali biste ukloniti metodu
getLastName(), budući da u verziji3.0.0u kodu ne postoji pojam stupcaprezime. To znači da će tamo biti postavljeni null. Možete zadržati metodu i dodati provjere nanull, ali je puno bolje rješenje osigurati da ste u logicigetSurname()odabrali ispravnu nenull vrijednost.
A/B testiranje
Trenutna situacija je takva da imamo aplikaciju verzije 1.0.0, implementirano na produkciji, i baza podataka u v1. Moramo implementirati drugu instancu aplikacije verzije 2.0.0, koja će ažurirati bazu podataka do v2.
Koraci:
- raspoređen je novi primjerak aplikacije verzije
2.0.0, koji ažurira bazu podataka nav2 - ujedno su neki upiti obrađivani instancama verzije
1.0.0 - a ažuriranje je prošlo uspješno, i imate nekoliko radnih instanci aplikacije verzije
1.0.0i ostalih verzija2.0.0.Svi komuniciraju s bazom podataka uv2 - verzija
1.0.0ne koristi u bazi podataka stupac surname, a verzija2.0.0koristi. Oni se ne ometaju međusobno, i ne bi trebale biti greške. - verzija
2.0.0pohranjuje podatke i u starom i u novom stupcu, što osigurava unazadnu kompatibilnost
Važno. Ako imate bilo kakve upite koji broje stavke na temelju vrijednosti iz starog / novog stupca, trebali biste zapamtiti da sada imate duplicirane vrijednosti (najvjerojatnije se još uvijek migriraju). Na primjer, ako želite prebrojati broj korisnika čija prezimena (kako god se zvao stupac) počinju slovom
A, do završetka migracije podataka (old→newMožete imati neusklađene podatke ako izvršavate upit na novom stupcu.
Povrat aplikacije
Trenutno imamo aplikaciju verzije 2.0.0 i bazu podataka u v2.
Koraci:
- vratite svoju aplikaciju na verziju
1.0.0. - verzija
1.0.0ne koristi stupac u bazi podatakaprezime, tako da bi povratak trebao biti uspješan.
Promjene baze podataka
Baza podataka sadrži stupac pod nazivom prezime.
Izvorni Flyway skript:
KREIRAJ TABLICU OSOBA (
id BIGINT GENERISAN PO ZADATKU KAO IDENTITET,
first_name varchar(255) NOT NULL,
last_name varchar(255) NOT NULL
);
umetni u OSOBE (first_name, last_name) vrijednosti ('Dave', 'Syer');Skript za dodavanje prezime.
Pažnja. Zapamtite da NE TREBA dodavati nikakva ograničenja NOT NULL na dodani stupac. Ako vratite JAR, stara verzija neće znati za dodani stupac i automatski će mu postaviti vrijednost NULL. U slučaju da takvo ograničenje postoji, stara aplikacija će jednostavno puknuti.
-- NAPOMENA: Ovo polje ne može imati ograničenje NOT NULL jer, ako se povuče, stara verzija neće znati za ovo polje
-- i uvijek će ga postaviti na NULL
ALTER TABLE OSOBA DODAJ prezime varchar(255);
-- PRETPOSTAVLJAMO DA JE TO BRZA MIGRACIJA - U SUPROTNOM BIH MORALE MIGRIRATI U SERIJAMA
UPDATE OSOBA POSTAVI OSOBA.prezime = OSOBA.prezime;Promjene koda
Skladištimo podatke kako u prezime, tako i u prezime. Pri tome čitamo iz prezime, jer je ovaj stupac najaktuelniji. Tokom implementacije, neki upiti mogli su biti obrađeni instancom aplikacije koja još nije ažurirana.
/*
* 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
+ "]";
}
}Korak 3: Uklanjanje last_name iz koda
Verzija aplikacije: 3.0.0
Verzija Baze podataka:v3
Komentar
Napomena prev.: Očigledno, u izvornom članku autor je greškom kopirao tekst ovog bloka iz koraka 2. U ovom koraku trebaju se izvršiti izmjene u kodu aplikacije usmjerene na uklanjanje funkcionalnosti koja koristi stupac prezime.
Dodavanjem novog stupca i kopiranjem njegovog sadržaja, stvorili smo unazad kompatibilne promjene u bazi podataka. Također, ako povučemo JAR ili imamo funkcionalni stari JAR, on se neće slomiti tokom izvršenja.
Povrat aplikacije
Trenutno imamo aplikaciju verzije 3.0.0 i bazu podataka v3. Verzija 3.0.0 ne čuva podatke u prezime. To znači da u prezime se drži najaktuelnija informacija.
Koraci:
- vratite svoju aplikaciju na verziju
2.0.0. - verzija
2.0.0koristi iprezimeiprezime. - verzija
2.0.0uzeti ćeprezime, ako nije nula, inače —prezime
Promjene Baze podataka
U bazi podataka nema strukturnih promjena. Izvršava se sljedeći skript koji provodi konačnu migraciju starih podataka:
-- PRETPOSTAVLJAMO DA JE TO BRZA MIGRACIJA - U SUPROTNOM BIH MORALE MIGRIRATI U SERIJAMA
-- TAKOĐE NE PROVERAVAMO DA LI NE PREKRAJAMO POSTOJEĆE UNOSE. MORALE BIH UPOREDITI
-- VERSIJE UNOSA DA ZALOŽIMO DA AKO VEĆ POSTOJI UNOS SA VIŠIM BROJEM VERZIJE
-- NEĆEMO GA PREKLAPATI.
UPDATE OSOBA POSTAVI OSOBA.prezime = OSOBA.prezime;
-- ODBACIVANJE OGRANIČENJA NOT NULL; U SUPROTNOM ĆETE POKUŠATI UMETNUTI NULL VREDNOST PREZIME
-- SA OGRANIČENJEM NOT NULL.
ALTER TABLE OSOBA MODIFICIRAJ KOLONU prezime varchar(255) NULL DEFAULT NULL;Promjene koda
Napomena: Opis ove jedinice je također pogrešno preuzet od strane autora s koraka 2. Prema logici narativa članka, izmjene u kodu na ovom koraku trebaju biti usmjerene na uklanjanje elemenata koji upravljaju kolonama. prezime.
Podatke čuvamo kako u prezime, tako i u prezime. Osim toga, čitamo iz kolone prezime, jer je ona najrelevantnija. Tijekom implementacije, neki zahtjevi mogu biti obrađeni instancom koja još nije ažurirana.
/*
* 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
+ "]";
}
}Korak 4: Uklanjanje last_name iz Baze Podataka
Verzija aplikacije: 4.0.0
Verzija Baze podataka: v4
Komentar
S obzirom na to da kod verzije 3.0.0 nije koristio kolonu prezime, tijekom izvršenja neće se dogoditi ništa loše ako se vratimo na 3.0.0 nakon uklanjanja kolone iz baze podataka.
Logovi izvođenja skripte
Provest ćemo to na sljedeći način:
01) Pokrenite 1.0.0
02) Sačekajte da aplikacija (1.0.0) pokrene
03) Generirajte osobu pozivanjem POST localhost:9991/person za verziju 1.0.0
04) Pokrenite 2.0.0
05) Sačekajte da aplikacija (2.0.0) pokrene
06) Generirajte osobu pozivanjem POST localhost:9991/person za verziju 1.0.0
07) Generirajte osobu pozivanjem POST localhost:9992/person za verziju 2.0.0
08) Ugasite aplikaciju (1.0.0)
09) Pokrenite 3.0.0
10) Sačekajte da aplikacija (3.0.0) pokrene
11) Generirajte osobu pozivanjem POST localhost:9992/person za verziju 2.0.0
12) Generirajte osobu pozivanjem POST localhost:9993/person za verziju 3.0.0
13) Ugasite aplikaciju (3.0.0)
14) Pokrenite 4.0.0
15) Sačekajte da aplikacija (4.0.0) pokrene
16) Generirajte osobu pozivanjem POST localhost:9993/person za verziju 3.0.0
17) Generirajte osobu pozivanjem POST localhost:9994/person za verziju 4.0.0
Pokretanje aplikacije u verziji 1.0.0
Generiranje osobe u verziji 1.0.0
Slanje posta na 127.0.0.1:9991/person. Ovo je odgovor:
{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}
Pokretanje aplikacije u verziji 2.0.0
Generiranje osobe u verziji 1.0.0
Slanje posta na 127.0.0.1:9991/person. Ovo je odgovor:
{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}
Generiranje osobe u verziji 2.0.0
Slanje posta na 127.0.0.1:9992/person. Ovo je odgovor:
{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}
Gašenje aplikacije 1.0.0
Pokretanje aplikacije u verziji 3.0.0
Generiranje osobe u verziji 2.0.0
Slanje posta na 127.0.0.1:9992/person. Ovo je odgovor:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}
Generiranje osobe u verziji 3.0.0
Slanje posta na 127.0.0.1:9993/person. Ovo je odgovor:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}
Gašenje aplikacije 2.0.0
Pokretanje aplikacije u verziji 4.0.0
Generiranje osobe u verziji 3.0.0
Slanje posta na 127.0.0.1:9993/person. Ovo je odgovor:
{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}
Generiranje osobe u verziji 4.0.0
Slanje posta na 127.0.0.1:9994/person. Ovo je odgovor:
{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}Izmjene Baze Podataka
U vezi s tim v3 samo uklanjamo kolonu prezime i dodajemo nedostajuća ograničenja.
-- Uklonite stupac
ALTER TABLE PERSON DROP last_name;
-- Dodajte ograničenja
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;Promjene koda
Nema promjena u kodu.
Izvještaj
Uspješno smo primijenili povratno nekompatibilnu promjenu imena stupca, izvršavajući nekoliko povratno kompatibilnih isporuka. Ispod je sažetak izvršenih radnji:
- isporuka aplikacije verzije
1.0.0sv1sheme Baze podataka (ime stupca =prezime) - isporuka aplikacije verzije
2.0.0,koje čuva podatke uprezimeiprezime. Aplikacija čita izprezime. Baza podataka je u verzijiv2, koja sadrži stupce kaoprezime, kao isurname. surnameje kopija last_name. (NAPOMENA: ovaj stupac ne bi trebao imati ograničenje not null) - isporuka aplikacije verzije
3.0.0, koji čuva podatke samo uprezimei čita iz surname. Što se tiče Baze podataka, izvršava se posljednja migracijaprezimeuprezime. Također, ograničenje NOT NULL uklanja se sprezime. Baza podataka je sada u verzijiv3 - isporuka aplikacije verzije
4.0.0— u kodu nisu izvršene nikakve promjene. Isporuka baze podatakav4, koja uklanjaprezime. Ovdje možete dodati sva nedostajuća ograničenja u Bazi podataka.
Slijedeći ovaj pristup, uvijek se možete vratiti na jednu verziju unazad, ne kršeći kompatibilnost baze podataka / aplikacije.
Kod
Sav kod korišten u ovom članku dostupan je na . Ispod je dodatni opis.
Projekti
Nakon kloniranja repozitorija, vidjet ćete sljedeću strukturu mapa.
├── boot-flyway-v1 - 1.0.0 verzija aplikacije sa v1 shemom
├── boot-flyway-v2 - 2.0.0 verzija aplikacije sa v2 shemom (povratno kompatibilna - aplikaciju je moguće vratiti)
├── boot-flyway-v2-bad - 2.0.0.BAD verzija aplikacije sa v2bad shemom (povratno nekompatibilna - aplikaciju nije moguće vratiti)
├── boot-flyway-v3 - 3.0.0 verzija aplikacije sa v3 shemom (aplikaciju je moguće vratiti)
└── boot-flyway-v4 - 4.0.0 verzija aplikacije sa v4 shemom (aplikaciju je moguće vratiti)Skripte
Možete pokrenuti skripte opisane u donjim skriptama, koje će demonstrirati povratno kompatibilne i nekompatibilne promjene u Bazi podataka.
Da biste vidjeli slučaj s povratno kompatibilnim promjenama, pokrenite:
./scripts/scenario_backward_compatible.shA da biste vidjeli slučaj s povratno nekompatibilnim promjenama, pokrenite:
./scripts/scenario_backward_incompatible.shSpring Boot Sample Flyway
Svi primjeri su preuzeti iz Spring Boot Sample Flyway.
Možete pogledati http://localhost:8080/flyway, tamo je popis skripti.
Ovaj primjer također uključuje H2 konzolu (na adresi http://localhost:8080/h2-console), tako da možete pregledavati stanje baze podataka (URL jdbc po defaultu — jdbc:h2:mem:testdb).
Dodatno
Također pročitajte druge članke na našem blogu:
Izvor: habr.com
