
Ez a cikk részletesen bemutatja, hogyan lehet megoldani az adatbázisok kompatibilitási problémáit a telepítés során. Megmutatjuk, mi történhet a termelési alkalmazásaival, ha megpróbál telepíteni előkészítés nélkül. Ezután végigvezetjük az alkalmazás életszakaszain, amelyek szükségesek a nullás leállási idő eléréséhez (megjegyzés: a továbbiakban – zero downtime). Műveleteink eredményeként a visszafelé inkompatibilis adatbázis-változtatásokat visszafelé kompatibilis módon alkalmazzuk.
Ha szeretne elmélyedni a cikk kódtöredékeiben, azokat itt találja: .
Bevezetés
Zero downtime deployment
Mi ez a misztikus zero downtime deployment? Можно сказать, это когда ваше приложение развернуто так, что вы можете успешно вводить новую версию приложения на продакшн, в то время как пользователь не замечает его недоступности. С точки зрения пользователя и компании, это наилучший из возможных сценариев деплоя, поскольку таким образом можно вводить новые функции и устранять ошибки без перебоев в работе.
Hogyan érhetjük el ezt? Több módszer is létezik, íme az egyik:
- telepítse az Ön szolgáltatásának 1. verzióját
- végezze el az adatbázis migrációját
- telepítse a szolgáltatása 2. verzióját párhuzamosan az 1. verzióval
- amint látja, hogy a 2. verzió megfelelően működik, távolítsa el az 1. verziót
- kész!
Egyszerű, ugye? Sajnos nem ennyire egyszerű, és ezt később részletesen is megvizsgáljuk. Most nézzük meg egy elég elterjedt telepítési folyamatot – a blue green deployment-et.
Hallott már a ? С Cloud Foundry это чрезвычайно легко сделать. Просто гляньте на , ahol ezt részletesebben kifejtjük. Röviden összefoglalva, emlékezzünk, hogyan kell végezni a blue green deployment-et:
- biztosítani kell, hogy két példányban fusson a production kód ("blue" és "green");
- az összes forgalmat a blue környezetbe kell irányítani, azaz a production URL-jeinek oda kell mutatniuk;
- az összes alkalmazásváltoztatást a green környezetben kell telepíteni és tesztelni;
- az URL-eket a blue-ról a green környezetre kell váltani
A Blue green deployment egy olyan megközelítés, amely lehetővé teszi, hogy új funkciókat vezessen be anélkül, hogy aggódnia kellene, hogy a production megsérül. Ennek oka, hogy ha bármi történik, könnyen visszaállhat az előző környezetbe, csak egy "kapcsoló kipöccintésével".
Az összes korábbi tudnivaló után felmerülhet a kérdés: Mi köze a zero downtime-nak a Blue green telepítéshez?
Nos, sok közö van, mivel két példány fenntartása ugyanazon környezetből dupla erőfeszítést igényel a karbantartásukhoz. Ezért van, hogy egyes csapatok, ahogyan azt , ezt a megközelítést követik:
A másik lehetőség az, hogy ugyanazt az adatbázist használjuk, kék-zöld váltókat létrehozva a web- és domain rétegek számára. Ebben a megközelítésben az adatbázisok gyakran problémát okozhatnak, különösen, amikor meg kell változtatni a sémát egy új szoftververzió támogatásához.
Itt elérkeztünk a cikk fő problémájához. Adatbázis. Nézzük meg újra ezt a mondatot.
végezze el az adatbázis migrációját.
Most fel kell tennie magának a kérdést — mi van, ha az adatbázis visszafordíthatatlan változása történik? Nem fog-e eltörni az első verzióm? Valójában pontosan ez fog történni...
Így, még ha a zero downtime / kék-zöld telepítés óriási előnyökkel is jár, a cégek hajlamosak a következő biztonságosabb telepítési folyamatot követni alkalmazásaik esetében:
- készítsen egy csomagot az új alkalmazásverzióval
- zárja le a futó alkalmazást
- futtassa az adatbázis migrációs szkriptjeit
- telepítse és indítsa el az új alkalmazásverziót
Ebben a cikkben részletesen ismertetjük, hogyan dolgozhat az adatbázissal és a kóddal, hogy kihasználhassa a zero downtime telepítés előnyeit.
Adatbázis problémák
Ha van egy állapotmentes alkalmazása, amely nem tárol adatokat az adatbázisban, akkor azonnal elérheti a zero downtime telepítést. Sajnos a szoftverek nagy része kénytelen valahol tárolni az adatokat. Ezért érdemes alaposan átgondolnia, mielőtt bármilyen változtatást végez a sémán. Mielőtt elmerülnénk a sémaváltoztatás olyan részleteiben, amelyek lehetővé teszik a leállás nélküli telepítést, először a verziókezelési sémára kell összpontosítanunk.
Verziókezelési séma
Ebben a cikkben használni fogjuk mint eszközt a verziókezeléshez (megjegyzés: adatbázis migrációkról van szó). Természetesen írni fogunk egy Spring Boot alkalmazást is, amely beépített támogatást nyújt a Flyway számára, és a séma migrálását a projekt kontextusának beállítása során végzi. A Flyway használatakor tárolhatja a migrációs szkripteket a projektjei mappájában (alapértelmezés szerint a classpath:db/migration). Itt láthat egy példát az ilyen migrációs fájlokra
└── db
└── migration
├── V1__init.sql
├── V2__Add_surname.sql
├── V3__Final_migration.sql
└── V4__Remove_lastname.sqlEbben a példában 4 migrációs forgatókönyvet látunk, amelyek, ha korábban nem hajtották végre őket, egymás után fognak végrehajtódni az alkalmazás indításakor. Nézzük meg az egyik fájlt (V1__init.sql) példaként.
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');Minden világos, ami önmagáért beszél: használhat SQL-t arra, hogy meghatározza, hogyan kell módosítani az adatbázisát. További információk a Spring Boot és a Flyway témájában találhatók a .
A Spring Boot verziókezelő eszköz használatával 2 nagy előnyt kap:
- elválasztja az adatbázis-változásokat a kódváltozásoktól
- az adatbázis-migráció együtt történik az alkalmazás telepítésével, azaz egyszerűsíti a telepítési folyamatot
Adatbázis problémák megoldása
A cikk következő részében a két megközelítés áttekintésére fogunk összpontosítani az adatbázis-változásokkal kapcsolatban.
- visszafelé inkompatibilitás
- visszafelé kompatibilitás
Az első figyelmeztetésként kerül bemutatásra, hogy nem érdemes zero downtime telepítést végezni előkészítés nélkül... A második megoldást kínál arra, hogyan lehet a telepítést megszakítás nélkül végrehajtani, miközben fenntartjuk a visszafelé kompatibilitást.
A projekt, amin dolgozni fogunk, egy egyszerű Spring Boot Flyway alkalmazás lesz, amely tartalmazza a entitásokra ne figyeljetek, azok a domainhez tartoznak és a teszt keretében nem kerülnek figyelembe vételre. Tehát, egy ilyen gráf struktúrához a láncok keresési kérdése így nézne ki: a first_name és last_name az adatbázisban (megj.: entitásokra ne figyeljetek, azok a domainhez tartoznak és a teszt keretében nem kerülnek figyelembe vételre. Tehát, egy ilyen gráf struktúrához a láncok keresési kérdése így nézne ki: ez egy táblázat, és a first_name és last_name ez pedig egy mező benne). Azt szeretnénk, ha átneveznénk last_name be. surname.
Feltételezések
Mielőtt mélyebbre ásnánk a részletekbe, fontos néhány feltételezést megállapítani a projektjeinkkel kapcsolatban. A fő eredmény, amit el szeretnénk érni, egy viszonylag egyszerű folyamat lesz.
Megjegyzés. Business PRO-TIP: A folyamatok egyszerűsítése sok pénzt takaríthat meg a karbantartás során (minél több ember dolgozik a cégedben, annál több pénzt spórolhatsz)!
Nem szabad adatbázis visszaállítást végezni
Ez egyszerűsíti a telepítési folyamatot (bizonyos adatbázis-visszaállítások gyakorlatilag lehetetlenek, például egy törlés visszaállítása). Csak az alkalmazásokat szeretnénk visszaállítani. Így még ha különböző adatbázisok vannak is (például SQL és NoSQL), a telepítési pipelined ugyanúgy fog kinézni.
Mindig legyen lehetőség az alkalmazás visszaállítására egy verzióval korábbi állapotba (legfeljebb egyet).
A visszaállítást csak akkor kell végrehajtani, ha szükséges. Ha a jelenlegi verzióban van egy hiba, amelyet nehéz kijavítani, lehetőségünk kell, hogy legyen visszatérni az utolsó működő verzióhoz. Feltételezzük, hogy ez az utolsó működő verzió az előző. A kód és az adatbázis kompatibilitásának fenntartása több kiadáshoz rendkívül bonyolult és költséges lenne.
Megjegyzés. A nagyobb olvashatóság érdekében a cikk keretein belül a főverziót fogjuk módosítani.
1. lépés: Kiinduló állapot
Alkalmazás verzió: 1.0.0
DB verzió: v1
Megjegyzés
Ez lesz az alkalmazás kiinduló állapota.
DB változások
A DB tartalmazza 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');Kód változások
Az alkalmazás a Person adatokat tárolja a 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
+ "]";
}
}Visszafelé nem kompatibilis oszlop átnevezés
Nézzük meg a példát arra, hogyan lehet átnevezni egy oszlopot:
Figyelem. A következő példa szándékosan hibát fog okozni. Ezt az adatbázis kompatibilitásának problémájának bemutatására mutatjuk be.
Alkalmazás verzió: 2.0.0.BAD
DB verzió: v2bad
Megjegyzés
A jelenlegi változások NEM teszik lehetővé, hogy két példányt (a régit és az újat) párhuzamosan futtassunk. Így a zero downtime telepítés nehezen elérhető (figyelembe véve a feltételezéseket, ez gyakorlatilag lehetetlen).
A/B tesztelés
A jelenlegi helyzet az, hogy van egy alkalmazásunk, amelynek verziója 1.0.0, az éles rendszerben van telepítve, és a DB v1. Telepítenünk kell egy második példányt az alkalmazásból, amelynek verziója 2.0.0.BAD, és frissítenünk kell az adatbázist a v2bad.
Lépések:
- telepített új példány az alkalmazás verziójával
2.0.0.BAD, amely frissíti az adatbázist av2bad - az adatbázisban
v2badoszloplast_nametöbbé nem létezik — átneveztéksurname - az adatbázis és az alkalmazás frissítése sikeresen megtörtént, és néhány példány működik a
1.0.0, mások pedig a2.0.0.BAD. Mindezek kapcsolódnak a DB-hezv2bad - minden példány verziója
1.0.0hibákat kezd el dobni, mert próbálnak adatokat beszúrni az oszlopbalast_name, amely már nem létezik - minden példány verziója
2.0.0.BADproblémamentesen fognak működni
Ahogy látható, ha visszafelé nem kompatibilis változtatásokat végzünk az adatbázison és az alkalmazáson, akkor az A/B tesztelés lehetetlenné válik.
Alkalmazás visszaállítása
Tegyük fel, hogy az A/B telepítési kísérlet után (megjegyzés: valószínűleg itt az író A/B tesztelésre gondolt) azt döntöttük, hogy vissza kell állítanunk az alkalmazást a verzióra 1.0.0. Tegyük fel, hogy nem akarjuk visszaállítani az adatbázist.
Lépések:
- leállítjuk az alkalmazás példányát, a verziója
2.0.0.BAD - az adatbázis még mindig
v2bad - mivel a verzió
1.0.0nem érti, mi azsurname, hibákat fogunk látni - a pokol kiszabadult, már nem tudunk visszatérni
Ahogy látja, ha visszafelé inkompatibilis változtatásokat hajtunk végre az adatbázison és az alkalmazáson, nem tudunk visszatérni a korábbi verzióhoz.
A script futtatási naplója
Visszafelé inkompatibilis forgatókönyv:
01) Futtassa a 1.0.0-t
02) Várjon, amíg az alkalmazás (1.0.0) elindul
03) Generáljon egy személyt a POST localhost:9991/person hívással a 1.0.0 verzión
04) Futtassa a 2.0.0.BAD-t
05) Várjon, amíg az alkalmazás (2.0.0.BAD) elindul
06) Generáljon egy személyt a POST localhost:9991/person hívással a 1.0.0 verzión <-- ennek meg kellene buknia
07) Generáljon egy személyt a POST localhost:9992/person hívással a 2.0.0.BAD verzión <-- ennek át kellene mennie
Alkalmazás indítása 1.0.0 verzióban
Személy generálása 1.0.0 verzióban
POST küldése a 127.0.0.1:9991/person-ra. Ez a válasz:
{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}
Alkalmazás indítása 2.0.0.BAD verzióban
Személy generálása 1.0.0 verzióban
POST küldése a 127.0.0.1:9991/person-ra. Ez a válasz:
curl: (22) A kért URL hibaüzenetet adott vissza: 500 Belső Szolgáltatás Hiba
Személy generálása a 2.0.0.BAD verzióban
POST küldése a 127.0.0.1:9995/person-ra. Ez a válasz:
{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}DB változások
A migrációs script, amely átnevezi last_name be. surname
Eredeti Flyway script:
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');A script, amely átnevezi last_name.
-- Ez a változtatás visszafelé inkompatibilis - nem lehet A/B tesztelni
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;Kód változások
Megváltoztattuk a mező nevét lastName Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata surname.
Az oszlop visszafelé kompatibilis módon történő átnevezése
Ez a leggyakoribb helyzet, amelybe beleütközhetünk. Visszafelé inkompatibilis változtatásokat kell végrehajtanunk. Már bizonyítottuk, hogy a leállás nélküli telepítésekhez nem alkalmazhatunk csak úgy adatbázis-migrációt, további lépések nélkül. Ebben a cikkben három alkalmazás telepítést fogunk végezni az adatbázis-migrációkkal együtt, hogy elérjük a kívánt eredményt, miközben megőrizzük a visszafelé kompatibilitást.
Megjegyzés. Emlékeztetünk, hogy van egy adatbázisunk a verzióval
v1. Ez tartalmazza az oszlopokatfirst_nameéslast_name. Meg kell változtatnunklast_nameGyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használatasurname. Van egy alkalmazásunk a verzióval1.0.0,, amely még nem használjasurname.
2. lépés: Hozzáadjuk a surname-t
Alkalmazás verzió: 2.0.0
DB verzió: v2
Megjegyzés
Új oszlop hozzáadásával és annak tartalmának másolásával visszafelé kompatibilis adatbázis-változtatásokat végzünk. Ugyanakkor, ha vissza kell állítanunk a JAR-t, vagy van egy működő régi JAR-unk, az futás közben nem fog meghibásodni.
Új verzió kiadása
Lépések:
- végezze el az adatbázis-migrációt az új oszlop létrehozásához
surname. Most az Ön adatbázisa a verzióvalv2 - másolja az adatokat a
last_namebe.surname. Figyeljünk arra, hogy, és ha sok ilyen adat van, érdemes fontolóra venni a tömeges migrációt! - írja meg a kódot, ahol használják BÁRMILYEN és új, és a régi oszlop. Most az alkalmazásod verziója
2.0.0 - olvassa az értéket az oszlopból
surname, ha az nemnull, vagy a last_name, hasurnamenincs megadva. Eltávolíthatod agetLastName()metódust a kódból, mivel az hibát fog adninullha visszaállítod az alkalmazásodat3.0.0tól2.0.0.
Ha a Spring Boot Flyway-t használod, ezek a lépések az alkalmazás verziójának indításakor történnek. Ha manuálisan futtatod az adatbázis-kezelő eszközt, akkor két különböző lépést kell végrehajtanod (először manuálisan frissítened kell az adatbázis verzióját, majd telepítened kell az új alkalmazást). 2.0.0 Ne feledd, hogy az újonnan létrehozott oszlop
Fontos. NEM LEHET NOT NULL lenni . Ha visszaállítod, a régi alkalmazás nem tud az új oszlopról, és nem állítja be azt aBeszúrásakor.
De ha ezt a korlátozást hozzáadod, és az adatbázisod, akkor az megköveteli az új oszlop értékének beállítását. Ez korlátozási hibákhoz vezet.v2El kell távolítanod a metódustFontos. , mivel a verzióban
getLastName()a kódban nincs oszlop fogalom3.0.0. Ez azt jelenti, hogy null értéket állítanak be. Meghagyhatod a metódust, és hozzáadhatsz ellenőrzéseket alast_name, de sokkal jobb megoldás megbizonyosodni arról, hogy a logikábannullgetSurname()a helyes nem-null értéket választottad., amely éles környezetben van telepítve, és az adatbázisban
A/B tesztelés
A jelenlegi helyzet az, hogy van egy alkalmazásunk, amelynek verziója 1.0.0. Telepítenünk kell a második példányt a verzióból v1, amely frissíti az adatbázist 2.0.0eközben néhány kérdést a verzió példányai kezeltek v2.
Lépések:
- telepített új példány az alkalmazás verziójával
2.0.0, amely frissíti az adatbázist av2 - a frissítés sikeresen megtörtént, és több működő verziópéldányod van az alkalmazásból
1.0.0 - és a többi verzióból
1.0.0Mind újra kommunikálnak az adatbázissal2.0.0.nem használja az adatbázisban a surname oszlopot, míg a verzióv2 - verzió
1.0.0használja. Ezek nem zavarják egymást, és nem kellene hibáknak lenniük.2.0.0megőrzi az adatokat mind a régi, mind az új oszlopban, ami biztosítja a visszafelé kompatibilitást - verzió
2.0.0Ha vannak bármilyen kérdéseid, amelyek elemeket számítanak a régi / új oszlop értékei alapján, ne feledd, hogy most adatduplikációk lesznek (valószínűleg még mindig migrálnak). Például, ha meg szeretnéd számolni a felhasználók számát, akiknek a vezetékneve (bármilyen néven is hívják az oszlopot) 'b'-vel kezdődik, akkor az adatmigrálás befejezése előtt
Fontos. a 'old' oszlopnál ellentmondásos adatokkal találkozhatsz, ha a új oszlopra kérdezel.
AJelenleg van egy alkalmazásod a verzióbólés az adatbázis→newvissza kell állítani az alkalmazásodat a verzióhoz
Alkalmazás visszaállítása
nem használja az adatbázisban az oszlopot 2.0.0 és az adatbázisban v2.
Lépések:
- visszaállíthatja az alkalmazását egy korábbi verzióra
1.0.0. - verzió
1.0.0nem használja az adatbázisban az oszlopotsurname, ezért a visszaállításnak sikeresnek kell lennie
DB módosítások
Az adatbázis oszlopot tartalmaz a következő névvel last_name.
Eredeti Flyway szkript:
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');Hozzáadási szkript surname.
Figyelem. Ne felejtsd el, hogy NEM ADDHATSZ SEMMILYEN NOT NULL megszorítást a hozzáadott oszlophoz. Ha visszaállítod a JAR-t, a régi verzió nem tud a hozzáadott oszlopról, és automatikusan NULL értéket ad neki. Ha van ilyen megszorítás, a régi alkalmazás egyszerűen hibát fog okozni.
-- MEGJEGYZÉS: Ez a mező nem lehet NOT NULL megszorítással, mert ha visszaállítod, a régi verzió nem tud a mezőről
-- és mindig NULL-ra állítja
ALTER TABLE PERSON ADD surname varchar(255);
-- FELTÉTELEZZÜK, HOGY EZ EGY GYORS MIGRÁCIÓ - KÜLÖNBEN CÉLSZERŰ BATCH-EBEN MIGRÁLNI
UPDATE PERSON SET PERSON.surname = PERSON.last_nameKód változások
Az adatokat úgy tároljuk, mint a last_name-ban, valamint a surname. Eközben olvasunk a last_name-ból, mivel ez az oszlop a legaktuálisabb. A telepítés során egyes lekérdezéseket lehet, hogy olyan alkalmazáspéldány kezelte, amely még nem volt frissítve.
/*
* 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
+ "]";
}
}3. lépés: last_name eltávolítása a kódból
Alkalmazás verzió: 3.0.0
DB verzió:v3
Megjegyzés
Megjegyzés: Nyilvánvalóan az eredeti cikkben a szerző tévesen másolta ezt a blokk szöveget a 2. lépésből. Ezen a lépésen a kód módosításait kell végrehajtani az oszlopot használó funkciók eltávolítására. last_name.
Új oszlop hozzáadásával és tartalmának másolásával hátra kompatibilis változásokat hoztunk létre az adatbázisban. Emellett, ha visszaállítjuk a JAR-t vagy van egy működő régi JAR, az nem fog hibát okozni a futás során.
Alkalmazás visszaállítása
Jelenleg az alkalmazásunk a következő verziójú: 3.0.0 és az adatbázis v3. Verzió: 3.0.0 nem tárolja az adatokat a last_name. Ez azt jelenti, hogy a surname tartalmazza a legaktuálisabb információt.
Lépések:
- visszaállíthatja az alkalmazását egy korábbi verzióra
2.0.0. - verzió
2.0.0használ éslast_nameéssurname. - verzió
2.0.0meg fogja kapnisurname, ha nem null, különben —last_name
DB változások
Az adatbázisban nincsenek strukturális módosítások. A következő szkript fut, amely végrehajtja a régi adatok végső migrálását:
-- FELTÉTELEZZÜK, HOGY EZ EGY GYORS MIGRÁCIÓ - KÜLÖNBEN CÉLSZERŰ BATCH-EBEN MIGRÁLNI
-- Azt SEM állítjuk, hogy nem felülírjuk a meglévő bejegyzéseket. Össze kellene hasonlítanunk
-- a bejegyzések verzióit, hogy biztosak legyünk abban, hogy ha van már egy bejegyzés
-- magasabb verziószámmal, azt nem írjuk felül.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;
-- A NOT NULL megszorítás eltávolítása; különben NULL értéket próbálsz beszúrni a last_name-ra
-- NOT_NULL megszorítással.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;Kód változások
Megjegyzés: Ennek a blokknak a leírását is tévesen másolta a szerző a 2. lépésből. A cikk narratív logikájának megfelelően a kód módosításainak ezen a lépésen a az oszlopot kezelő elemek eltávolítására kell irányulnia. last_name.
Az adatokat úgy tároljuk, mint a last_name-ban, valamint a surname. Ezen kívül olvasunk az oszlopból last_name, mivel ez a legaktuálisabb. A telepítés során néhány lekérdezést olyan példány kezelhet, amely még nem frissült.
/*
* 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
+ "]";
}
}4. lépés: last_name eltávolítása az adatbázisból
Alkalmazás verzió: 4.0.0
DB verzió: v4
Megjegyzés
A verzió kód miatt 3.0.0 nem használtuk az oszlopot last_name, a végrehajtás során nem történik semmi rossz, ha visszalépünk 3.0.0 az adatbázisból az oszlop eltávolítása után.
A script futtatási naplója
Ezt az alábbi módon fogjuk megtenni:
01) Futtassuk a 1.0.0-át
02) Várjunk az alkalmazás (1.0.0) elindulására
03) Generáljunk egy személyt a 1.0.0 verzióra a POST localhost:9991/person hívással
04) Futtassuk a 2.0.0-át
05) Várjunk az alkalmazás (2.0.0) elindulására
06) Generáljunk egy személyt a 1.0.0 verzióra a POST localhost:9991/person hívással
07) Generáljunk egy személyt a 2.0.0 verzióra a POST localhost:9992/person hívással
08) Öljük meg az alkalmazást (1.0.0)
09) Futtassuk a 3.0.0-át
10) Várjunk az alkalmazás (3.0.0) elindulására
11) Generáljunk egy személyt a 2.0.0 verzióra a POST localhost:9992/person hívással
12) Generáljunk egy személyt a 3.0.0 verzióra a POST localhost:9993/person hívással
13) Öljük meg az alkalmazást (3.0.0)
14) Futtassuk a 4.0.0-át
15) Várjunk az alkalmazás (4.0.0) elindulására
16) Generáljunk egy személyt a 3.0.0 verzióra a POST localhost:9993/person hívással
17) Generáljunk egy személyt a 4.0.0 verzióra a POST localhost:9994/person hívással
Alkalmazás indítása a 1.0.0-ás verzióban
Személy generálása az 1.0.0-ás verzióban
POST küldése a 127.0.0.1:9991/person címre. Ez a válasz:
{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}
Alkalmazás indítása a 2.0.0-ás verzióban
Személy generálása az 1.0.0-ás verzióban
POST küldése a 127.0.0.1:9991/person címre. Ez a válasz:
{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}
Személy generálása a 2.0.0-ás verzióban
POST küldése a 127.0.0.1:9992/person címre. Ez a válasz:
{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}
1.0.0 alkalmazás leállítása
Alkalmazás indítása a 3.0.0-ás verzióban
Személy generálása a 2.0.0-ás verzióban
POST küldése a 127.0.0.1:9992/person címre. Ez a válasz:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}
Személy generálása a 3.0.0-ás verzióban
POST küldése a 127.0.0.1:9993/person címre. Ez a válasz:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}
2.0.0 alkalmazás leállítása
Alkalmazás indítása a 4.0.0-ás verzióban
Személy generálása a 3.0.0-ás verzióban
POST küldése a 127.0.0.1:9993/person címre. Ez a válasz:
{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}
Személy generálása a 4.0.0-ás verzióban
POST küldése a 127.0.0.1:9994/person címre. Ez a válasz:
{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}Adatbázis változások
Kapcsolatban v3 egyszerűen eltávolítjuk az oszlopot last_name és hozzáadjuk a hiányzó korlátozásokat.
-- ELMETETT OSZLOP
ALTER TABLE PERSON DROP last_name;
-- KORLÁTOZÁSOK HOZZÁADÁSA
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;Kód változások
Nincs változás a kódban.
Következtetés
Sikeresen alkalmaztuk a nem hátra kompatibilis oszlopnév-változást több hátra kompatibilis telepítéssel. Az elvégzett lépések összefoglalása:
- alkalmazás telepítése a
1.0.0av1adatbázis séma (oszlop neve =last_name) - alkalmazás telepítése a
2.0.0,amely adatokat tárollast_nameéssurname. Az alkalmazás olvas alast_name. Az adatbázis a verzióban találhatóv2, amely oszlopokat tartalmaz, mint példáullast_name, valamintvezetéknév. vezetéknéva l másolatát jelentiast_name. (MEGJEGYZÉS: ez az oszlop nem rendelkezhet not null megszorítással) - alkalmazás telepítése a
3.0.0, amely csak adatokat tárolsurnameés olvas a vezetéknévből. Ami az adatbázist illeti, a legutolsó migráció zajlik.last_namebe.surname. A megszorítás szintén . Ha visszaállítod, a régi alkalmazás nem tud az új oszlopról, és nem állítja be azt a levonásra kerül alast_name. Az adatbázis most a verzióban találhatóv3 - alkalmazás telepítése a
4.0.0— a kódban nincsenek változtatások. Az adatbázis telepítésev4, amely eltávolítjalast_name. Itt bármilyen hiányzó megszorítást hozzáadhat az adatbázishoz.
E megközelítés követésével mindig visszaléphet egy verziót anélkül, hogy megsértené az adatbázis / alkalmazás kompatibilitását.
Kód
A cikkben használt összes kód elérhető a . További leírás következik.
Projektek
A tároló klónozása után a következő mappastruktúrát fogja látni.
├── boot-flyway-v1 - az alkalmazás 1.0.0 verziója v1 séma szerint
├── boot-flyway-v2 - az alkalmazás 2.0.0 verziója v2 séma szerint (visszafelé kompatibilis - az alkalmazás visszaállítható)
├── boot-flyway-v2-bad - az alkalmazás 2.0.0.BAD verziója v2bad séma szerint (visszafelé nem kompatibilis - az alkalmazás nem állítható vissza)
├── boot-flyway-v3 - az alkalmazás 3.0.0 verziója v3 séma szerint (az alkalmazás visszaállítható)
└── boot-flyway-v4 - az alkalmazás 4.0.0 verziója v4 séma szerint (az alkalmazás visszaállítható)Szkriptek
Futtathatja az alábbi scriptben leírt szkripteket, amelyek bemutatják a visszafelé kompatibilis és nem kompatibilis változásokat az adatbázisban.
Ahhoz, hogy lássa a visszafelé kompatibilis változások esetét,futtassa:
. /scripts/scenario_backward_compatible.shÉs ahhoz, hogy lássa a visszafelé nem kompatibilis változások esetét,futtassa:
. /scripts/scenario_backward_incompatible.shSpring Boot Sample Flyway
Minden példa a Spring Boot Sample Flyway-ból származik.
Megnézheti a http://localhost:8080/flyway, ott van a szkriptek listája.
Ez a példa tartalmaz egy H2 konzolt is (cím: http://localhost:8080/h2-console), hogy megtekinthesse az adatbázis állapotát (az alapértelmezett jdbc URL — jdbc:h2:mem:testdb).
További információ
Olvasd el többi cikkünket a blogunkban:
Forrás: habr.com
