Núll niður í miðbæ og gagnasöfn

Núll niður í miðbæ og gagnasöfn

Þessi grein útskýrir í smáatriðum hvernig á að leysa gagnagrunnssamhæfisvandamál við uppsetningu. Við munum segja þér hvað getur gerst við framleiðsluforritin þín ef þú reynir að dreifa án undirbúnings. Við förum síðan í gegnum lífsferilsstig forritsins sem þarf til að hafa núll niður í miðbæ (ca. akrein: lengra - núll niður í miðbæ). Niðurstaða aðgerða okkar verður sú að beita afturábak-ósamrýmanlegum gagnagrunnsbreytingunni á afturábak-samhæfan hátt.

Ef þú vilt skilja kóðadæmin úr greininni geturðu fundið þau á GitHub.

Inngangur

Núll dreifing niður í miðbæ

Þvílík dulspeki núll dreifing niður í miðbæ? Þú getur sagt að þetta sé þegar forritið þitt er dreift á þann hátt að þú getur kynnt nýja útgáfu af forritinu til framleiðslu á meðan notandinn tekur ekki eftir því að það sé ekki tiltækt. Frá sjónarhóli notenda og fyrirtækis er þetta besta mögulega dreifingarsviðið vegna þess að það gerir kleift að kynna nýja eiginleika og laga villur án truflana.

Hvernig á að ná þessu? Það eru nokkrar leiðir, hér er ein af þeim:

  • notaðu útgáfu nr. 1 af þjónustunni þinni
  • framkvæma gagnagrunnsflutning
  • Settu upp útgáfu #2 af þjónustunni þinni samhliða útgáfu #1
  • um leið og þú sérð að útgáfa nr. 2 virkar eins og hún ætti að vera, fjarlægðu útgáfu nr. 1
  • er tilbúinn!

Auðvelt, er það ekki? Því miður er þetta ekki svo einfalt og við munum skoða það nánar síðar. Nú skulum við athuga annað nokkuð algengt dreifingarferli - blágræn uppsetning.

Hefur þú einhvern tíma heyrt um blágræn dreifing? Cloud Foundry gerir þetta mjög auðvelt. Sjáðu bara þessi grein, þar sem við lýsum þessu nánar. Til að draga stuttlega saman, skulum við minna þig á hvernig á að gera blágræna uppsetningu:

  • tryggja að tvö eintök af framleiðslukóðanum þínum („blár“ og „grænn“) virki;
  • beina allri umferð í bláa umhverfið, þ.e. þannig að framleiðsluslóðir vísa þangað;
  • dreifa og prófa allar breytingar á forritum í grænu umhverfi;
  • skipta vefslóðum úr bláu yfir í grænt umhverfi

Blágræn dreifing er nálgun sem gerir þér kleift að kynna nýja eiginleika auðveldlega án þess að hafa áhyggjur af því að framleiðsla brotni. Þetta er vegna þess að jafnvel þótt eitthvað gerist geturðu auðveldlega snúið aftur í fyrra umhverfi með því einfaldlega að „smella á rofa“.

Eftir að hafa lesið allt ofangreint gætirðu spurt spurningarinnar: Hvað hefur núll niður í miðbæ að gera með uppsetningu blágræns?

Jæja, þeir eiga ansi margt sameiginlegt þar sem að viðhalda tveimur eintökum af sama umhverfi þarf tvöfalda áreynslu til að viðhalda þeim. Þetta er ástæðan fyrir því að sum lið halda því fram Martin Fowler, fylgdu afbrigði af þessari nálgun:

Annar valkostur er að nota sama gagnagrunn og búa til blágræna rofa fyrir vef- og lénalög. Í þessari nálgun getur gagnagrunnurinn oft verið vandamál, sérstaklega þegar þú þarft að breyta skema hans til að styðja nýja útgáfu af hugbúnaðinum.

Og hér komum við að aðalvandamálinu í þessari grein. Gagnagrunnur. Lítum aftur á þessa setningu.

framkvæma gagnagrunnsflutning.

Nú þarftu að spyrja sjálfan þig spurningarinnar - hvað ef gagnagrunnsbreytingin er ekki afturábaksamhæf? Mun fyrsta útgáfan mín af forritinu ekki bila? Reyndar er þetta nákvæmlega það sem mun gerast...

Svo, jafnvel þrátt fyrir mikla ávinning af núll niður í miðbæ / blágrænt dreifing, hafa fyrirtæki tilhneigingu til að fylgja eftirfarandi öruggara ferli til að dreifa forritum sínum:

  • undirbúa pakka með nýrri útgáfu af forritinu
  • lokaðu forriti sem er í gangi
  • keyra forskriftir til að flytja gagnagrunninn
  • dreifa og ræsa nýja útgáfu af forritinu

Í þessari grein munum við útskýra hvernig þú getur unnið með gagnagrunninn þinn og kóðann til að nýta þér núll niður í miðbæ.

Gagnagrunnsvandamál

Ef þú ert með ríkisfangslaust forrit sem geymir engin gögn í gagnagrunninum, geturðu fengið enga niður í miðbæ strax. Því miður þarf flestir hugbúnaður að geyma gögn einhvers staðar. Þess vegna ættir þú að hugsa þig tvisvar um áður en þú gerir einhverjar breytingar á hringrásinni. Áður en við förum í smáatriðin um hvernig á að breyta stefinu þannig að uppsetning án niðurtíma sé möguleg, skulum við fyrst einbeita okkur að útgáfuskemu.

Útgáfukerfi

Í þessari grein munum við nota Flugbraut sem útgáfustýringartæki (ca. Þýðing: við erum að tala um gagnaflutninga). Auðvitað munum við líka skrifa Spring Boot forrit sem hefur innbyggðan Flyway stuðning og mun framkvæma skemaflutning á meðan forritasamhengið er sett upp. Þegar þú notar Flyway geturðu geymt flutningsforskriftir í verkefnamöppunni þinni (sjálfgefið í classpath:db/migration). Hér má sjá dæmi um slíkar flutningsskrár

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

Í þessu dæmi sjáum við 4 flutningsforskriftir sem, ef þær hafa ekki verið keyrðar áður, verða keyrðar hvert á eftir öðru þegar forritið byrjar. Við skulum skoða eina af skránum (V1__init.sql) sem dæmi.

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

Allt skýrir sig fullkomlega sjálft: þú getur notað SQL til að skilgreina hvernig gagnagrunninum þínum ætti að breyta. Fyrir frekari upplýsingar um Spring Boot og Flyway, skoðaðu Spring Boot Docs.

Með því að nota frumstýringartæki með Spring Boot færðu 2 stóra kosti:

  • þú aðskilur breytingar á gagnagrunni frá kóðabreytingum
  • Gagnagrunnsflutningur á sér stað samhliða útsetningu forritsins þíns, þ.e. dreifingarferlið þitt er einfaldað

Úrræðaleit í gagnagrunnsvandamálum

Í næsta hluta greinarinnar munum við einbeita okkur að því að skoða tvær aðferðir við breytingar á gagnagrunni.

  • afturábak ósamrýmanleiki
  • afturábak eindrægni

Sú fyrri verður talin vera viðvörun um að þú ættir ekki að framkvæma núll niður í miðbæ án undirbúnings undirbúnings... Sá síðari býður upp á lausn á því hvernig þú getur framkvæmt dreifingu án niðurtíma og á sama tíma viðhaldið afturábakssamhæfi.

Verkefnið okkar sem við munum vinna að verður einfalt Spring Boot Flyway forrit sem hefur Person с first_name и last_name í gagnagrunninum (ca. þýðing: Person er borð og first_name и last_name - þetta eru reitirnir í því). Við viljum endurnefna last_name в surname.

Forsendur

Áður en við förum út í smáatriðin eru nokkrar forsendur sem við þurfum að gera varðandi umsóknir okkar. Helsta niðurstaðan sem við viljum ná verður frekar einfalt ferli.

Athugið. Viðskipti PRO-TIP. Einföldun ferla getur sparað þér mikla peninga í stuðningi (því fleiri sem þú hefur í vinnu hjá fyrirtækinu þínu, því meiri peninga geturðu sparað)!

Engin þörf á að afturkalla gagnagrunninn

Þetta einfaldar dreifingarferlið (sumar endurfærslur gagnagrunns eru nánast ómögulegar, svo sem afturköllun á eyðingu). Við kjósum að afturkalla aðeins forrit. Þannig, jafnvel þótt þú hafir mismunandi gagnagrunna (til dæmis SQL og NoSQL), mun dreifingarleiðslan þín líta eins út.

Það verður ALLTAF að vera hægt að spóla forritinu eina útgáfu til baka (ekki meira)

Afturkalla ætti aðeins að gera þegar þörf krefur. Ef það er villa í núverandi útgáfu sem er ekki auðvelt að laga, ættum við að geta farið aftur í nýjustu virku útgáfuna. Við gerum ráð fyrir að þessi nýjasta virka útgáfa sé sú fyrri. Það væri afar erfitt og dýrt að viðhalda samhæfni kóða og gagnagrunns fyrir fleiri en eina útgáfu.

Seðillinn. Fyrir meiri læsileika munum við í þessari grein breyta aðalútgáfu forritsins.

Skref 1: Upphafsástand

Útgáfa forrits: 1.0.0
DB útgáfa: v1

Athugasemd

Þetta mun vera upphafsstaða umsóknarinnar.

Gagnagrunnsbreytingar

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

Kóðabreytingar

Forritið geymir Persónugögn í 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
                + "]";
    }
}

Endurnefna dálk ósamrýmanleg afturábak

Við skulum skoða dæmi um hvernig á að breyta heiti dálks:

Athygli. Eftirfarandi dæmi mun viljandi brjóta hlutina. Við sýnum þetta til að sýna fram á vandamálið við gagnagrunnssamhæfi.

Útgáfa forrits: 2.0.0.BAD

DB útgáfa: v2bad

Athugasemd

Núverandi breytingar leyfa okkur EKKI að keyra tvö tilvik (gamalt og nýtt) á sama tíma. Þannig verður erfitt að ná engum niðurtímauppsetningu (ef forsendur eru teknar með í reikninginn er það í raun ómögulegt).

A/B próf

Núverandi staða er sú að við erum með forritaútgáfu 1.0.0, beitt í framleiðslu og gagnagrunni v1. Við þurfum að dreifa öðru tilviki forritsins, útgáfu 2.0.0.BAD, og uppfærðu gagnagrunninn í v2bad.

Skref:

  1. nýtt tilvik af útgáfuforritinu er notað 2.0.0.BADsem uppfærir gagnagrunninn í v2bad
  2. í gagnagrunninum v2bad dálki last_name er ekki lengur til - því var breytt í surname
  3. Uppfærsla gagnagrunnsins og forritsins tókst og sum tilvik eru í gangi 1.0.0, aðrir - inn 2.0.0.BAD. Allt er tengt gagnagrunninum v2bad
  4. öll tilvik útgáfunnar 1.0.0 mun byrja að henda villum vegna þess að þeir munu reyna að setja gögn inn í dálkinn last_namesem er ekki lengur til
  5. öll tilvik útgáfunnar 2.0.0.BAD mun virka án vandræða

Eins og þú sérð, ef við gerum afturábak ósamhæfðar breytingar á gagnagrunninum og forritinu, er A/B próf ómögulegt.

Til baka umsókn

Gerum ráð fyrir að eftir að hafa reynt að gera A/B dreifingu (ca. pr.: höfundur átti líklega við A/B próf hér) við ákváðum að við þyrftum að snúa forritinu aftur í útgáfuna 1.0.0. Segjum að við viljum ekki afturkalla gagnagrunninn.

Skref:

  1. við hættum útgáfu umsóknartilvikinu 2.0.0.BAD
  2. gagnagrunnurinn er enn v2bad
  3. frá útgáfunni 1.0.0 skil ekki hvað það er surname, við munum sjá villur
  4. helvíti hefur brotnað laus, við getum ekki farið aftur

Eins og þú sérð, ef við gerum afturábak ósamhæfðar breytingar á gagnagrunninum og forritinu, getum við ekki snúið aftur í fyrri útgáfu.

Framkvæmdaskrár skriftu

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

Gagnagrunnsbreytingar

Flutningsforskrift sem endurnefnir last_name в surname

Heimild Flyway handrit:

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

Handrit sem endurnefnir last_name.

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

Kóðabreytingar

Við höfum breytt heiti svæðisins lastName á surname.

Endurnefna dálk á afturábak-samhæfan hátt

Þetta er algengasta ástandið sem við gætum lent í. Við þurfum að gera afturábak ósamrýmanlegar breytingar. Við höfum þegar sannað að fyrir uppsetningu án niður í miðbæ ættum við ekki einfaldlega að beita gagnagrunnsflutningi án frekari skrefa. Í þessum hluta greinarinnar munum við framkvæma 3 dreifingar á forritinu ásamt gagnagrunnsflutningum til að ná tilætluðum árangri en viðhalda afturábakssamhæfi.

Athugið. Mundu að við höfum útgáfugagnagrunn v1. Það inniheldur dálka first_name и last_name. Við verðum að breyta last_name á surname. Við erum líka með app útgáfu 1.0.0, sem er ekki enn notað surname.

Skref 2: Bættu við eftirnafni

Útgáfa forrits: 2.0.0
DB útgáfa: v2

Athugasemd

Með því að bæta við nýjum dálki og afrita innihald hans búum við til bakábaksamhæfðar breytingar á gagnagrunni. Á sama tíma, ef við snúum JAR til baka eða erum með gamla JAR í gangi, brotnar hann ekki við framkvæmd.

Við erum að setja út nýja útgáfu

Skref:

  1. framkvæma gagnagrunnsflutning til að búa til nýjan dálk surname. Nú er DB útgáfan þín v2
  2. afrita gögn frá last_name в surname. Borgaðu eftirtektað ef þú ert með mikið af þessum gögnum ættir þú að íhuga hópflutning!
  3. skrifaðu kóðann þar sem þeir eru notaðir BÆÐI и Og gamla dálki. Nú er app útgáfan þín 2.0.0
  4. lestu gildið úr dálknum surname, ef það er ekki null, eða frá last_name, ef að surname ekki tilgreint. Þú getur eytt getLastName() úr kóðanum, þar sem hann mun gefa út null þegar þú afturkallar umsókn þína frá 3.0.0 í 2.0.0.

Ef þú ert að nota Spring Boot Flyway verða þessi tvö skref framkvæmd við ræsingu útgáfunnar 2.0.0 umsóknir. Ef þú keyrir gagnagrunnsútgáfutólið handvirkt þarftu að gera tvo mismunandi hluti til að gera þetta (fyrst uppfærðu db útgáfuna handvirkt og dreifðu síðan nýja forritinu).

Það er mikilvægt. Mundu að nýstofnaður dálkur ÆTTI EKKI быть EKKI NULL. Ef þú gerir afturköllun, veit gamla forritið ekki um nýja dálkinn og mun ekki setja hann upp á meðan Insert. En ef þú bætir við þessari þvingun og db þín verður v2, til þess þarf að stilla gildi nýja dálksins. Sem mun leiða til brota á höftum.

Það er mikilvægt. Þú ættir að fjarlægja aðferðina getLastName(), vegna þess að í útgáfunni 3.0.0 Það er ekkert hugtak um dálk í kóðanum last_name. Þetta þýðir að núll verður sett þar. Þú getur yfirgefið aðferðina og bætt við ávísunum fyrir null, en miklu betri lausn væri að ganga úr skugga um að í rökfræðinni getSurname() þú valdir rétt gildi sem er ekki núll.

A/B próf

Núverandi staða er sú að við erum með forritaútgáfu 1.0.0, sett á framleiðslu, og gagnagrunnurinn í v1. Við þurfum að dreifa öðru tilviki útgáfuforritsins 2.0.0sem mun uppfæra gagnagrunninn í v2.

Skref:

  1. nýtt tilvik af útgáfuforritinu er notað 2.0.0sem uppfærir gagnagrunninn í v2
  2. í millitíðinni voru sumar beiðnir unnar af útgáfutilvikum 1.0.0
  3. uppfærslan tókst og þú ert með mörg hlaupandi tilvik af útgáfuforritinu 1.0.0 og aðrar útgáfur 2.0.0. Allir hafa samskipti við gagnagrunninn í v2
  4. útgáfa 1.0.0 notar ekki eftirnafnsdálkinn í gagnagrunninum heldur útgáfuna 2.0.0 notar. Þeir trufla ekki hvort annað og það ættu engar villur að vera.
  5. útgáfa 2.0.0 geymir gögn bæði í gamla og nýja dálknum, sem tryggir afturábak eindrægni

Það er mikilvægt. Ef þú hefur einhverjar fyrirspurnir sem telja atriði byggð á gildum úr gamla/nýja dálknum, ættirðu að muna að þú ert núna með tvöföld gildi (líklegast eru þau enn að flytja). Til dæmis, ef þú vilt telja fjölda notenda sem hafa eftirnafn (hvað sem dálkurinn heitir) sem byrjaði á bókstafnum A, þá þar til gagnaflutningi er lokið (oldnew dálki) gætirðu verið með ósamkvæm gögn ef þú spyrð um nýjan dálk.

Til baka umsókn

Nú höfum við app útgáfu 2.0.0 og gagnagrunnur í v2.

Skref:

  1. snúðu forritinu þínu aftur í útgáfu 1.0.0.
  2. útgáfa 1.0.0 notar ekki dálk í gagnagrunninum surname, þannig að afturköllunin ætti að ganga vel

DB breytingar

Gagnagrunnurinn inniheldur dálk sem heitir last_name.

Upprunahandrit flugbrautar:

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

Bæta við handriti surname.

Athygli. Mundu að þú GETUR EKKI BÆTT neinum NOT NULL takmörkunum við dálkinn sem þú ert að bæta við. Ef þú afturkallar JAR, mun gamla útgáfan ekki hafa hugmynd um dálkinn sem bætt var við og mun sjálfkrafa stilla hann á NULL. Ef slík takmörkun er til staðar mun gamla forritið einfaldlega brotna.

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

Kóðabreytingar

Við geymum gögn sem last_name, og í surname. Á sama tíma lesum við úr last_name, þar sem þessi dálkur á mest við. Meðan á dreifingarferlinu stóð gætu sumar beiðnir verið unnar af forritatilviki sem hefur ekki enn verið uppfært.

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

Skref 3: Fjarlægir eftirnafn úr kóðanum

Útgáfa forrits: 3.0.0

DB útgáfa:v3

Athugasemd

Athugið per.: Svo virðist sem höfundur í upprunalegu greininni afritaði fyrir mistök texta þessa blokk úr skrefi 2. Í þessu skrefi ætti að gera breytingar á forritskóðanum sem miða að því að fjarlægja virknina sem notar dálkinn last_name.

Með því að bæta við nýjum dálki og afrita innihald hans, bjuggum við til bakábaksamhæfðar breytingar á gagnagrunni. Einnig, ef við snúum JAR til baka eða erum með gamla JAR í gangi, þá brotnar hann ekki við framkvæmd.

Til baka umsókn

Eins og er höfum við app útgáfu 3.0.0 og gagnasafn v3. Útgáfa 3.0.0 vistar ekki gögn til last_name. Þetta þýðir að í surname nýjustu upplýsingarnar eru geymdar.

Skref:

  1. snúðu forritinu þínu aftur í útgáfu 2.0.0.
  2. útgáfa 2.0.0 notar og last_name и surname.
  3. útgáfa 2.0.0 mun taka surname, ef það er ekki núll, annars -last_name

Gagnagrunnsbreytingar

Engar skipulagsbreytingar eru á gagnagrunninum. Eftirfarandi forskrift er keyrð til að framkvæma lokaflutning gömlu gagna:

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

Kóðabreytingar

Athugið per.: Lýsingin á þessum reit var einnig ranglega afrituð af höfundi frá skrefi 2. Í samræmi við rökfræði greinarinnar ættu breytingar á kóðanum í þessu skrefi að miða að því að fjarlægja úr honum þætti sem vinna með dálknum last_name.

Við geymum gögn sem last_name, og í surname. Að auki lesum við úr pistlinum last_name, þar sem það á mest við. Meðan á dreifingarferlinu stendur gætu sumar beiðnir verið unnar af tilviki sem hefur ekki enn verið uppfært.

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

Skref 4: Fjarlægir eftirnafn úr gagnagrunninum

Útgáfa forrits: 4.0.0

DB útgáfa: v4

Athugasemd

Vegna þess að útgáfukóði 3.0.0 notaði ekki dálkinn last_name, ekkert slæmt mun gerast við framkvæmd ef við snúum aftur til 3.0.0 eftir að dálkur hefur verið fjarlægður úr gagnagrunninum.

Framkvæmdaskrár skriftu

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 breytingar

Tiltölulega v3 við fjarlægjum bara dálkinn last_name og bæta við takmörkunum sem vantar.

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

Kóðabreytingar

Það eru engar breytingar á kóðanum.

Output

Okkur tókst að breyta afturábak-ósamhæfðri dálknafni með því að framkvæma nokkrar afturábaksamhæfar dreifingar. Hér að neðan er yfirlit yfir þær aðgerðir sem gerðar eru:

  1. dreifing forritsútgáfu 1.0.0 с v1 gagnagrunnsskema (dálknafn = last_name)
  2. dreifing forritsútgáfu 2.0.0, sem geymir gögn í last_name и surname. Umsóknin les úr last_name. Gagnagrunnurinn er í útgáfu v2sem inniheldur dálka eins og last_nameOg surname. surname er afrit af last_name. (ATH: Þessi dálkur má ekki hafa ekki núll þvingun)
  3. dreifing forritsútgáfu 3.0.0, sem aðeins geymir gögn í surname og les úr eftirnafni. Hvað gagnagrunninn varðar þá er síðasta flutningurinn að eiga sér stað last_name в surname. Einnig takmörkun EKKI NULL fjarlægð úr last_name. Gagnagrunnurinn er nú kominn í útgáfu v3
  4. dreifing forritsútgáfu 4.0.0 - engar breytingar eru gerðar á kóðanum. Uppsetning gagnagrunns v4, sem fjarlægir last_name. Hér getur þú bætt öllum skorðum sem vantar við gagnagrunninn.

Með því að fylgja þessari nálgun geturðu alltaf snúið einni útgáfu til baka án þess að rjúfa samhæfni gagnagrunns/forrita.

Code

Allur kóði sem notaður er í þessari grein er fáanlegur á GitHub. Hér að neðan er viðbótarlýsing.

Verkefni

Eftir að hafa klónað geymsluna muntu sjá eftirfarandi möppuskipulag.

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

Handrit

Þú getur keyrt forskriftirnar sem lýst er í forskriftunum hér að neðan, sem sýna afturábak-samhæfar og ósamrýmanlegar breytingar á gagnagrunninum.

Til að sjá málið með afturábak samhæfðum breytingum, keyra:

./scripts/scenario_backward_compatible.sh

Og að sjá tilfelli með afturábak ósamhæfðar breytingar, keyra:

./scripts/scenario_backward_incompatible.sh

Spring Boot Sample Flyway

Öll dæmi eru tekin úr Spring Boot Sample Flyway.

Þú getur kíkt á http://localhost:8080/flyway, það er listi yfir handrit.

Þetta dæmi inniheldur einnig H2 leikjatölvuna (kl http://localhost:8080/h2-console) svo þú getir skoðað stöðu gagnagrunnsins (sjálfgefin jdbc vefslóð er jdbc:h2:mem:testdb).

auki

Lestu einnig aðrar greinar á blogginu okkar:

Heimild: www.habr.com

Bæta við athugasemd