Null seisaku juurutust ja andmebaase

Null seisaku juurutust ja andmebaase

See artikkel selgitab üksikasjalikult, kuidas lahendada juurutamisel andmebaasi ühilduvusprobleeme. Räägime teile, mis võib juhtuda teie tootmisrakendustega, kui proovite juurutada ilma eelneva ettevalmistuseta. Seejärel läbime rakenduse elutsükli etapid, mis on vajalikud nullseisuaega (u. sõidurada: edasi - seisakuid null). Meie toimingute tulemuseks on tagasiühildumatu andmebaasi muudatuse rakendamine tagasiühilduval viisil.

Kui soovite artikli koodinäiteid mõista, leiate need aadressilt GitHub.

Sissejuhatus

Null seisaku kasutuselevõttu

Mis müstiline null seisaku kasutuselevõttu? Võib öelda, et see on siis, kui teie rakendus juurutatakse nii, et saate rakenduse uue versiooni edukalt tootmisse tuua, samas kui kasutaja ei märka selle kättesaamatust. Kasutaja ja ettevõtte seisukohast on see parim võimalik juurutamise stsenaarium, kuna see võimaldab häireteta juurutada uusi funktsioone ja parandada vigu.

Kuidas seda saavutada? On mitmeid viise, siin on üks neist:

  • juurutage oma teenuse versioon nr 1
  • teha andmebaasi migratsioon
  • Juurutage oma teenuse versioon nr 2 paralleelselt versiooniga nr 1
  • niipea kui näete, et versioon nr 2 töötab nii nagu peab, eemaldage versioon nr 1
  • on valmis!

Lihtne, kas pole? Kahjuks pole see nii lihtne ja me vaatame seda üksikasjalikumalt hiljem. Nüüd kontrollime veel ühte üsna levinud juurutusprotsessi – sinirohelist juurutamist.

Kas olete kunagi kuulnud sinine roheline kasutuselevõtt? Cloud Foundry teeb selle väga lihtsaks. Lihtsalt vaata Selle artikli, kus me kirjeldame seda üksikasjalikumalt. Lühidalt kokkuvõtteks tuletame teile meelde, kuidas sinist rohelist juurutamist teha:

  • veenduge, et teie tootmiskoodi kaks koopiat ("sinine" ja "roheline") töötavad;
  • suunata kogu liiklus sinisesse keskkonda, s.t. et tootmis-URL-id suunaksid sinna;
  • juurutada ja testida kõiki rakenduse muudatusi rohelises keskkonnas;
  • lülitage URL-id sinisest roheliseks

Sinine roheline juurutamine on lähenemisviis, mis võimaldab teil hõlpsalt uusi funktsioone juurutada, ilma et peaksite muretsema tootmise katkemise pärast. Selle põhjuseks on asjaolu, et isegi kui midagi juhtub, saate lihtsalt lülitit nipsutades hõlpsasti tagasi minna eelmisele keskkonda.

Pärast kõike ülaltoodut lugedes võite küsida: mis on nullseisakutel pistmist Blue Greeni kasutuselevõtuga?

Noh, neil on üsna palju ühist, kuna sama keskkonna kahe koopia säilitamine nõuab nende hooldamiseks kahekordset pingutust. Seetõttu väidavad mõned meeskonnad Martin Fowler, järgige selle lähenemisviisi variatsiooni:

Teine võimalus on kasutada sama andmebaasi, luues sinakasrohelised lülitid veebi- ja domeenikihtide jaoks. Selle lähenemisviisi korral võib andmebaas sageli olla probleemiks, eriti kui peate selle skeemi muutma, et toetada tarkvara uut versiooni.

Ja siin jõuame selle artikli peamise probleemini. Andmebaas. Vaatame seda fraasi veel kord.

teha andmebaasi migratsioon.

Nüüd tuleb endalt esitada küsimus – mis siis, kui andmebaasi muudatus ei ole tagurpidi ühilduv? Kas minu esimene rakenduse versioon ei lähe katki? Tegelikult juhtub täpselt nii...

Seega, isegi vaatamata nullseisaku / sinise rohelise juurutamise tohututele eelistele, järgivad ettevõtted oma rakenduste juurutamiseks järgmist ohutumat protsessi:

  • koostage pakett rakenduse uue versiooniga
  • sulgege töötav rakendus
  • käivitage andmebaasi migreerimiseks skripte
  • juurutage ja käivitage rakenduse uus versioon

Selles artiklis kirjeldame üksikasjalikult, kuidas saate oma andmebaasi ja koodiga töötada, et kasutada ära ilma seisakuta juurutamist.

Andmebaasi probleemid

Kui teil on olekuta rakendus, mis ei salvesta andmebaasi andmeid, saate koheselt kasutusele võtta ilma seisakuta. Kahjuks peab enamik tarkvara andmeid kuskile salvestama. Seetõttu peaksite enne vooluringis muudatuste tegemist kaks korda mõtlema. Enne kui jõuame üksikasjadesse selle kohta, kuidas skeemi muuta nii, et seisakuta juurutamine oleks võimalik, keskendume esmalt versiooniskeemile.

Versioonide skeem

Selles artiklis me kasutame Lennutee versioonikontrolli tööriistana (u. Tõlge: me räägime andmebaaside migratsioonist). Loomulikult kirjutame ka Spring Booti rakenduse, millel on sisseehitatud Flyway tugi ja mis teostab rakenduse konteksti seadistamise ajal skeemi migratsiooni. Flyway kasutamisel saate migratsiooniskripte salvestada oma projektide kausta (vaikimisi kaustas classpath:db/migration). Siin näete näidet sellistest migratsioonifailidest

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

Selles näites näeme 4 migratsiooniskripti, mida, kui neid pole varem käivitatud, käivitatakse rakenduse käivitumisel üksteise järel. Vaatame ühte faili (V1__init.sql) näiteks.

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õik on täiesti iseenesestmõistetav: saate SQL-i abil määrata, kuidas teie andmebaasi tuleks muuta. Lisateavet Spring Booti ja Flyway kohta leiate siit Spring Boot Docs.

Kui kasutate Spring Bootiga allika juhtimistööriista, saate kaks suurt eelist:

  • eraldate andmebaasi muudatused koodimuudatustest
  • Andmebaasi migratsioon toimub koos teie rakenduse levitamisega, st. teie juurutamisprotsess on lihtsustatud

Andmebaasi probleemide tõrkeotsing

Artikli järgmises osas keskendume andmebaasi muutmise kahele lähenemisviisile.

  • tagasiühilduvus
  • tagasiühilduvus

Esimest käsitletakse hoiatusena, et ilma eelneva ettevalmistuseta ei tohiks teha nullseisaku juurutust... Teine pakub lahenduse, kuidas saab juurutamist teostada ilma seisakuta ja samal ajal säilitada tagasiühilduvust.

Meie projekt, mille kallal töötame, on lihtne Spring Boot Flyway rakendus, millel on Person с first_name и last_name andmebaasis (u. tõlge: Person on tabel ja first_name и last_name - need on väljad selles). Tahame ümber nimetada last_name в surname.

Oletused

Enne üksikasjadesse laskumist peame oma rakenduste kohta tegema paar eeldust. Peamine tulemus, mida tahame saavutada, on üsna lihtne protsess.

Märkus. Business PRO-TIP. Protsesside lihtsustamine võib säästa palju toetuste arvelt (mida rohkem inimesi teie ettevõttes töötab, seda rohkem raha saate säästa)!

Pole vaja andmebaasi tagasi pöörata

See lihtsustab juurutamisprotsessi (mõned andmebaasi tagasipööramised on peaaegu võimatud, näiteks kustutamise tagasipööramine). Eelistame ainult rakenduste tagasipööramist. Nii näeb juurutamise konveier välja sama, isegi kui teil on erinevad andmebaasid (nt SQL ja NoSQL).

Rakendust peab ALATI olema võimalik ühe versiooni võrra tagasi kerida (mitte enam)

Tagasivõtmine tuleks teha ainult vajaduse korral. Kui praeguses versioonis on viga, mida pole lihtne parandada, peaksime suutma naasta uusimale töötavale versioonile. Eeldame, et see viimane tööversioon on eelmine. Koodi ja andmebaasi ühilduvuse säilitamine rohkem kui ühe kasutuselevõtu jaoks oleks äärmiselt keeruline ja kulukas.

Märkus. Parema loetavuse huvides muudame selles artiklis rakenduse põhiversiooni.

1. samm: algseisund

Rakenduse versioon: 1.0.0
DB versioon: v1

Kommentaar

See on rakenduse esialgne olek.

Andmebaasi muudatused

DB sisaldab 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');

Koodi muudatused

Rakendus salvestab isikuandmed 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
                + "]";
    }
}

Tagasiühildumatu veeru ümbernimetamine

Vaatame veeru nime muutmise näidet:

Tähelepanu. Järgmine näide rikub asju tahtlikult. Näitame seda, et näidata andmebaasi ühilduvuse probleemi.

Rakenduse versioon: 2.0.0.BAD

DB versioon: v2bad

Kommentaar

Praegused muudatused EI luba meil käitada kahte eksemplari (vana ja uus) korraga. Seega on seisakuta juurutamist raske saavutada (kui eeldusi arvesse võtta, on see tegelikult võimatu).

A/B testimine

Praegune olukord on selline, et meil on rakenduse versioon 1.0.0, kasutusele tootmises ja andmebaasis v1. Peame juurutama rakenduse teise eksemplari, versiooni 2.0.0.BADja värskendage andmebaasi v2bad.

Sammud:

  1. juurutatakse versioonirakenduse uus eksemplar 2.0.0.BADmis värskendab andmebaasi v2bad
  2. andmebaasis v2bad veerg last_name ei ole enam olemas – see muudeti uueks surname
  3. Andmebaasi ja rakenduse värskendamine õnnestus ning mõned eksemplarid töötavad 1.0.0, teised - sisse 2.0.0.BAD. Kõik on andmebaasiga ühendatud v2bad
  4. kõik versiooni eksemplarid 1.0.0 hakkab viskama vigu, sest nad proovivad sisestada andmeid veergu last_namekeda enam ei eksisteeri
  5. kõik versiooni eksemplarid 2.0.0.BAD töötab probleemideta

Nagu näete, kui teeme andmebaasis ja rakenduses tagasiühildumatuid muudatusi, on A/B testimine võimatu.

Rakenduse tagasipööramine

Oletame, et pärast A/B juurutamise katset (u. per.: autor pidas siin ilmselt silmas A/B testimist) otsustasime, et peame rakenduse versioonile tagasi pöörduma 1.0.0. Oletame, et me ei taha andmebaasi tagasi võtta.

Sammud:

  1. peatame versioonirakenduse eksemplari 2.0.0.BAD
  2. andmebaas on alles v2bad
  3. versioonist alates 1.0.0 ei saa aru, mis see on surname, näeme vigu
  4. põrgu on lahti läinud, me ei saa enam tagasi minna

Nagu näete, kui teeme andmebaasis ja rakenduses tagasiühildumatuid muudatusi, ei saa me eelmisele versioonile tagasi pöörduda.

Skripti täitmise logid

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"}

Andmebaasi muudatused

Migratsiooniskript, mis nimetab ümber last_name в surname

Allikas 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, mis nimetab ümber last_name.

-- This change is backward incompatible - you can't do A/B testing
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;

Koodi muudatused

Oleme muutnud välja nime lastName edasi surname.

Veeru ümbernimetamine tagasiühilduval viisil

See on kõige levinum olukord, millega võime kokku puutuda. Peame tegema tagurpidi kokkusobimatuid muudatusi. Oleme juba tõestanud, et seisakuta juurutamiseks ei tohiks me lihtsalt rakendada andmebaasi migratsiooni ilma täiendavate sammudeta. Artikli selles jaotises teostame 3 rakenduse juurutamist koos andmebaasi migreerimisega, et saavutada soovitud tulemus, säilitades samal ajal tagasiühilduvuse.

Märkus. Tuletame meelde, et meil on versioonide andmebaas v1. See sisaldab veerge first_name и last_name. Me peame muutuma last_name edasi surname. Meil on ka rakenduse versioon 1.0.0, mida veel ei kasutata surname.

2. samm: lisage perekonnanimi

Rakenduse versioon: 2.0.0
DB versioon: v2

Kommentaar

Uue veeru lisamisega ja selle sisu kopeerimisega loome tagasiühilduvad andmebaasimuudatused. Samas, kui võtame JAR-i tagasi või paneme tööle vana JAR-i, ei lähe see täitmise ajal katki.

Anname välja uue versiooni

Sammud:

  1. tehke uue veeru loomiseks andmebaasi migreerimine surname. Nüüd teie DB versioon v2
  2. kopeeri andmed last_name в surname. Обратите вниманиеet kui teil on neid andmeid palju, peaksite kaaluma pakettmigreerimist!
  3. kirjutage kood, kus neid kasutatakse MÕLEMAD и uusJa vana veerg. Nüüd teie rakenduse versioon 2.0.0
  4. loe väärtust veerust surname, kui seda pole null, või alates last_name, kui a surname täpsustamata. Saate kustutada getLastName() koodist, kuna see väljastab null rakenduse tagasipööramisel 3.0.0 kuni 2.0.0.

Kui kasutate Spring Boot Flyway, tehakse need kaks sammu versiooni käivitamisel 2.0.0 rakendusi. Kui käivitate andmebaasi versioonide loomise tööriista käsitsi, peate selleks tegema kaks erinevat asja (kõigepealt värskendama db versiooni käsitsi ja seejärel juurutama uus rakendus).

See on tähtis. Pidage meeles, et äsja loodud veerg EI PEAKS olema EI NULL. Kui teete tagasipööramise, ei tea vana rakendus uuest veerust ega installi seda ajal Insert. Aga kui lisate selle piirangu ja teie db on v2, selleks on vaja määrata uue veeru väärtus. Mis toob kaasa piirangute rikkumise.

See on tähtis. Peaksite meetodi eemaldama getLastName(), sest versioonis 3.0.0 Koodis pole veeru mõistet last_name. See tähendab, et seal määratakse null. Võite meetodi lahkuda ja lisada tšekke null, kuid palju parem lahendus oleks selles loogikas veenduda getSurname() valisite õige nullist erineva väärtuse.

A/B testimine

Praegune olukord on selline, et meil on rakenduse versioon 1.0.0, kasutusele võetud tootmises ja andmebaasis v1. Peame juurutama versioonirakenduse teise eksemplari 2.0.0mis värskendab andmebaasi v2.

Sammud:

  1. juurutatakse versioonirakenduse uus eksemplar 2.0.0mis värskendab andmebaasi v2
  2. vahepeal töödeldi mõnda taotlust versioonijuhtumite kaupa 1.0.0
  3. värskendus õnnestus ja teil on mitu versioonirakenduse eksemplari 1.0.0 ja muud versioonid 2.0.0. Kõik suhtlevad andmebaasiga v2
  4. versioon 1.0.0 ei kasuta andmebaasis perekonnanime veergu, vaid versiooni 2.0.0 kasutab. Need ei sega üksteist ja vigu ei tohiks olla.
  5. versioon 2.0.0 salvestab andmed nii vanasse kui uude veergu, tagades tagasiühilduvuse

See on tähtis. Kui teil on päringuid, mis loendavad üksusi vana/uue veeru väärtuste põhjal, pidage meeles, et teil on nüüd dubleeritud väärtused (tõenäoliselt migreeruvad need endiselt). Näiteks kui soovite loendada kasutajate arvu, kelle perekonnanimi (mis iganes veergu nimetatakse) algas tähega A, seejärel kuni andmete migreerimine on lõppenud (oldnew veerus) võivad andmed olla vastuolulised, kui esitate päringu uue veeru vastu.

Rakenduse tagasipööramine

Nüüd on meil rakenduse versioon 2.0.0 ja andmebaas sees v2.

Sammud:

  1. kerige oma rakenduse versiooni tagasi 1.0.0.
  2. versioon 1.0.0 ei kasuta andmebaasis veergu surname, seega peaks tagasivõtmine olema edukas

DB muudatused

Andmebaas sisaldab veergu nimega last_name.

Flyway lähteskript:

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');

Lisa skript surname.

Tähelepanu. Pidage meeles, et te EI SAA lisatavale veerule MITTE NULL-piiranguid LISADA. Kui võtate JAR-i tagasi, pole vanal versioonil lisatud veerust aimugi ja see seab selle automaatselt väärtusele NULL. Kui selline piirang on olemas, läheb vana rakendus lihtsalt katki.

-- 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

Koodi muudatused

Andmeid säilitame kui last_nameja sisse surname. Samal ajal loeme alates last_name, kuna see veerg on kõige asjakohasem. Juurutusprotsessi ajal võis mõnda taotlust töödelda rakenduse eksemplar, mida pole veel värskendatud.

/*
 * 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. samm: eemaldage koodist perekonnanimi

Rakenduse versioon: 3.0.0

DB versioon:v3

Kommentaar

Märge per.: Ilmselt kopeeris autor algses artiklis selle ploki teksti ekslikult sammust 2. Selles etapis tuleks rakenduse koodis teha muudatusi eesmärgiga eemaldada veergu kasutav funktsionaalsus last_name.

Lisades uue veeru ja kopeerides selle sisu, lõime tagasiühilduvad andmebaasi muudatused. Samuti, kui me JAR-i tagasi võtame või kui käivitame vana JAR-i, ei purune see täitmise ajal.

Rakenduse tagasipööramine

Praegu on meil rakenduse versioon 3.0.0 ja andmebaas v3. Versioon 3.0.0 ei salvesta andmeid last_name. See tähendab, et sisse surname salvestatakse kõige värskem teave.

Sammud:

  1. kerige oma rakenduse versiooni tagasi 2.0.0.
  2. versioon 2.0.0 kasutab ja last_name и surname.
  3. versioon 2.0.0 võtab surname, kui see ei ole null, muidu -last_name

Andmebaasi muudatused

Struktuurseid muudatusi andmebaasis ei ole. Vanade andmete lõplikuks migreerimiseks käivitatakse järgmine skript:

-- 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;

Koodi muudatused

Märge per.: Autor kopeeris ekslikult ka selle ploki kirjelduse sammust 2. Vastavalt artikli loogikale peaksid selles etapis tehtavad koodimuudatused olema suunatud veeruga töötavate elementide eemaldamisele. last_name.

Andmeid säilitame kui last_nameja sisse surname. Lisaks loeme veerust last_name, kuna see on kõige asjakohasem. Juurutusprotsessi ajal võib mõnda taotlust töödelda eksemplar, mida pole veel täiendatud.

/*
 * 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. samm: eemaldage andmebaasist perekonnanimi

Rakenduse versioon: 4.0.0

DB versioon: v4

Kommentaar

Tulenevalt asjaolust, et versioonikood 3.0.0 veergu ei kasutanud last_name, ei juhtu täitmise ajal midagi halba, kui tagasi pöördume 3.0.0 pärast veeru andmebaasist eemaldamist.

Skripti täitmise logid

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 muudatused

Suhteliselt v3 me lihtsalt eemaldame veeru last_name ja lisage puuduvad piirangud.

-- 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;

Koodi muudatused

Koodis muudatusi ei ole.

Väljund

Rakendasime edukalt tagasiühildumatu veeru nime muutmise, viies läbi mitu tagasiühilduvat juurutust. Allpool on tehtud toimingute kokkuvõte:

  1. rakenduse versiooni juurutamine 1.0.0 с v1 andmebaasi skeem (veeru nimi = last_name)
  2. rakenduse versiooni juurutamine 2.0.0, mis salvestab andmed last_name и surname. Rakendus loeb alates last_name. Andmebaas on versioonis v2sisaldavad veerge nagu last_nameJa surname. surname on koopia last_name. (MÄRKUS. Sellel veerul ei tohi olla nullpiirangut)
  3. rakenduse versiooni juurutamine 3.0.0, mis salvestab ainult andmeid surname ja loeb perekonnanimest. Mis puutub andmebaasi, siis toimub viimane migratsioon last_name в surname. Samuti piirang EI NULL eemaldatud last_name. Andmebaas on nüüd versioonis v3
  4. rakenduse versiooni juurutamine 4.0.0 - koodis muudatusi ei tehta. Andmebaasi juurutamine v4, mis eemaldab last_name. Siin saate andmebaasi lisada kõik puuduvad piirangud.

Seda lähenemisviisi järgides saate alati ühe versiooni tagasi pöörata, ilma et see kahjustaks andmebaasi/rakenduse ühilduvust.

Kood

Kõik selles artiklis kasutatud kood on saadaval aadressil Github. Allpool on täiendav kirjeldus.

Projektid

Pärast hoidla kloonimist näete järgmist kaustastruktuuri.

├── 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)

Skriptid

Saate käivitada allolevates skriptides kirjeldatud skripte, mis näitavad tagasiühilduvaid ja mitteühilduvaid muudatusi andmebaasis.

Et näha tagasiühilduvate muudatustega, jookse:

./scripts/scenario_backward_compatible.sh

Ja näha tagasiühildumatute muudatustega juhtum, jookse:

./scripts/scenario_backward_incompatible.sh

Kevadsaabaste näidislennutee

Kõik näited on võetud siit Spring Boot Sample Flyway.

Võite vaadata http://localhost:8080/flyway, on olemas skriptide loend.

See näide hõlmab ka H2 konsooli (at http://localhost:8080/h2-console), et saaksite vaadata andmebaasi olekut (vaikimisi jdbc URL on jdbc:h2:mem:testdb).

Lisaks

Loe ka teisi meie ajaveebi artikleid:

Allikas: www.habr.com

Lisa kommentaar