Żero Waqfien Skjerament u Databases

Żero Waqfien Skjerament u Databases

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

└── db
 └── migration
     ├── V1__init.sql
     ├── V2__Add_surname.sql
     ├── V3__Final_migration.sql
     └── V4__Remove_lastname.sql

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:

  1. tiġi skjerata istanza ġdida tal-applikazzjoni tal-verżjoni 2.0.0.BADli jaġġorna d-database għal v2bad
  2. fid-database v2bad kolonna last_name m'għadux jeżisti - inbidel għal surname
  3. 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
  4. 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
  5. 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.

Passi:

  1. nwaqqfu l-istanza tal-applikazzjoni tal-verżjoni 2.0.0.BAD
  2. id-database għadu v2bad
  3. mill-verżjoni 1.0.0 ma jifhimx x'inhu surname, se naraw żbalji
  4. 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:

  1. twettaq migrazzjoni tad-database biex toħloq kolonna ġdida surname. Issa l-verżjoni tad-DB tiegħek v2
  2. 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!
  3. ikteb il-kodiċi fejn jintużaw IT-TNEJN и ġdidU il-qodma kolonna. Issa l-verżjoni tal-app tiegħek 2.0.0
  4. 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:

  1. tiġi skjerata istanza ġdida tal-applikazzjoni tal-verżjoni 2.0.0li jaġġorna d-database għal v2
  2. sadanittant xi talbiet ġew ipproċessati mill-istanzi tal-verżjoni 1.0.0
  3. 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
  4. 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.
  5. 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 (oldnew 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:

  1. erġa' lura l-applikazzjoni tiegħek għall-verżjoni 1.0.0.
  2. 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:

  1. erġa' lura l-applikazzjoni tiegħek għall-verżjoni 2.0.0.
  2. verżjoni 2.0.0 użi u last_name и surname.
  3. 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:

  1. skjerament tal-verżjoni tal-applikazzjoni 1.0.0 с v1 skema tad-database (isem tal-kolonna = last_name)
  2. 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)
  3. 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
  4. 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).

addizzjonalment

Aqra wkoll artikli oħra fuq il-blog tagħna:

Sors: www.habr.com

Żid kumment