
DĂ«sen Artikel erklĂ€ert am Detail wĂ©i d'DatebankkompatibilitĂ©itsprobleemer beim Deployment lĂ©isen. Mir soen Iech wat mat Ăre Produktiounsapplikatioune ka geschĂ©ien wann Dir probĂ©iert ouni virleefeg Virbereedung z'installĂ©ieren. Mir ginn dann duerch d'Uwendungsliewenszyklusstadien dĂ©i noutwenneg sinn fir null Ausdauer ze hunn (ca. Lane: weider - null Ausdauer). D'Resultat vun eisen Operatiounen wĂ€ert sinn d'RĂ©ck-inkompatibel Datebank Ă€nneren op eng zrĂ©ck-kompatibel ManĂ©ier Ă«mzesetzen.
Wann Dir de Code Beispiller aus dem Artikel wëllt verstoen, kënnt Dir se op .
Aféierung
Null Downtime Deployment
Wat eng mystesch null Ănnerbriechung? Dir kĂ«nnt soen dat ass wann Ăr Applikatioun esou agesat gĂ«tt datt Dir erfollegrĂ€ich eng nei Versioun vun der Applikatioun an d'Produktioun afĂ©iere kĂ«nnt, wĂ€hrend de Benotzer seng OnverfĂŒgbarkeet net bemierkt. Aus enger Benotzer- a Firmenperspektiv ass dĂ«st dee beschtmĂ©igleche Deployment Szenario well et erlaabt nei Features agefouert ze ginn an Bugs ouni Ănnerbriechung ze fixĂ©ieren.
Wéi dëst z'erreechen? Et gi verschidde Weeër, hei ass ee vun hinnen:
- deploy Versioun Nr 1 vun Ărem Service
- eng Datebankmigratioun ausféieren
- Deploy Versioun #2 vun Ărem Service parallel mat Versioun #1
- soubal Dir gesitt datt d'Versioun Nummer 2 funktionnéiert wéi se soll, huelt d'Versioun Nummer 1 ewech
- gemaach!
Einfach, ass et net? Leider ass et net sou einfach, a mir wÀerten dat spéider am Detail kucken. Loosst eis elo en aneren zimlech allgemengen Deploymentprozess iwwerpréiwen - blo gréng Deployment.
Hutt Dir jeemools héieren ? Cloud Foundry mécht dëst extrem einfach. Kuckt just un , wou mir dat méi am Detail beschreiwen. Fir kuerz ze resuméieren, loosst eis Iech drun erënneren wéi Dir blo gréng Deployment maacht:
- sĂ©cherstellen datt zwee Exemplare vun Ărem Produktiounscode ("blo" a "grĂ©ng") funktionnĂ©ieren;
- all VerkĂ©ier an dĂ©i blo Ămwelt riichten, d.h. sou datt d'Produktioun URLen dohinner weisen;
- deployĂ©ieren an testen all Applikatioun Ănnerungen an engem grĂ©ngen Ămfeld;
- schalt URLen aus blo op grĂ©ng Ămwelt
Blo grĂ©ng Deployment ass eng Approche dĂ©i Iech erlaabt nei Features einfach z'informĂ©ieren ouni Iech Suergen iwwer d'Produktioun ze briechen. DĂ«st ass wĂ©inst der Tatsaach datt och wann eppes geschitt, Dir kĂ«nnt einfach zrĂ©ck an dat viregt Ămfeld zrĂ©ckrollen andeems Dir einfach "e Schalter flĂ©isst."
Nodeems Dir all déi uewe gelies hutt, kënnt Dir d'Fro stellen: Wat huet Null Downtime mat Blue Green Deployment ze dinn?
Gutt, si hunn zimmlech vill gemeinsam, well zwee Exemplare vum selwechten Ămfeld erhalen, erfuerdert duebel Effort fir se z'erhalen. Dofir behaapten e puer Equippen , befollegt eng Variatioun vun dĂ«ser Approche:
Eng aner Optioun ass déi selwecht Datebank ze benotzen, blo-gréng Schalter fir de Web an Domain Schichten ze kreéieren. An dëser Approche kann d'Datebank dacks e Problem sinn, besonnesch wann Dir sÀi Schema Ànneren musst fir eng nei Versioun vun der Software z'ënnerstëtzen.
An hei komme mer zum Haaptproblem an dësem Artikel. Datebank. Loosst eis dëse Saz nach eng Kéier kucken.
eng Datebankmigratioun ausféieren.
Elo musst Dir Iech d'Fro stellen - wat wann d'DatebankÀnnerung net zréckkompatibel ass? WÀert meng éischt Versioun vun der App net briechen? TatsÀchlech ass dat genau wat wÀert geschéien ...
Also, och trotz de grousse Virdeeler vun Null Downtime / Blogréng Deployment, tendéieren Firmen de folgende méi séchere Prozess fir hir Uwendungen z'installéieren:
- preparéieren e Pak mat enger neier Versioun vun der Applikatioun
- eng lafend Applikatioun zoumaachen
- Scripte lafen fir d'Datebank ze migréieren
- deployéieren an eng nei Versioun vun der Applikatioun starten
An dĂ«sem Artikel wĂ€erte mir detaillĂ©iert wĂ©i Dir mat Ărer Datebank a Code schaffe kĂ«nnt fir vun Null Downtime Deployment ze profitĂ©ieren.
Datebank Problemer
Wann Dir eng stateless Applikatioun hutt, dĂ©i keng Daten an der Datebank spĂ€ichert, kĂ«nnt Dir direkt Null-Downtime-Deployment krĂ©ien. Leider muss dĂ©i meescht Software Daten iergendwou spĂ€icheren. Dofir sollt Dir zweemol nodenken ier Dir Ănnerungen am Circuit maacht. Ier mer an d'Detailer kommen wĂ©i een de Schema Ă€nnert, sou datt d'Deployment ouni Downtime mĂ©iglech ass, loosst eis fir d'Ă©ischt op de Versiounsschema konzentrĂ©ieren.
Versioun Schema
An dĂ«sem Artikel wĂ€erte mir benotzen als Versiounskontrollinstrument (ca. Iwwersetzung: mir schwĂ€tzen iwwer Datebankmigratiounen). Natierlech wĂ€erte mir och eng Spring Boot Applikatioun schreiwen dĂ©i agebaute Flyway Support huet a Schema Migratioun ausfĂ©iert wĂ€rend den Applikatiounskontext opstellt. Wann Dir Flyway benotzt, kĂ«nnt Dir Migratiounsskripter an Ărem Projeten Dossier spĂ€icheren (par dĂ©faut an classpath:db/migration). Hei kĂ«nnt Dir e Beispill vun esou Migratioun Fichieren gesinn
âââ db
âââ migration
âââ V1__init.sql
âââ V2__Add_surname.sql
âââ V3__Final_migration.sql
âââ V4__Remove_lastname.sqlAn dĂ«sem Beispill gesi mir 4 Migratiounsskripter dĂ©i, wann net virdru ausgefouert goufen, een nom aneren ausgefouert ginn wann d'Applikatioun ufĂ€nkt. Loosst eis ee vun de Fichieren kucken (V1__init.sql) als Beispill.
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');Alles ass perfekt selbstĂ€nneg: Dir kĂ«nnt SQL benotze fir ze definĂ©ieren wĂ©i Ăr Datebank geĂ€nnert soll ginn. Fir mĂ©i Informatiounen iwwert FrĂ©ijoer Boot an Flyway, kontrollĂ©ieren aus .
Andeems Dir e Quellkontrollinstrument mat Spring Boot benotzt, kritt Dir 2 grouss Virdeeler:
- Dir trennt Datebank Ănnerungen aus Code Ănnerungen
- Datebank Migratioun geschitt zesumme mat der Ausrollung vun Ărer Applikatioun, d.h. Ăren Ofbauprozess ass vereinfacht
Troubleshooting Datebank Problemer
An der nĂ€chster Sektioun vum Artikel konzentrĂ©iere mir eis op zwou Approche fir Datebank Ănnerungen ze kucken.
- réckgÀngeg Inkompatibilitéit
- Réckkompatibilitéit
Déi éischt gëtt als Warnung ugesinn datt Dir keng Null-Downtime-Deployment ouni virleefeg Virbereedung sollt maachen ... Déi zweet bitt eng Léisung fir wéi Dir en Deployment ouni Downtime ausféiere kënnt a glÀichzÀiteg Réckkompatibilitéit erhalen.
Eise Projet un deem mir wĂ€erte schaffen ass eng einfach Spring Boot Flyway Applikatioun dĂ©i huet Person Ń first_name Đž last_name an der Datebank (ca. Iwwersetzung: Person ass en DĂ«sch a first_name Đž last_name - dat sinn d'Felder dran). Mir wĂ«llen Ă«mbenennen last_name ĐČ surname.
Viraussetzungen
Ier mer an d'Detailer kommen, ginn et e puer Viraussetzungen déi mir iwwer eis Uwendungen maache mussen. Den Haaptresultat, dee mir erreechen wëllen, ass e relativ einfache Prozess.
D'Notiz. Business PRO-TIP. Vereinfachung vu Prozesser kann Iech vill Suen op ĂnnerstĂ«tzung spueren (wat mĂ©i Leit Dir fir Ăr Firma schafft, wat Dir mĂ©i Sue kĂ«nnt spueren)!
Kee Grond fir d'Datebank zréckzekréien
DĂ«st vereinfacht den DĂ©tachement Prozess (e puer Datebank Rollbacks si bal onmĂ©iglech, wĂ©i LĂ€schen Rollback). Mir lĂ©iwer nĂ«mmen Uwendungen zrĂ©ckrollen. Op dĂ«s ManĂ©ier, och wann Dir verschidden Datenbanken hutt (zum Beispill SQL an NoSQL), wĂ€ert Ăr Deployment Pipeline d'selwecht ausgesinn.
Et muss ĂMMER mĂ©iglech sinn d'Applikatioun eng Versioun zrĂ©ck ze rullĂ©ieren (net mĂ©i)
Rollback soll nëmme gemaach ginn wann néideg. Wann et e Feeler an der aktueller Versioun ass, deen net einfach fixéiert ass, sollte mir fÀeg sinn op déi lescht funktionnéiert Versioun zréckzekommen. Mir huelen un datt dës lescht funktionnéiert Versioun déi virdrun ass. Code an Datebank Kompatibilitéit erhalen fir méi wéi ee Rollout wier extrem schwéier an deier.
D'Notiz. Fir méi Liesbarkeet, wÀerte mir an dësem Artikel d'Haaptversioun vun der Applikatioun Ànneren.
Schrëtt 1: Ufank Staat
App Versioun: 1.0.0
DB Versioun: v1
Commentaire
Dëst wÀert den initialen Zoustand vun der Applikatioun sinn.
Datebank Ănnerungen
DB enthÀlt 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');Code Ănnerungen
D'Applikatioun spÀichert Persoundaten an 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
+ "]";
}
}Zeréck inkompatibel Kolonn ëmbenennen
Loosst eis e Beispill kucken wéi Dir e Kolonnnumm Ànnert:
Opgepasst. Dat folgend Beispill wÀert d'Saache bewosst briechen. Mir weisen dëst fir de Problem vun der Datebankkompatibilitéit ze weisen.
App Versioun: 2.0.0.BAD
DB Versioun: v2bad
Commentaire
DĂ©i aktuell Ănnerungen erlaben eis NET zwou Instanzen (al an nei) zur selwechter ZĂ€it ze lafen. Also, Null Downtime Deployment wĂ€ert schwĂ©ier z'erreechen (wann Viraussetzunge berĂŒcksichtegt ginn, ass et tatsĂ€chlech onmĂ©iglech).
A/B Test
Déi aktuell Situatioun ass datt mir eng Applikatioun Versioun hunn 1.0.0, an der Produktioun agesat, an Datebank v1. Mir mussen eng zweet Instanz vun der Applikatioun ofsetzen, Versioun 2.0.0.BAD, an update der Datebank op v2bad.
Schrëtt:
- eng nei Instanz vun der Versiounsapplikatioun gëtt ofgesat
2.0.0.BADdéi d'Datebank aktualiséiertv2bad - an der Datebank
v2badKolonnlast_nameexistéiert net méi - et gouf geÀnnertsurname - D'Datebank an d'Applikatioun Update war erfollegrÀich an e puer Instanzen lafen
1.0.0, anerer - an2.0.0.BAD. Alles ass mat der Datebank verbonnenv2bad - all Instanzen vun der Versioun
1.0.0wÀert ufÀnken Feeler ze geheien well se probéieren Daten an d'Kolonn ze setzenlast_namedéi et net méi gëtt - all Instanzen vun der Versioun
2.0.0.BADwÀert ouni Problemer schaffen
WĂ©i Dir gesitt, wa mir rĂ©ckgĂ€ngeg inkompatibel Ănnerungen un der Datebank an der Applikatioun maachen, ass A/B Testen onmĂ©iglech.
Applikatioun Réckroll
Loosst eis unhuelen datt nodeems Dir probéiert A/B Deployment ze maachen (ca. per .: den Auteur gemengt wahrscheinlech A / B Testen hei) hu mir décidéiert datt mir d'Applikatioun op d'Versioun mussen zréckrollen 1.0.0. Loosst eis soen datt mir d'Datebank net wëllen zréckrollen.
Schrëtt:
- mir stoppen der Versioun Applikatioun Instanz
2.0.0.BAD - d'Datebank ass nach ëmmer
v2bad - zanter der Versioun
1.0.0versteet net wat et asssurname, mir wÀerte Feeler gesinn - D'HÀll ass gebrach, mir kënnen net méi zréck
WĂ©i Dir gesitt, wa mir rĂ©ckgĂ€ngeg inkompatibel Ănnerunge vun der Datebank an der Applikatioun maachen, kĂ«nne mir net op dĂ©i viregt Versioun zrĂ©ckrollen.
Skript Ausféierung Logbicher
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"}Datebank Ănnerungen
Migratiounsskript dat Ă«mbenannt last_name ĐČ surname
Source Flyway Skript:
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');Skript dat ëmbenannt last_name.
-- This change is backward incompatible - you can't do A/B testing
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;Code Ănnerungen
Mir hunn den Numm vum Feld geÀnnert lastName op surname.
Eng Kolonn ëmbenennen op eng zréckkompatibel Manéier
DĂ«st ass dĂ©i heefegst Situatioun dĂ©i mir begĂ©inen. Mir mussen rĂ©ckgĂ€ngeg inkompatibel Ănnerungen maachen. Mir hu scho bewisen datt fir Null-Downtime Deployment, mir sollten net einfach Datebankmigratioun ouni zousĂ€tzlech SchrĂ«tt applizĂ©ieren. An dĂ«ser Rubrik vum Artikel wĂ€erte mir 3 Deployementer vun der Applikatioun zesumme mat Datebankmigratiounen ausfĂ©ieren fir dat gewĂ«nschte Resultat z'erreechen an d'RĂ©ckkompatibilitĂ©it z'erhalen.
D'Notiz. Erënneren, datt mir eng Versioun Datebank hunn
v1. Et enthÀlt Kolonnenfirst_nameОlast_name. Mir mussen Ànnerenlast_nameopsurname. Mir hunn och App Versioun1.0.0,déi nach net benotzt gëttsurname.
Schrëtt 2: Numm derbÀi
App Versioun: 2.0.0
DB Versioun: v2
Commentaire
Andeems Dir eng nei Kolonn bĂ€idrĂ©it a sĂ€in Inhalt kopĂ©iert, kreĂ©iere mir zrĂ©ckkompatibel Datebank Ănnerungen. Zur selwechter ZĂ€it, wa mir de JAR zrĂ©ckrollen oder en alen JAR lafen, brĂ©cht en net wĂ€hrend der AusfĂ©ierung.
Mir rullen eng nei Versioun aus
Schrëtt:
- eng Datebankmigratioun ausféieren fir eng nei Kolonn ze kreéieren
surname. Elo Ăr DB Versiounv2 - kopĂ©ieren Daten aus
last_nameĐČsurname. Opgepasstdatt wann Dir vill vun dĂ«sen DonnĂ©eĂ«n hutt, sollt Dir Batchmigratioun betruechten! - schreiwen de Code wou se benotzt ginn BĂ©id Đž ĐœĐŸĐČŃĐčan dĂ©i al Kolonn. Elo Ăr App Versioun
2.0.0 - liesen de WĂ€ert aus der Kolonn
surname, wann et net assnulloder aus last_name, wann asurnamenet uginn. Dir kĂ«nnt lĂ€schengetLastName()aus dem Code, well et gĂ«tt erausginnnullwann Dir Ăr Applikatioun zrĂ©ckrollt3.0.0ze2.0.0.
Wann Dir Spring Boot Flyway benotzt, ginn dës zwee Schrëtt wÀhrend der Versioun vum Startup gemaach 2.0.0 Uwendungen. Wann Dir d'Datebankversiouns-Tool manuell leeft, musst Dir zwou verschidde Saache maachen fir dëst ze maachen (éischt d'db Versioun manuell aktualiséieren an dann déi nei Applikatioun ofsetzen).
Et ass wichteg. Erënneren, datt déi nei geschaf Kolonn SOLL NET ze sinn NET NULL. Wann Dir eng Rollback maacht, weess déi al Applikatioun net iwwer déi nei Kolonn a wÀert se net wÀhrend der Installatioun installéieren
Insert.Awer wann Dir dĂ«s AschrĂ€nkung bĂ€idrĂ©it an Ăr db wĂ€ert sinnv2, DĂ«st wĂ€ert erfuerderen de WĂ€ert vun der neier Kolonn ze setzen. Wat zu Violatioune vu Restriktiounen fĂ©iert.Et ass wichteg. Dir sollt d'Method ewechhuelen
getLastName(), well an der Versioun3.0.0Et gëtt kee Konzept vun enger Kolonn am Codelast_name. Dëst bedeit datt null do gesat gëtt. Dir kënnt d'Method verloossen a Schecken derbÀi firnull, mee eng vill besser Léisung wier sécher ze stellen, datt an der LogikgetSurname()Dir hutt de richtegen Net-NullwÀert gewielt.
A/B Test
Déi aktuell Situatioun ass datt mir eng Applikatioun Versioun hunn 1.0.0, op Produktioun ofgesat, an d'Datebank an v1. Mir mussen eng zweet Instanz vun der Versiounsapplikatioun ofsetzen 2.0.0déi d'Datebank aktualiséieren v2.
Schrëtt:
- eng nei Instanz vun der Versiounsapplikatioun gëtt ofgesat
2.0.0déi d'Datebank aktualiséiertv2 - an der TëschenzÀit goufen e puer Ufroe vu Versiounsinstanzen veraarbecht
1.0.0 - den Update war erfollegrÀich an Dir hutt verschidde Lafen Instanzen vun der Versiounsapplikatioun
1.0.0an aner Versiounen2.0.0.Jiddereen kommunizéiert mat der Datebank anv2 - Versioun
1.0.0benotzt net den Numm Kolonn an der Datebank, mÀ d'Versioun2.0.0benotzt. Si stéieren net mateneen, an et sollt kee Feeler sinn. - Versioun
2.0.0spÀichert Daten an der aler an der neier Kolonn, a garantéiert Réckkompatibilitéit
Et ass wichteg. Wann Dir Ufroen hutt déi Elementer zielen baséiert op WÀerter aus der aler / neier Kolonn, sollt Dir drun erënneren datt Dir elo duplizéiert WÀerter hutt (wahrscheinlech si se nach ëmmer migréieren). Zum Beispill, wann Dir d'Zuel vun de Benotzer ziele wëllt, deenen hire Familljennumm (egal wéi d'Kolonn genannt gëtt) mam Buschtaf ugefaang huet
A, dann bis d'Datemigratioun fĂ€erdeg ass (oldânewKolonn) Dir hutt vlĂ€icht inkonsistent DonnĂ©eĂ«n wann Dir eng nei Kolonn ufrot.
Applikatioun Réckroll
Elo hu mir App Versioun 2.0.0 an Datebank an v2.
Schrëtt:
- rullt Ăr Applikatioun op d'Versioun zrĂ©ck
1.0.0. - Versioun
1.0.0benotzt keng Kolonn an der Datebanksurname, sou datt d'Rollback erfollegrÀich ass
D'Ănnerung am DB
D'Datebank enthÀlt eng Kolonn mam Numm last_name.
Flyway Quell Skript:
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');Schreift derbÀi surname.
Opgepasst. Denkt drun datt Dir NET NULL AschrÀnkungen op d'Kolonn bÀidréit, déi Dir bÀidréit. Wann Dir de JAR zréckrollt, wÀert déi al Versioun keng Ahnung iwwer déi addéiert Kolonn hunn a se automatesch op NULL setzen. Wann et esou eng Begrenzung gëtt, brécht déi al Applikatioun einfach.
-- 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_nameCode Ănnerungen
Mir spÀicheren Daten als last_name, a surname. GlÀichzÀiteg liesen mir aus last_name, well dës Kolonn déi relevantst ass. WÀrend dem Détachementprozess kënnen e puer Ufroe vun enger Applikatiounsinstanz veraarbecht ginn, déi nach net aktualiséiert gouf.
/*
* 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
+ "]";
}
}Schrëtt 3: Last_name aus dem Code lÀschen
App Versioun: 3.0.0
DB Versioun:v3
Commentaire
Note per.: Scheinbar, am Originalartikel huet den Auteur falsch den Text vun dĂ«sem Block vum SchrĂ«tt kopĂ©iert 2. Op dĂ«sem SchrĂ«tt sollten Ănnerungen am Applikatiounscode gemaach ginn, fir d'FunktionalitĂ©it ze lĂ€schen, dĂ©i d'Kolonn benotzt. last_name.
Andeems Dir eng nei Kolonn bĂ€idrĂ©it a sĂ€in Inhalt kopĂ©iert, hu mir rĂ©ckgĂ€ngeg kompatibel Datebank Ănnerungen erstallt. Och wa mir de JAR zrĂ©ckrollen oder en alen JAR lafen, brĂ©cht et net wĂ€hrend der AusfĂ©ierung.
Applikatioun Réckroll
Momentan hu mir App Versioun 3.0.0 an Datebank v3. Versioun 3.0.0 spÀichert net Daten un last_name. Dat heescht, datt am surname déi aktuellst Informatioun gëtt gespÀichert.
Schrëtt:
- rullt Ăr Applikatioun op d'Versioun zrĂ©ck
2.0.0. - Versioun
2.0.0benotzt anlast_nameĐžsurname. - Versioun
2.0.0wÀert huelensurname, wann et net null ass, soss -last_name
Datebank Ănnerungen
Et gi keng strukturell Ănnerungen an der Datebank. De folgende Skript gĂ«tt ausgefouert fir dĂ©i lescht Migratioun vun den alen DonnĂ©eĂ«n auszefĂ©ieren:
-- 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;Code Ănnerungen
Note per .: D'Beschreiwung vun dĂ«sem Block gouf och falsch vum Auteur vum SchrĂ«tt kopĂ©iert 2. Am Aklang mat der Logik vum Artikel, Ănnerunge vum Code an dĂ«sem SchrĂ«tt solle zielt fir Elementer ze lĂ€schen dĂ©i mat der Kolonn funktionnĂ©ieren last_name.
Mir spÀicheren Daten als last_name, a surname. ZousÀtzlech liesen mir aus der Kolonn last_name, well et am meeschte relevant ass. WÀrend dem Détachementprozess kënnen e puer Ufroe vun enger Instanz veraarbecht ginn, déi nach net aktualiséiert gouf.
/*
* 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
+ "]";
}
}Schrëtt 4: Last_name aus der Datebank erofhuelen
App Versioun: 4.0.0
DB Versioun: v4
Commentaire
Wéinst der Tatsaach, datt d'Versioun Code 3.0.0 hunn d'Kolonn net benotzt last_name, nÀischt Schlechtes wÀert wÀhrend der Ausféierung geschéien wa mir zréck op 3.0.0 nodeems Dir eng Kolonn aus der Datebank ewechgeholl huet.
Skript Ausféierung Logbicher
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"}D'Ănnerung am DB
Relativ v3 mir lÀschen just d'Kolonn last_name an dobÀi vermësst Restriktiounen.
-- 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;Code Ănnerungen
Et gi keng Ănnerungen un de Code.
Konklusioun
Mir hunn erfollegrĂ€ich e RĂ©ck-inkompatibel Spaltennumm Ănnerung applizĂ©iert andeems mir e puer zrĂ©ckkompatibel Deployementer ausfĂ©ieren. DrĂ«nner ass e ResumĂ© vun den Aktiounen dĂ©i gemaach goufen:
- Détachement vun der Applikatioun Versioun
1.0.0Ńv1Datebank Schema (Kolonnnumm =last_name) - DĂ©tachement vun der Applikatioun Versioun
2.0.0,déi Daten spÀichert anlast_nameОsurname. D'Applikatioun liest auslast_name. D'Datebank ass an der Versiounv2enthÀlt Spalten wéilast_nameansurname. surnameass eng Kopie vum last_name. (OPGEPASST: Dës Kolonn dÀerf keng net null Constraint hunn) - Détachement vun der Applikatioun Versioun
3.0.0, dĂ©i nĂ«mmen Daten spĂ€ichert ansurnamea liest aus Familljennumm. Wat d'Datebank ugeet, fĂ«nnt dĂ©i lescht Migratioun stattlast_nameĐČsurname. Och eng Begrenzung NET NULL zrĂ©ckgezunn auslast_name. D'Datebank ass elo an der Versiounv3 - DĂ©tachement vun der Applikatioun Versioun
4.0.0- keng Ănnerungen am Code gemaach. Datebank Deploymentv4, dĂ©i lĂ€schtlast_name. Hei kĂ«nnt Dir all fehlend AschrĂ€nkungen an d'Datebank derbĂ€isetzen.
Andeems Dir dës Approche verfollegt, kënnt Dir ëmmer eng Versioun zréckrollen ouni d'Datebank-/Uwendungskompatibilitéit ze briechen.
Code
All Code an dësem Artikel benotzt ass sinn op . Drënner ass eng zousÀtzlech Beschreiwung.
Projeten
Nodeems Dir de Repository klonen, gesitt Dir déi folgend Dossierstruktur.
âââ 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)Scripten
Dir kĂ«nnt d'Skripte lafen, dĂ©i an de Scripten hei Ă«nnen beschriwwe ginn, dĂ©i zrĂ©ckkompatibel an inkompatibel Ănnerungen an der Datebank weisen.
Fir ze kucken de Fall mat RĂ©ckkompatibel Ănnerungen, lafen:
./scripts/scenario_backward_compatible.shAn ze gesinn Fall mat rĂ©ckgĂ€ngeg inkompatibel Ănnerungen, lafen:
./scripts/scenario_backward_incompatible.shFréijoer Boot Sample Flyway
All Beispiller sinn aus Spring Boot Sample Flyway.
Dir kënnt e Bléck op http://localhost:8080/flyway, et gëtt eng Lëscht vu Scripten.
Dëst Beispill enthÀlt och d'H2 Konsol (at http://localhost:8080/h2-console) sou datt Dir den Datebankstatus kuckt (Standard jdbc URL ass jdbc:h2:mem:testdb).
ZousÀtzlech
Liest och aner Artikelen op eisem Blog:
Source: will.com
