Nulla aega jaandmine ning andmebaasid

Nulla aega jaandmine ning andmebaasid

Selles artiklis käsitletakse, kuidas lahendada andmebaaside ühilduvusprobleeme juurutamise ajal. Räägime, mis võib juhtuda teie rakendustega tootmises, kui proovite juurutada ilma eelneva ettevalmistuseta. Seejärel vaatame rakenduse elutsükli etappe, mis on vajalikud null aegete saavutamiseks (märkus: edaspidi — nulla aega). Meie tegevuse tulemuseks on tagasi pöörduva mitteühilduva muudatuse rakendamine tagasi ühilduval viisil.

Kui soovite artiklist koodi näiteid, leiate need aadressilt GitHub.

Sissejuhatus

Nulla aega jaandmine

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

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

  • juurutage teenuse versioon №1
  • tehke andmebaasi migreerimine
  • juurutage teenuse versioon №2 paralleelselt versiooniga №1
  • kui näete, et versioon №2 töötab nagu peab, eemaldage versioon №1
  • valmis!

Lihtne, eks? Kahjuks ei ole see nii lihtne, ja me arutame seda hiljem üksikasjalikult. Kuid praegu vaadakem veel ühte üsna levinud deploy protsessi — blue green deployment.

Oled sa kunagi kuulnud blue green deployment? С Cloud Foundry это чрезвычайно легко сделать. Просто гляньте на selle artikli, kus me käsitleme seda põhjalikumalt. Kokkuvõtlikult tuletame meelde, kuidas teha blue green deployment:

  • tagada, et kaks koopiat sinu production koodist (“blue” ja “green”) töötaksid;
  • suunata kogu liiklus blue keskkonda, st et tootmisse aadressid osutaksid sinna;
  • deploida ja testida kõik rakenduse muudatused green keskkonnas;
  • vahetada URL- aadressid blue keskkonnast green keskkonda.

Blue green deployment on lähenemine, mis võimaldab sul lihtsalt uusi funktsioone sisse tuua, muretsemata, et tootmine katki läheb. See on seotud sellega, et isegi kui midagi juhtub, saad lihtsalt "lülitiga klõpsates" tagasi eelnevasse keskkonda.

Kuna oled kõik eelneva läbi lugenud, võid küsida: Millist seost zero downtime'il on blue green deploy'ga?

Noh, neil on üsna palju ühist, kuna kahe sama keskkonna koopia toetamine nõuab kahekordseid pingutusi nende hooldamiseks. Seetõttu väidab mõned meeskonnad, Martin Fowler, järgides selle lähenemise variatsioone:

teine variant on kasutada sama andmebaasi, luues sinised-rohelised vahetused veebikliendi ja domeenikihtide vahel. Sellise lähenemise puhul võivad andmebaasid tihti probleemiks saada, eriti kui peate muutma nende skeemi uue tarkvaraversiooni toetamiseks.

Ja siin me jõuame selle artikli peamise probleemini. Andmebaas. Vaadakem sellele lausele veel kord.

tehke andmebaasi migratsioon.

Nüüd peaksite endalt küsima – mis siis, kui andmebaasi muutmine on tagasivõetamatu? Kas minu esialgne rakenduse versioon ei purune? Tegelikult juhtub just see...

Seega, vaatamata zero downtime / blue green deployment tohututele eelistele, kalduvad ettevõtted järgima järgmist, turvalisemat rakenduste juurutamise protsessi:

  • valmistada ette uus rakenduse versioon
  • keelata jooksva rakenduse
  • käivitada andmebaasi migratsiooni skriptid
  • juurutada ja käivitada uus rakenduse versioon

Selles artiklis käsitleme üksikasjalikult, kuidas saate andmebaasi ja koodi kasutada, et teha kasutusele zero downtime deployment.

Andmebaasiprobleemid

Kui teil on stateless rakendus, mis ei salvesta andmeid andmebaasis, saate zero downtime deploymenti kohe. Kahjuks peab suurem osa tarkvarast salvestama andmeid kusagil. Just sel põhjusel peaksite enne schéma muudatuste tegemist kaks korda mõtlema. Enne kui jõuame selliste muudatuste detailideni, mis võimaldavad downtime'iga juurutamise, keskendume esiteks versioonihalduse skeemile.

Versioonihalduse skeem

Selles artiklis kasutame Flyway versioonihaldustööriistana (märkus tõlkijalt: jutt on andmebaasi migreerimistest). Loomulikult kirjutame ka Spring Boot rakenduse, millel on sisseehitatud Flyway tugi ja mis viib schéma migreerimise läbi rakenduse konteksti seadistamise ajal. Flyway kasutamisel saate salvestada migreerimisk skriptid oma projektide kaustas (vaikimisi classpath:db/migration). Siin näete näidet sellistest migreerimisfailidest.

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

Selles näites näeme 4 migreerimisskeemi, mis, kui nad pole varem rakendatud, täidetakse rakenduse käivitamisel järjestikku. Vaatame üht failidest (V1__init.sql) näiteks.

Loo tabel PERSON (
id BIGINT GENEREERITUD VAID AINULT IDENTITEEDI KUNA,
first_name varchar(255) mitte null,
last_name varchar(255) mitte null
);

sisesta INTO PERSON (first_name, last_name) VALUES ('Dave', 'Syer');

Kõik räägib enda eest: saate kasutada SQL-i, et määrata, kuidas teie andmebaas peaks muutuma. Täiendava teabe saamiseks Spring Booti ja Flyway kohta tutvuge Spring Booti dokumendid.

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

  • te eraldate andmebaasi muudatused koodimuudatustest
  • andmebaasi migratsioon toimub koos teie rakenduse juurutamisega, st teie juurutamisprotsess lihtsustub

Andmebaasi probleemide lahendamine

Artikli järgmises osas keskendume kahte lähenemisviisi andmebaasi muudatuste arutamisele.

  • tagasiühilduvus
  • tagasiühilduvus

Esimene hoiatab, et null-seisakuga juurutust ei tohiks teha ilma eelneva ettevalmistuseta... Teine pakub lahendust, kuidas juurutada seisakuteta ja samal ajal säilitada tagurpidi ühilduvus.

Meie projekt, millega hakkame tegelema, on lihtne Spring Boot Flyway rakendus, milles on Isik koos eesnimi ja perekonnanimi andmebaasis (märkus: Isik on tabel ning feesnimi ja perekonnanimi on selle väljad). Soovime ümber nimetada perekonnanimi ühes perekonnanimi.

Eeldused

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

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

Andmebaasi tagasiviimist ei tohiks teha.

See lihtsustab juurutamisprotsessi (mõned andmebaasi tagasiviimised on praktiliselt võimatud, näiteks kustutamise tagasiviimine). Eelistame tagasiviimist ainult rakendustele. Nii on teie juurutamise toru ühtne, isegi kui teil on erinevad andmebaasid (nt SQL ja NoSQL).

Rakendust tuleb alati võimalikult tagasi viia ühte versiooni (mitte rohkem).

Tagasiviimist tuleb teha ainult vajadusel. Kui praeguses versioonis on viga, mida on raske parandada, peame saama tagasi viia viimase töötava versiooni. Eeldame, et see viimane töötav versioon on eelmine. Koodi ja andmebaasi ühilduvuse säilitamine enam kui ühe väljalaskega oleks äärmiselt keeruline ja kulukas.

Märkus. Suurema loetavuse huvides muudame käesolevas artiklis rakenduse suurversiooni.

Samm 1: Algseisund

Rakenduse versioon: 1.0.0
Andmebaasi versioon: v1

Kommentaar

See on rakenduse algseisund.

Andmebaasi muudatused

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

Rakendus salvestab andmed isiku kohta perekonnanimi:

/*
 * 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ühilduv veeru ümbernimetamine

Vaatame näidet, kuidas muuta veeru nime:

Tähelepanu. Järgmine näide põhjustab tahtlikult rikke. Me näitame seda, et demonstreerida andmebaasi ühilduvuse probleemi.

Rakenduse versioon: 2.0.0.BAD

DB versioon: v2bad

Kommentaar

Praegused muudatused EI luba meil käivitada kahte eksemplari (vana ja uus) samaaegselt. Seega, nullist katkestamata juurutamine on raske saavutada (kui arvestada eeldusi, on see tegelikult võimatu).

A/B testimine

Praegune olukord on selline, et meil on versiooni rakendus 1.0.0, toodetud, ja andmebaas v1. Peame juurutama teise rakenduse eksemplari, versiooni 2.0.0.BAD, ja värskendama andmebaasi kuni v2bad.

Sammud:

  1. toodud uus rakenduse eksemplar versioon 2.0.0.BAD, which updates the database to v2bad
  2. andmebaasis v2bad veerg perekonnanimi ei eksisteeri enam — see on muudetud perekonnanimi
  3. andmebaasi ja rakenduse värskendamine õnnestus, ning mõned eksemplarid töötavad 1.0.0, teised — 2.0.0.BAD. Kõik on seotud andmebaasiga v2bad
  4. kõik versiooni eksemplarid 1.0.0 hakkavad andma vigu, sest nad proovivad sisestada andmeid veergu perekonnanimi, mida enam ei ole
  5. kõik versiooni eksemplarid 2.0.0.BAD töötavad tõrgeteta

Nagu näete, kui teeme tagasipoole ühilduvaid muudatusi andmebaasis ja rakenduses, pole A/B testimine võimalik.

Rakenduse tagasipöördumine

Oletame, et pärast A/B juurutuse katset (märk. tõlk.: tõenäoliselt mõtles autor A/B testimist) otsustasime, et peame rakenduse tagasi versioonile pöörduma 1.0.0. Oletame, et me ei soovi andmebaasi tagasipöörata.

Sammud:

  1. peatame rakenduse eksemplari versioonis 2.0.0.BAD
  2. andmebaas on endiselt v2bad
  3. kuna versioon 1.0.0 ei saa aru, mis on perekonnanimi, näeme vigu
  4. paha, mis pääses vabadusse, me ei saa enam tagasi pöörduda

Nagu näete, kui teeme tagasipoole ühilduvaid muudatusi andmebaasis ja rakenduses, ei saa me naasta varasema versiooni juurde.

Skripti täitmise logid

Tagasiühilduv stsenaarium:

01) Käivita versioon 1.0.0
02) Oota, kuni rakendus (1.0.0) käivitub
03) Loo inimene, tehes 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, tehes POST localhost:9991/person versioonile 1.0.0 <-- see peaks ebaõnnestuma
07) Loo inimene, tehes POST localhost:9992/person versioonile 2.0.0.BAD <-- see peaks õnnestuma

Käivitamine rakenduses versioonis 1.0.0
Inimese loomine versioonis 1.0.0
POST 127.0.0.1:9991/person saatmine. See on vastus:

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

Käivitamine rakenduses versioonis 2.0.0.BAD
Inimese loomine versioonis 1.0.0
POST 127.0.0.1:9991/person saatmine. See on vastus:

curl: (22) Taotletud URL tagastas vea: 500 Internal Server Error

Inimese loomine versioonis 2.0.0.BAD
POST 127.0.0.1:9995/person saatmine. See on vastus:

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

Andmebaasi muudatused

Migreerimisskript, mis ümber nimetab perekonnanimi ühes perekonnanimi

Algne 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 ümber nimetab perekonnanimi.

-- See muudatus on tagasiviidav - A/B testimist ei saa teha
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;

Koodi muutmine

Me muutsime välja nime lastName järgnevaga perekonnanimi.

Veeru ümber nimetamine tagasiviidaval viisil

See on kõige levinum olukord, millega me kokku puutume. Me peame tegema tagasipöördumatud muutused. Oleme juba tõestanud, et katkestusteta juurutamiseks ei tohi me lihtsalt andmebaasi migreerimist rakendada ilma täiendavate toiminguteta. Artikli selles osas teeme kolm rakenduse juurutamist koos andmebaasi migreerimisega, et saavutada soovitud tulemus ja samal ajal säilitada tagasipöördumatuse ühilduvus.

Märkus. Kordame, et meil on andmebaasi versioon v1. See sisaldab veerge eesnimi ja perekonnanimi. Me peame muutma perekonnanimi järgnevaga perekonnanimi. Samuti on meil rakendus versiooniga 1.0.0, mis ei kasuta veel perekonnanimi.

Samm 2: Lisame perekonnanime

Rakenduse versioon: 2.0.0
Andmebaasi versioon: v2

Kommentaar

Uue veeru lisamisel ja selle sisu kopeerimisel loome tagasipöördumatult ühilduvad andmebaasi muudatused. Samal ajal, kui me tagastame JAR-i või kui meil on töötav vana JAR, ei tohiks see töötamise ajal katki minna.

Juhtige uut versiooni

Sammud:

  1. sooritage andmebaasi migreerimine, et luua uus veerg perekonnanimi. Nüüd on teie andmebaasi versioon v2
  2. koopiate andmed perekonnanimi ühes perekonnanimi. Pange tähele, et kui teil on palju neid andmeid, peaksite kaaluma grupimigratsiooni!
  3. kirjutage kood, kus kasutatakse KOHAL ja uus, ja vana veeru. Nüüd on teie rakenduse versioon 2.0.0
  4. loe väärtus veerust perekonnanimi, kui see ei ole null, või last_name, kui perekonnanimi ei ole määratud. Saate eemaldada getLastName() koodist, kuna see toob esile null rakenduse tagasivõtmisel 3.0.0 kuni 2.0.0.

Kui kasutate Spring Boot Flyway, siis need kaks sammu tehakse versiooni käivitamise ajal 2.0.0 rakendus. Kui te käivitate andmebaasi versioonihaldustööriista käsitsi, peate tegema kaks eraldi toimingut (esiteks uuendage andmebaasi versioon käsitsi ja seejärel juurutage uus rakendus).

Oluline. Pidage meeles, et uus veerg EI TOHI olla NOT NULL. Kui teete tagasivõtu, siis vana rakendus ei tea uuest veerust ja ei seadista seda ajal Sisestamine. Aga kui te lisate selle piirmäära, ja teie andmebaas on v2, siis see nõuab uue veeru väärtuse seadmist. Mis viib piirangute riknemiseni.

Oluline. Peaksite eemaldama meetodi getLastName(), kuna versioonis 3.0.0 koodis ei ole veeru mõistet perekonnanimi. See tähendab, et seal seadistatakse null. Saate meetodi jätta ja lisada kontrollid null, kuid palju parem lahendus oleks tagada, et getSurname() olete valinud õige mitte-null väärtuse.

A/B testimine

Praegune olukord on selline, et meil on versiooni rakendus 1.0.0, juurutatud tootmises, ja andmebaas olevat v1. Me peame juurutama teise versiooni rakenduse koopia 2.0.0, mis uuendab andmebaasi versioonini v2.

Sammud:

  1. toodud uus rakenduse eksemplar versioon 2.0.0, which updates the database to v2
  2. samal ajal mõned päringud töötasid versiooni eksemplaridega 1.0.0
  3. uuendus läks edukalt ja teil on mitu töötavat rakenduse versiooni 1.0.0 ja ülejäänud versioonid 2.0.0. K kõik suhtlevad andmebaasiga v2
  4. versioon 1.0.0 ei kasuta andmebaasis veergu surname, samas kui versioon 2.0.0 kasutab. Nad ei sega üksteist ja vigu ei tohiks olla.
  5. versioon 2.0.0 salvestab andmeid nii vanas kui uues veerus, mis tagab tagasiü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 veel migratsioonis). Näiteks kui soovite lugeda kasutajate arvu, kelle perekonnanimi (sõltumata veeru nimest) algab tähega A, siis andmete migratsiooni lõpuni (vanauus veeru) võivad teil olla ebaühtlased andmed, kui teete päringu uude veergu.

Rakenduse tagasipöördumine

Praegu on meil rakendus versioon 2.0.0 ja andmebaas v2.

Sammud:

  1. veerake oma rakendus versioonini 1.0.0.
  2. versioon 1.0.0 ei kasuta andmebaasis veergu perekonnanimi, seetõttu peab tagasivõtmine olema edukas

Andmebaasi muudatused

Andmebaas sisaldab veergu nimega perekonnanimi.

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

Lisamisskript perekonnanimi.

Tähelepanu. Pange tähele, et ei tohi lisada ühtegi NOT NULL piirangut lisatavasse veergu. Kui te tagasivõtmise JAR-i, siis vana versioon ei tea lisatud veerust midagi ja seadistab selle automaatselt NULL-iks. Kui selline piirang on olemas, puruneb vana rakendus lihtsalt.

-- MÄRKUS: Sellel väljadel ei saa olla NOT NULL piirangut, sest kui te tagasi võtate, ei tea vana versioon sellest väljast
-- ja seadistab selle alati NULL-iks
ALTER TABLE PERSON ADD surname varchar(255);

-- ESMALT OLEME ARVANUD, ET SEE ON KIIRE MIGREERIMINE - MUUD JUHUL PEAME MIGREERIMA PARTIIDENA
UPDATE PERSON SET PERSON.surname = PERSON.last_name

Koodi muutmine

Salvestame andmed nii perekonnanimi, kui ka perekonnanimi. Samal ajal loeme perekonnanimi, kuna see veerg on kõige asjakohasem. Deployimise käigus võidi mõned päringud töödelda rakenduse instantsiga, mis ei olnud 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 sümbolist

Rakenduse versioon: 3.0.0

DB versioon:v3

Kommentaar

Toimetaja märkus: Ilmselt on algses artiklis autor selle bloki teksti ekslikult kopeerinud sammust 2. Sel sammul tuleb teha muudatusi rakenduse koodis, mis on suunatud funktsionaalsuse eemaldamisele, mis kasutab veergu perekonnanimi.

Uue veeru lisamise ja selle sisu kopeerimisega oleme loonud andmebaasi tagasilühilduvad muudatused. Samuti, kui me naaseme vanemasse JAR-faili või meil on töötav vana JAR, siis see ei purune käitamise ajal.

Rakenduse tagasipöördumine

Meil on hetkel versiooni 3.0.0 ja andmebaas v3. Versioon 3.0.0 ei salvesta andmeid perekonnanimi. See tähendab, et perekonnanimi hoiab kõige ajakohasemat teavet.

Sammud:

  1. veerake oma rakendus versioonini 2.0.0.
  2. versioon 2.0.0 kasutab ja perekonnanimi ja perekonnanimi.
  3. versioon 2.0.0 võtab perekonnanimi, kui see ei ole null, muidu —perekonnanimi

Andmebaasi muudatused

Andmebaasis pole struktuurimuudatusi. Käitatakse järgmist skripti, mis teostab vanade andmete lõpliku migratsiooni:

-- ELEGIME KIIRE MIGRATSIOONI - KUI EI, PEAME MIGREERIMA PARTIIDENA
-- KA EI KONTROLLI ME, KAS ME EI KATTA OLEMASOLEVAID KANNE. PEAME VÕRDLEMA
-- KANNE VERSIOONE, ET VEENDUDA, KAS OLEMAS OLEVAT KANNE KÕRGEMA VERSIOONI NUMBRIGA
-- ME EI KATA SEDA.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;

-- KUSTUTAME MITTE NULL KOHUSTUSE; MU otherwise PROOVITE SISSE KANDA NULL VÄÄRTUSE LAST_NAME
-- MITTE_NULL KOHUSTUSEGA.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;

Koodi muutmine

Märkus: Selle ploki kirjeldus on autori poolt ekslikult kopeeritud sammust 2. Artikli narratiivi loogika kohaselt peaks selle sammu koodimuudatus suunama eemaldama elemente, mis töötavad veeru kallal. perekonnanimi.

Me salvestame andmeid nii perekonnanimi, kui ka perekonnanimi. Lisaks loeme veerust perekonnanimi, kuna see on kõige asjakohasem. Juurutamise käigus võivad mõned päringud töötlemiseks kasutada instantsi, mis 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 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 perekonnanimi, pole täitmise ajal midagi halba, kui me taastume 3.0.0 pärast veeru eemaldamist andmebaasist.

Skripti täitmise logid

Me teeme seda järgmistel viisidel:

01) Käivita 1.0.0
02) Oota, kuni rakendus (1.0.0) käivitub
03) Generaatori loomine 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) Generaatori loomine helistades POST localhost:9991/person versioonile 1.0.0
07) Generaatori loomine 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) Generaatori loomine helistades POST localhost:9992/person versioonile 2.0.0
12) Generaatori loomine 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) Generaatori loomine helistades POST localhost:9993/person versioonile 3.0.0
17) Generaatori loomine helistades POST localhost:9994/person versioonile 4.0.0

Rakenduse käivitamine versioonis 1.0.0
Generaatori loomine 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"}

Rakenduse käivitamine versioonis 2.0.0

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

Generaatori loomine 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 lõpetamine 1.0.0

Rakenduse käivitamine versioonis 3.0.0

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

Generaatori loomine 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 lõpetamine 2.0.0

Rakenduse käivitamine versioonis 4.0.0

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

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

Andmed DB muudatused

Seoses v3 kuid me eemaldame lihtsalt veeru perekonnanimi ja lisame puuduvad piirangud.

-- EEMALDA VEERG
ALTER TABLE PERSON DROP last_name;

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

Koodi muutmine

Koodimuudatusi ei ole.

Kokkuvõte

Oleme tagasi lükanud ühilduvuse muutuse veeru nime osas, tehes mitu tagasi ühilduvat juurutust. Allpool on kokkuvõte tehtud toimingutest:

  1. rakenduse versiooni juurutamine 1.0.0 koos v1 DB skeem (veeru nimi = perekonnanimi)
  2. rakenduse versiooni juurutamine 2.0.0, mis säilitab andmeid perekonnanimi ja perekonnanimi. Rakendus loeb perekonnanimi. DB on versioonis v2, mis sisaldab veerge nagu perekonnanimi, kui ka surname. surname on l koopiaast_name. (MÄRKUS: sellel veerul ei tohiks olla not null piirangut)
  3. rakenduse versiooni juurutamine 3.0.0, mis säilitab andmeid ainult perekonnanimi ja loeb surname. Mis puudutab DB-d, toimub viimane migratsioon perekonnanimi ühes perekonnanimi. Samuti eemaldatakse piirang NOT NULL veerult perekonnanimi. DB on nüüd versioonis v3
  4. rakenduse versiooni juurutamine 4.0.0 — koodis ei toimu mingeid muudatusi. DB juurutamine v4, mis eemaldab perekonnanimi. Siia saate lisada kõik puuduvad piirangud DB-s.

Selle lähenemise järgimisega saate alati tagasi minna ühe versiooni võrra, rikkuvad DB / rakenduse ühilduvust.

Kood

Kogu selles artiklis kasutatud kood on saadaval Github. Allpool lisainformatsioon.

Projektid

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

├── boot-flyway-v1              - 1.0.0 versioon rakendusest koos skeemi v1-ga
├── boot-flyway-v2              - 2.0.0 versioon rakendusest koos skeemi v2-ga (tagasi ühilduv - rakendust saab tagasivõtta)
├── boot-flyway-v2-bad          - 2.0.0.BAD versioon rakendusest koos skeemi v2bad-ga (tagasi ühilduv mitte - rakendust ei saa tagasivõtta)
├── boot-flyway-v3              - 3.0.0 versioon rakendusest koos skeemi v3-ga (rakendust saab tagasivõtta)
└── boot-flyway-v4              - 4.0.0 versioon rakendusest koos skeemi v4-ga (rakendust saab tagasivõtta)

Skriptid

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

Et näha tagasi ühilduvate muudatuste juhtumit, käivitage:

./scripts/scenario_backward_compatible.sh

Ja et näha tagasi mitteühilduvate muudatuste juhtumit, käivitage:

./scripts/scenario_backward_incompatible.sh

Spring Boot Näidis Flyway

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

Saate vaadata http://localhost:8080/flyway, seal on skriptide nimekiri.

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

Lisaks

Vaata ka teisi artikleid meie blogis:

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster