Nulli seiskumise rakendamine ja andmebaasid

Nulli seiskumise rakendamine ja andmebaasid

Selles artiklis selgitatakse üksikasjalikult, kuidas lahendada andmebaasi ühilduvuse probleeme juurutamise ajal. Räägime sellest, mis võib juhtuda teie toodetud rakendustega, kui proovite juurutamist teha ilma eelneva ettevalmistuseta. Seejärel käime läbi rakenduse elutsükli etapid, mis on vajalikud, et saavutada null seisaku aeg (märkus: edaspidi - zero downtime). Meie tegevuse tulemusena rakendatakse tagurpidi ühilduvaid andmebaasi muudatusi ühilduval viisil.

Kui soovite artiklist koodinäidete üle vaadata, leiate need aadressilt GitHub.

Sissejuhatus

Zero downtime deployment

Mis on see müstiline zero downtime deployment? Можно сказать, это когда ваше приложение развернуто так, что вы можете успешно вводить новую версию приложения на продакшн, в то время как пользователь не замечает его недоступности. С точки зрения пользователя и компании, это наилучший из возможных сценариев деплоя, поскольку таким образом можно вводить новые функции и устранять ошибки без перебоев в работе.

Kuidas seda saavutada? On mitu viisi, siin on üks:

  • juuruta versioon nr 1 oma teenusest
  • teosta andmebaasi migratsioon
  • juuruta versioon nr 2 oma teenusest paralleelselt versiooniga nr 1
  • kui näete, et versioon nr 2 töötab nagu peab, eemaldage versioon nr 1
  • valmis!

Lihtne, eks? Kahjuks ei ole see nii lihtne ja me käsitleme seda hiljem üksikasjalikult. Aga praegu kontrollime veel ühte üsna levinud juurutamisprotsessi - blue green deployment.

Kas olete kunagi kuulnud blue green deployment? С Cloud Foundry это чрезвычайно легко сделать. Просто гляньте на seda artiklit, kus me kirjeldame seda põhjalikumalt. Lühidalt kokkuvõttes tuletame meelde, kuidas teha blue green deployment:

  • tagada, et teie tootmisvõi koodil oleks kaks koopiat ("blue" ja "green");
  • suunata kogu liiklus blue keskkonda, st et tootmis URL-id suunaksid sinna;
  • juurutada ja testida kõik rakenduse muudatused green keskkonnas;
  • vahetada URL-id blue keskkonnast green keskkonda

Blue green deployment on lähenemine, mis võimaldab teil hõlpsasti uusi funktsioone sisse tuua, muretsedes, et tootmine katki läheb. See tuleneb asjaolust, et isegi kui midagi juhtub, saate hõlpsasti naasta eelmisse keskkonda, lihtsalt "lülitades".

Kõike ülalpool loetletut lugedes võite küsida: Milline seos on zero downtime'il blue green juurutamisega?

Noh, neil on üsna palju ühist, kuna kahe sama keskkonna koopia toetamine nõuab nende hooldamiseks topeltpingutust. Just seetõttu, nagu väidab Martin Fowler, järgivad mõned meeskonnad selle lähenemise variatsiooni:

teise variandi kasutamine seisneb sama andmebaasi kasutamises, luues sinise ja rohelise lülitid veebi ja domeeni kihtide jaoks. Sellise lähenemise korral võivad andmebaasid sageli probleemiks osutuda, eriti kui peate muutma selle skeemi, et toetada uut tarkvaraversiooni.

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

tehke andmebaasi migratsioon.

Nüüd peaksite endalt küsima — mis siis, kui andmebaasi muutmine ei ole tagasi ühilduv? Kas minu esimene rakenduse versioon ei purune? Tegelikult just see juhtubki...

Nii et isegi vaatamata zero downtime / sinise ja rohelise juurutamise tohututele eelistele kalduvad ettevõtted järgima järgmisi turvalisemaid rakenduste juurutamisprotsesse:

  • valmistage ette uus rakenduse versioon
  • lülitage välja töötav rakendus
  • käivitage andmebaasi migratsiooni skriptid
  • juurutage ja käivitage uus rakenduse versioon

Selles artiklis kirjeldame üksikasjalikult, kuidas saate andmebaasi ja koodi töötlemise etapid nullvaheaja juurutamise eeliste nautimiseks.

Andmebaasi probleemid

Kui teil on staateless rakendus, mis ei salvesta andmeid andmebaasi, võite saavutada zero downtime juurutamise kohe. Kahjuks peab enamik tarkvarast andmeid kuskil salvestama. Just seetõttu peate enne skeemi muutmist kaks korda mõtlema. Enne kui süveneme detailidesse, kuidas skeemi muuta, et saada võimalus juurutamiseks ilma seisakuta, keskendume kõigepealt versioonihalduse skeemile.

Versioonihalduse skeem

Selles artiklis kasutame Flyway versioonihaldusvahendina (märkus tõlkijalt: räägime andmebaasi migratsioonidest). Loomulikult kirjutame ka Spring Boot rakenduse, millel on sisseehitatud Flyway tugi ja mis teostab skeemi migratsiooni rakenduse konteksti seadistamise ajal. Flyway kasutamisel saate salvestada migratsiooniskeemid oma projektikaustades (vaikesätete kohaselt classpath:db/migration). Siin näete selliste migratsioonifailide näidet

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

Selles näites näeme 4 migratsioonistsenaariumi, mis, kui neid varem ei teostatud, viiakse järjestikku ellu rakenduse käivitamisel. Vaatame ühte faili (V1__init.sql) näitena.

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 selge: saate kasutada SQL-i, et määrata, kuidas teie andmebaasi tuleks muuta. Lisainformatsiooni saamiseks Spring Booti ja Flyway kohta tutvuge Spring Boot Docs.

Kasutades versioonihaldustööriista koos Spring Bootiga, saate kaks suurt eelist:

  • eristate andmebaasi muudatused koodimuudatustest
  • andmebaasi migratsioon toimub koos teie rakenduse käivitamisega, st teie juurutamisprotsess lihtsustub

Andmebaasi probleemide lahendamine

Artikli järgmises osas keskendume kahe lähenemise uurimisele andmebaasi muudatustele.

  • tagasiviidavus
  • tagasiühilduvus

Esimene käsitletakse hoiatuseks, et mitte teha nullseisaku juurutamist ettevalmistuseta... Teine pakub lahendust, kuidas juurutamist teha ja samal ajal tagada tagasiühilduvus.

Meie projekt, millega me tegelema hakkame, on lihtne Spring Boot Flyway rakendus, kus on ei pane tähele, need kuuluvad domeeni ja ei ole testi raames käsitletud. Seega, sellise graafilise struktuuri puhul näeks otsinguahelate päring välja nagu: jot first_name ja last_name andmebaasis (märk: ei pane tähele, need kuuluvad domeeni ja ei ole testi raames käsitletud. Seega, sellise graafilise struktuuri puhul näeks otsinguahelate päring välja nagu: on tabel ja first_name ja last_name — need on väljad;). Soovime ümber nimetada last_name ja perekonnanimi.

Eeldused

Enne kui süveneme üksikasjadesse, on oluline märkida paar eeldust meie rakenduste kohta. Peamine tulemus, mida soovime saavutada, on üsna lihtne protsess.

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

Andmebaasi tagasivõtmine ei ole vajalik

See lihtsustab juurutamisprotsessi (mõned andmebaasi tagasivõtmised on praktiliselt võimatud, näiteks kustutamise tagasivõtmine). Eelistame tagasi võtta ainult rakendusi. Nii et isegi kui teil on erinevad andmebaasid (näiteks SQL ja NoSQL), näeb teie juurutamise toru välja sama.

Rakenduse tagasivõtmine peaks alati olema võimalus tagasiviimiseks ühe versiooni võrra (mitte rohkem)

Tagasi pööramine tuleks teha ainult vajaduse korral. Kui praeguses versioonis on viga, mida on keeruline eemaldada, peaksime suutma naasta viimase töökorras versiooni juurde. Eeldame, et see viimane töökorras versioon on eelnev. Toetamine mitme versiooni koodi ja andmebaasi ühilduvusele oleks äärmiselt keeruline ja kulukas.

Note. Suurema loetavuse nimel muudame käesolevas artiklis rakenduse peaversiooni.

Samm 1: Algne seisund

Rakenduse versioon: 1.0.0
Andmebaasi versioon: v1

Kommentaar

See on rakenduse algne seisund.

Andmebaasi muudatused

Andmebaas sisaldab last_name.

LOO TABEL PERSON (
    id BIGINT LOODUD ALATI KUI IDENTITY,
    first_name varchar(255) mitte null,
    last_name varchar(255) mitte null
);

sisesta PERSON (first_name, last_name) väärtused ('Dave', 'Syer');

Koodimuudatused

Rakendus salvestab Person andmeid 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 ühilduvuste muutmine veeru nimi

Vaadakem näidet, kuidas muuta veeru nime:

Tähelepanu. Järgmine näide toob meelega kaasa rikke. Näitame seda, et demonstreerida andmebaasi ühilduvuse probleemi.

Rakenduse versioon: 2.0.0.BAD

Andmebaasi versioon: v2bad

Kommentaar

Praegused muudatused EI LUBA meil käivitada kahte eksemplari (vana ja uus) korraga. Seega on null-kuna seadistamine raske saavutada (kui arvestada eeldusi, on see tegelikult võimatu).

A/B testimine

Praegune olukord on see, et meil on rakendus versioon 1.0.0, , mis on produtseeritud, ja andmebaas v1. Me peame rakendama teise eksemplari rakendust, versioon 2.0.0.BAD, ja värskendama andmebaasi versioonini v2bad.

Sammud:

  1. on ette nähtud uus eksemplar rakenduse versioonist 2.0.0.BAD, mis värskendab andmebaasi versioonini v2bad
  2. andmebaasis v2bad veerg last_name ei eksisteeri enam — see on muudetud nimeks perekonnanimi
  3. andmebaasi ja rakenduse uuendamine õnnestus ning mõned eksemplarid töötavad 1.0.0, teised — 2.0.0.BAD. Kõik on seotud andmebaasiga v2bad
  4. kõik eksemplarid versioon 1.0.0 algavad vigade andmine, kuna nad proovivad sisestada andmeid veergu last_name, mida enam ei ole
  5. kõik eksemplarid versioon 2.0.0.BAD töötavad probleemideta

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

Rakenduse tagasipööramine

Oletame, et pärast A/B seadistuskatse tegemist (tõlke märk: autoril võib-olla oli mõte A/B testimine) otsustasime, et peame rakenduse tagasi pöörama versioonile 1.0.0. Oletame, et me ei soovi andmebaasi tagasi pöörata.

Sammud:

  1. me peatame rakenduse versiooni 2.0.0.BAD
  2. andmebaas on endiselt v2bad
  3. kuna versioon 1.0.0 ei mõista, mis on perekonnanimi, näeme vigu
  4. põrgu on vabanenud, me ei saa enam tagasi minna

Nagu näete, kui teeme andmebaasi ja rakenduse vahel tagasi ühilduvaid muudatusi, ei saa me tagasi minna eelmisele versioonile.

Skripti täitmise logid

Tagasi ühilduv stsenaarium:

01) Käivita 1.0.0
02) Oota, kuni rakendus (1.0.0) käivitub
03) Loo inimene, kutsudes POST localhost:9991/person versioonile 1.0.0
04) Käivita 2.0.0.BAD
05) Oota, kuni rakendus (2.0.0.BAD) käivitub
06) Loo inimene, kutsudes POST localhost:9991/person versioonile 1.0.0 <-- see peaks ebaõnnestuma
07) Loo inimene, kutsudes POST localhost:9992/person versioonile 2.0.0.BAD <-- see peaks edenduma

Käivitame rakenduse versioonis 1.0.0
Loodame inimesi versioonis 1.0.0
Postitus 127.0.0.1:9991/person. See on vastus:

{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}

Käivitame rakenduse versioonis 2.0.0.BAD
Loodame inimesi versioonis 1.0.0
Postitus 127.0.0.1:9991/person. See on vastus:

curl: (22) Taotletud URL tagastas vea: 500 Sisemine serveri viga

Loodame inimesi versioonis 2.0.0.BAD
Postitus 127.0.0.1:9995/person. See on vastus:

{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}

Andmebaasi muudatused

Migratsiooniskript, mis ümber nimetab last_name ja perekonnanimi

Algne Flyway skript:

LOO TABEL PERSON (
    id BIGINT LOODUD ALATI KUI IDENTITY,
    first_name varchar(255) mitte null,
    last_name varchar(255) mitte null
);

sisesta PERSON (first_name, last_name) väärtused ('Dave', 'Syer');

Skript, mis ümber nimetab last_name.

-- See muudatus on tagasi ühilduv - A/B testimist ei saa läbi viia
ALTER TABLE PERSON MUUDA last_name surname VARCHAR;

Koodimuudatused

Muutisime välja nime lastName . Tundub, et perekonnanimi.

Veeru ümbernimetamine tagasi ühilduval viisil

See on kõige tavalisem olukord, millega me silmitsi seisame. Peame tegema tagasi ühilduvaid muudatusi. Oleme juba tõestanud, et katkestusteta juurutamiseks ei tohi me lihtsalt andmebaasi migratsiooni rakendada ilma lisategevusteta. Selle artikli jaotises teostame 3 rakenduse juurutust koos andmebaasi migratsioonidega, et saavutada soovitud tulemus ja samal ajal säilitada tagasipöördumise ühilduvus.

Märkus. Meenutame, et meil on andmebaas versiooniga v1. See sisaldab veerge first_name ja last_name. Peame muutma last_name . Tundub, et perekonnanimi. Meil on ka rakendus versiooniga 1.0.0, , mis ei kasuta veel perekonnanimi.

Samm 2: Lisame surname

Rakenduse versioon: 2.0.0
Andmebaasi versioon: v2

Kommentaar

Uue veeru lisamise ja selle sisu kopeerimisega loome tagasi ühilduvad andmebaasi muudatused. Samal ajal, kui me tagasi JAR-i pöörame või meil on töötav vana JAR, ei riku see täitmist.

Käivitame uue versiooni

Sammud:

  1. tehke andmebaasi migratsioon, et luua uus veerg perekonnanimi. Nüüd on teie andmebaas versiooniga v2
  2. kopeerige andmed last_name ja perekonnanimi. Pange tähele, mis, kui teil on palju neid andmeid, peate arvestama paketihalduse migratsiooniga!
  3. kirjutage kood, kus kasutatakse KUMMADKI ja uus, ja vana veerg. Nüüd on teie rakenduse versioon 2.0.0
  4. lugeda veerus olevat väärtust perekonnanimi, kui see ei ole null, või last_name, kui perekonnanimi pole määratud. Võite eemaldada getLastName() koodist, kuna see annab null rakenduse versiooni tagasipööramisel 3.0.0 kuni 2.0.0.

Kui kasutate Spring Boot Flyway't, siis need kaks sammu tehakse rakenduse versiooni käivitamisel. 2.0.0 Kui käitate andmebaasi versioonide haldusvahendit käsitsi, peate selle jaoks tegema kaks erinevat toimingut (esiteks uuendage DB versioon käsitsi ja seejärel juurutage uus rakendus).

Oluline. Pidage meeles, et uus veerg EI TOHI olla NOT NULL. Kui teete tagasi pöördumise, ei tea vana rakendus uuest veerust ja ei määra seda ajal Insert. Aga kui lisate selle piirangu ja teie DB on v2, siis vajate uue veeru väärtuse seadistamiseks. See põhjustab piirangu rikkumist.

Oluline. Peaksite eemaldama meetodi getLastName(), kuna versioonis 3.0.0 koodis ei ole veeru mõistet last_name. See tähendab, et sinna seatakse null. Saate meetodi jätta ja lisada kontrollid null, kuid palju parem lahendus oleks veenduda, et teie loogikas getSurname() valisite õige mitte-null väärtuse.

A/B testimine

Praegune olukord on see, et meil on rakendus versioon 1.0.0, mis on juurutatud tootmises, ja DB on v1. Peame juurutama teise rakenduse versiooni 2.0.0, mis uuendab andmebaasi kuni v2.

Sammud:

  1. on ette nähtud uus eksemplar rakenduse versioonist 2.0.0, mis värskendab andmebaasi versioonini v2
  2. samal ajal, kui mõned päringud töötlesid versiooni eksemplare 1.0.0
  3. uuendamine õnnestus ja teil on mitu töötavat versiooni eksemplari 1.0.0 ja teised versioonid 2.0.0. Kõik suhtlevad DB-ga v2
  4. ICQ.com veebilehest dateeritud 1997. aasta aprilli, ja siis kuulus domeen hoopis teisele organisatsioonile — mingi mõõteseadmete tootjate ja kasutajate ühingule. Aasta 1.0.0 ei kasuta andmebaasis veergu surname, kuid versioon 2.0.0 kasutab. Nad ei sega üksteist ja vigu ei tohiks olla.
  5. ICQ.com veebilehest dateeritud 1997. aasta aprilli, ja siis kuulus domeen hoopis teisele organisatsioonile — mingi mõõteseadmete tootjate ja kasutajate ühingule. Aasta 2.0.0 salvestab andmed nii vanas kui ka uues veerus, mis tagab ühilduvuse

Oluline. Kui teil on mingeid päringuid, mis loendavad elemente vanade / uute veergude väärtuste põhjal, peate meeles pidama, et nüüd on teil väärtuste dubleerimine (tõenäoliselt nad kõik veel migreeruvad). Näiteks kui soovite lugeda kasutajate arvu, kelle perekonnanimi (olgu see veeru nimi kuidas tahes) algas tähega A, siis andmete migreerimise lõpuni (olduus veerg) võivad teil olla mittekooskõlalised andmed, kui teete päringu uuele veerule.

Rakenduse tagasipööramine

Praegu on meil rakenduse versioon 2.0.0 ja andmebaas on v2.

Sammud:

  1. tagasi pöörake oma rakendus versiooni 1.0.0.
  2. ICQ.com veebilehest dateeritud 1997. aasta aprilli, ja siis kuulus domeen hoopis teisele organisatsioonile — mingi mõõteseadmete tootjate ja kasutajate ühingule. Aasta 1.0.0 ei kasuta andmebaasis veergu perekonnanimi, seega peab tagasivõtt olema edukas

Andmebaasi muudatused

DB sisaldab veergu nimega last_name.

Algne Flyway skript:

LOO TABEL PERSON (
    id BIGINT LOODUD ALATI KUI IDENTITY,
    first_name varchar(255) mitte null,
    last_name varchar(255) mitte null
);

sisesta PERSON (first_name, last_name) väärtused ('Dave', 'Syer');

Lisamise skript perekonnanimi.

Tähelepanu. Pidage meeles, et ei TOHI LISADA mingeid NOT NULL piiranguid lisatavasse veergu. Kui teie JAR-i tagasi võtate, ei tea vana versioon uue veeru olemasolust ja seab selle automaatselt NULL-iks. Sellise piirangu korral puruneb vana rakendus lihtsalt.

-- MÄRKUS: See väli ei saa olla NOT NULL piirang, kuna kui te tagasi võtate, ei tea vana versioon selle välja kohta
-- ja seab selle alati NULL-iks
ALTER TABLE PERSON ADD surname varchar(255);

-- EELDAME, ET SEE ON KIIRE MIGRATSIOON - MUU SELLES TÕSTAMISEKS PEAME MIGREERIMA PARTIIDES
UPDATE PERSON SET PERSON.surname = PERSON.last_name

Koodimuudatused

Salvestame andmed nii last_name, kui ka perekonnanimi. Samal ajal loeme last_name, kuna see veerg on kõige asjakohasem. Deployimise käigus võis mõningaid päringuid töödelda rakendusäkkide, mis pole veel uuendatud.

/*
 * 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
                + "]";
    }
}

Samm 3: last_name eemaldamine koodist

Rakenduse versioon: 3.0.0

Andmebaasi versioon:v3

Kommentaar

Märk. tõlk.: Tundub, et algses artiklis on autor ekslikult kopeerinud selle ploki sisu sammust 2. Antud sammu käigus tuleb teha koodis muudatusi, et eemaldada funktsionaalsus, mis kasutab veergu last_name.

Uue veeru lisamise ja selle sisu kopeerimisega oleme loonud tagurpidi ühilduvad andmebaasi muudatused. Samuti, kui me tagastame JAR-i või kui meil on töötav vana JAR, ei purune see täitmise käigus.

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 perekonnanimi hoiab kõige ajakohasemat teavet.

Sammud:

  1. tagasi pöörake oma rakendus versiooni 2.0.0.
  2. ICQ.com veebilehest dateeritud 1997. aasta aprilli, ja siis kuulus domeen hoopis teisele organisatsioonile — mingi mõõteseadmete tootjate ja kasutajate ühingule. Aasta 2.0.0 kasutab ja last_name ja perekonnanimi.
  3. ICQ.com veebilehest dateeritud 1997. aasta aprilli, ja siis kuulus domeen hoopis teisele organisatsioonile — mingi mõõteseadmete tootjate ja kasutajate ühingule. Aasta 2.0.0 võtab perekonnanimi, kui see ei ole null, vastasel juhul —last_name

Andmebaasi muudatused

Andmebaasis ei ole struktuuri muudatusi. Käivitatakse järgmine skript, mis viib lõpule vanade andmete migratsiooni:

-- EELDAME, ET SEE ON KIIRE MIGRATSIOON - MUU SELLES TÕSTAMISEKS PEAME MIGREERIMA PARTIIDES
-- KA ME EI KONTROLLI, KAS ME EI ÜLEVIIE OLEVAT SISUST. ME PEAME VÕRRENDAMA
-- SISU VERSIOONE, ET KINNITADA, ET KUI ON JUBA SISU, MILLEL ON KÕRGEM VERSIOONINUMBER
-- ME EI KATKESTAMA SEDA.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;

-- EEMALDAMINE NOT NULL PIIRANG, MU otherwise PROOVITE SISSE LÜÜA NULL VÄÄRTUS LAST_NAME
-- NOT_NULL PIIRANGUGA.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;

Koodimuudatused

Märk. tõlk.: Selle ploki kirjeldus on samuti vale, kopeeritud autori poolt sammust 2. Artikli narratiivi loogika kohaselt peaks selle sammu koodimuudatused olema suunatud eemaldades elemente, mis tegelevad veeruga last_name.

Salvestame andmed nii last_name, kui ka surname. Lisaks loeme veerust last_name, kuna see on kõige asjakohasem. Paigaldamise ajal võivad mõned päringud olla töödeldud eksemplari poolt, mis ei ole veel uuendatud.

/*
 * 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
                + "]";
    }
}

Samm 4: last_name eemaldamine andmebaasist

Rakenduse versioon: 4.0.0

Andmebaasi versioon: v4

Kommentaar

Kuna versiooni kood 3.0.0 ei kasutanud veergu last_name, siis täitmise ajal ei juhtu midagi halba, kui tagasi pöördume 3.0.0 pärast veeru eemaldamist andmebaasist.

Skripti täitmise logid

Teeme seda järgmiselt:

01) Käivita 1.0.0
02) Oota, kuni rakendus (1.0.0) käivitub
03) Genereeri isik, helistades POST localhost:9991/person versioonile 1.0.0
04) Käivita 2.0.0
05) Oota, kuni rakendus (2.0.0) käivitub
06) Genereeri isik, helistades POST localhost:9991/person versioonile 1.0.0
07) Genereeri isik, helistades POST localhost:9992/person versioonile 2.0.0
08) Lõpeta rakendus (1.0.0)
09) Käivita 3.0.0
10) Oota, kuni rakendus (3.0.0) käivitub
11) Genereeri isik, helistades POST localhost:9992/person versioonile 2.0.0
12) Genereeri isik, helistades POST localhost:9993/person versioonile 3.0.0
13) Lõpeta rakendus (3.0.0)
14) Käivita 4.0.0
15) Oota, kuni rakendus (4.0.0) käivitub
16) Genereeri isik, helistades POST localhost:9993/person versioonile 3.0.0
17) Genereeri isik, helistades POST localhost:9994/person versioonile 4.0.0

Käivitamine rakenduses versioonis 1.0.0
Generatsiooni isik versioonis 1.0.0
Postitamine aadressile 127.0.0.1:9991/person. See on vastus:

{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}

Käivitamine rakenduses versioonis 2.0.0

Generatsiooni isik versioonis 1.0.0
Postitamine aadressile 127.0.0.1:9991/person. See on vastus:

{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}

Generatsiooni isik versioonis 2.0.0
Postitamine aadressile 127.0.0.1:9992/person. See on vastus:

{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}

Rakenduse 1.0.0 lõpetamine

Käivitamine rakenduses versioonis 3.0.0

Generatsiooni isik versioonis 2.0.0
Postitamine aadressile 127.0.0.1:9992/person. See on vastus:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}

Generatsiooni isik versioonis 3.0.0
Postitamine aadressile 127.0.0.1:9993/person. See on vastus:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}

Rakenduse 2.0.0 lõpetamine

Käivitamine rakenduses versioonis 4.0.0

Generatsiooni isik versioonis 3.0.0
Postitamine aadressile 127.0.0.1:9993/person. See on vastus:

{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}

Generatsiooni isik versioonis 4.0.0
Postitamine aadressile 127.0.0.1:9994/person. See on vastus:

{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}

Andmebaasi muudatused

Seoses v3 eemaldame veeru last_name ja lisame puuduvad piirangud.

-- EEMALDA VEERG
ALTER TABLE PERSON DROP last_name;

-- LISAGE PIIRANGUD
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;

Koodimuudatused

Koodimuudatusi pole.

Kokkuvõte

Oleme tagasi pöördunud ühilduvuse muutuse nime veeru, tehes mitu tagasi ühilduvat juurutust. Allpool on kokkuvõte tehtud toimingutest:

  1. rakenduse versiooni juurutamine 1.0.0 jot v1 andmebaasi skeem (veeru nimi = last_name)
  2. rakenduse versiooni juurutamine 2.0.0, mis salvestab andmeid last_name ja perekonnanimi. Rakendus loeb last_name. Andmebaas on versioonis v2, mille veerud on nagu last_name, kui ka perekonnanimi. perekonnanimi on koopia last_name. (MÄRKUS: see veerg ei tohi omada not null piirangut)
  3. rakenduse versiooni juurutamine 3.0.0, mis salvestab andmeid ainult perekonnanimi ja loeb perekonnanimest. Andmebaasi osas toimub viimane migratsioon last_name ja perekonnanimi. Samuti tühistatakse piirang NOT NULL veeru pealt last_name. Andmebaas on nüüd versioonis v3
  4. rakenduse versiooni juurutamine 4.0.0 — koodis ei tehta mingeid muudatusi. Andmebaasi juurutamine v4, mis eemaldab last_name. Siia võite lisada kõik puuduvad piirangud andmebaasi.

Järgides seda lähenemist, saate alati tagasi ühe versiooni võrra tagasi pöörduda, häirimata andmebaasi / rakenduse ühilduvust.

Kood

Kogu selle artikli jooksul kasutatav kood on saadaval aadressil Github. Allpool on lisateave.

Projektid

Pärast repositooriumi kloonimist näete järgmist kataloogistruktuuri.

├── boot-flyway-v1              - rakenduse 1.0.0 versioon koos skeemi v1
├── boot-flyway-v2              - rakenduse 2.0.0 versioon koos skeemi v2 (tagasiühilduv - rakendust saab tagasi pöörata)
├── boot-flyway-v2-bad          - rakenduse 2.0.0.BAD versioon koos skeemi v2bad (tagasiühilduvust rikkumine - rakendust ei saa tagasi pöörata)
├── boot-flyway-v3              - rakenduse 3.0.0 versioon koos skeemi v3 (rakendust saab tagasi pöörata)
└── boot-flyway-v4              - rakenduse 4.0.0 versioon koos skeemi v4 (rakendust saab tagasi pöörata)

Skripti

Saate käivitada allpool kirjeldatud skripte, mis demonstreerivad tagasiühilduvaid ja ühilduvust rikkuvaid muudatusi andmebaasis.

Küsimiseks juhtum tagasiühilduvate muudatustega, käivitage:

.\/scripts\/scenario_backward_compatible.sh

Ja et näha juhtum tagasiühipidamatute muudatustega, käivitage:

.\/scripts\/scenario_backward_incompatible.sh

Spring Boot Näidis Flyway

Kõik näited on võetud Spring Boot Näidis Flyway.

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

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

Lisaks

Vaata ka teisi artikleid meie blogis:

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster