Usambazaji na Hifadhidata Sifuri za Kupungua

Usambazaji na Hifadhidata Sifuri za Kupungua

Makala haya yanaeleza kwa kina jinsi ya kutatua masuala ya uoanifu wa hifadhidata katika utumaji. Tutakuambia nini kinaweza kutokea kwa programu zako za uzalishaji ikiwa utajaribu kupeleka bila maandalizi ya awali. Kisha tutapitia hatua za mzunguko wa maisha ya maombi ambazo zinahitajika kuwa na sifuri ya kupumzika (takriban. lane: zaidi - sifuri downtime) Matokeo ya utendakazi wetu yatakuwa ni kutumia mabadiliko ya hifadhidata ya nyuma-yasiyotangamana kwa namna ya kurudi nyuma.

Ikiwa unataka kuelewa mifano ya msimbo kutoka kwa kifungu, unaweza kuipata GitHub.

Utangulizi

Usambazaji wa muda usiopungua sifuri

Ni fumbo gani sifuri kupelekwa kwa wakati wa kupumzika? Unaweza kusema huu ni wakati programu yako inatumwa kwa njia ambayo unaweza kutambulisha toleo jipya la programu kwa toleo la umma kwa mafanikio, huku mtumiaji haoni kutopatikana kwake. Kwa mtazamo wa mtumiaji na kampuni, hii ndiyo hali bora zaidi ya utumiaji kwa sababu inaruhusu vipengele vipya kuanzishwa na hitilafu kurekebishwa bila kukatizwa.

Jinsi ya kufikia hili? Kuna njia kadhaa, hapa kuna moja yao:

  • tumia toleo la 1 la huduma yako
  • fanya uhamiaji wa hifadhidata
  • Tumia toleo la #2 la huduma yako sambamba na toleo la #1
  • punde tu unapoona toleo hilo Na. 2 likifanya kazi inavyopaswa, ondoa toleo la 1
  • tayari!

Rahisi, sivyo? Kwa bahati mbaya, sio rahisi sana, na tutazingatia kwa undani baadaye. Sasa hebu tuangalie mchakato mwingine wa kawaida wa kupeleka - uwekaji wa kijani kibichi.

Umewahi kusikia kupelekwa kwa kijani kibichi? Cloud Foundry hurahisisha sana hii. Angalia tu nakala hii, ambapo tunaelezea hili kwa undani zaidi. Kwa muhtasari mfupi, hebu tukumbushe jinsi ya kufanya uwekaji wa kijani kibichi:

  • hakikisha kwamba nakala mbili za msimbo wako wa uzalishaji (“bluu” na “kijani”) zinafanya kazi;
  • kuelekeza trafiki yote kwenye mazingira ya bluu, i.e. ili URL za uzalishaji zielekeze hapo;
  • kupeleka na kupima mabadiliko yote ya maombi katika mazingira ya kijani;
  • badilisha url kutoka mazingira ya bluu hadi kijani kibichi

Utumiaji wa kijani kibichi ni mbinu inayokuruhusu kutambulisha vipengele vipya kwa urahisi bila kuwa na wasiwasi kuhusu kuvunjika kwa uzalishaji. Hii ni kutokana na ukweli kwamba hata jambo likitokea, unaweza kurudi kwa urahisi kwenye mazingira ya awali kwa "kubamiza swichi."

Baada ya kusoma yote yaliyo hapo juu, unaweza kuuliza swali: Je, kupungua kwa sifuri kuna uhusiano gani na kupelekwa kwa Bluu ya kijani?

Kweli, wana mengi sawa, kwa kuwa kudumisha nakala mbili za mazingira sawa kunahitaji bidii mara mbili kuzidumisha. Ndio maana baadhi ya timu zinadai Martin Fowler, fuata tofauti ya mbinu hii:

Chaguo jingine ni kutumia hifadhidata sawa, kuunda swichi za bluu-kijani kwa tabaka za wavuti na kikoa. Kwa njia hii, database inaweza mara nyingi kuwa tatizo, hasa wakati unahitaji kubadilisha schema yake ili kusaidia toleo jipya la programu.

Na hapa tunakuja kwa shida kuu katika nakala hii. Database. Hebu tuangalie tena msemo huu.

fanya uhamishaji wa hifadhidata.

Sasa unapaswa kujiuliza swali - vipi ikiwa mabadiliko ya hifadhidata hayaendani nyuma? Je, toleo langu la kwanza la programu halitakatika? Kwa kweli, hii ndio hasa kitakachotokea ...

Kwa hivyo, hata licha ya faida kubwa za kupunguzwa kwa sifuri / uwekaji wa kijani kibichi, kampuni huwa na kufuata mchakato salama zaidi wa kupeleka maombi yao:

  • tayarisha kifurushi na toleo jipya la programu
  • funga programu inayoendesha
  • endesha maandishi ili kuhamisha hifadhidata
  • tuma na uzindue toleo jipya la programu

Katika makala haya, tutaeleza kwa kina jinsi unavyoweza kufanya kazi na hifadhidata na msimbo wako ili kuchukua fursa ya kutoweka kwa muda usiopungua.

Matatizo ya hifadhidata

Iwapo una programu isiyo na uraia ambayo haihifadhi data yoyote kwenye hifadhidata, unaweza kupata utumaji wa muda usiopungua sifuri mara moja. Kwa bahati mbaya, programu nyingi zinahitaji kuhifadhi data mahali fulani. Ndiyo sababu unapaswa kufikiria mara mbili kabla ya kufanya mabadiliko yoyote kwenye mzunguko. Kabla hatujaingia katika maelezo ya jinsi ya kubadilisha schema ili uwekaji wa wakati wa chini uwezekane, hebu kwanza tuzingatie schema ya uchapishaji.

Mpango wa utayarishaji

Katika makala hii tutatumia Njia ya kuruka kama zana ya kudhibiti toleo (takriban. Tafsiri: tunazungumza juu ya uhamiaji wa hifadhidata) Kwa kawaida, tutaandika pia programu ya Spring Boot ambayo ina usaidizi wa ndani wa Flyway na itafanya uhamishaji wa schema wakati wa kusanidi muktadha wa programu. Unapotumia Flyway, unaweza kuhifadhi hati za uhamiaji kwenye folda ya miradi yako (kwa chaguo-msingi in classpath:db/migration) Hapa unaweza kuona mfano wa faili kama hizo za uhamiaji

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

Katika mfano huu tunaona hati 4 za uhamiaji ambazo, ikiwa hazijatekelezwa hapo awali, zitatekelezwa moja baada ya nyingine wakati programu itaanza. Wacha tuangalie faili moja (V1__init.sql) kama mfano.

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

Kila kitu kinajieleza kikamilifu: unaweza kutumia SQL kufafanua jinsi hifadhidata yako inapaswa kurekebishwa. Kwa habari zaidi kuhusu Spring Boot na Flyway, angalia Hati za Boot ya Spring.

Kwa kutumia zana ya kudhibiti chanzo na Spring Boot, unapata faida 2 kubwa:

  • unatenganisha mabadiliko ya hifadhidata kutoka kwa mabadiliko ya nambari
  • Uhamishaji wa hifadhidata hutokea pamoja na uchapishaji wa programu yako, i.e. mchakato wako wa kusambaza umerahisishwa

Kutatua matatizo ya hifadhidata

Katika sehemu inayofuata ya kifungu, tutazingatia kuangalia njia mbili za mabadiliko ya hifadhidata.

  • kutopatana kwa nyuma
  • utangamano wa nyuma

Ya kwanza itazingatiwa kuwa onyo kwamba hupaswi kutekeleza uwekaji wa muda wa sifuri bila maandalizi ya awali... Ya pili inatoa suluhisho la jinsi unavyoweza kutekeleza upelekaji bila muda wa kupungua na wakati huo huo kudumisha utangamano wa nyuma.

Mradi wetu tutakaoufanyia kazi utakuwa ni programu rahisi ya Spring Boot Flyway ambayo ina Person с first_name и last_name katika hifadhidata (takriban. tafsiri: Person ni meza na first_name и last_name - haya ni mashamba ndani yake) Tunataka kubadilisha jina last_name в surname.

Mawazo

Kabla ya kuingia katika maelezo, kuna mawazo kadhaa tunayohitaji kufanya kuhusu maombi yetu. Matokeo kuu tunayotaka kufikia yatakuwa mchakato rahisi sana.

noti. Biashara PRO-TIP. Michakato ya kurahisisha inaweza kukuokoa pesa nyingi kwenye usaidizi (kadiri unavyokuwa na watu wengi wanaofanya kazi kwenye kampuni yako, ndivyo pesa nyingi unavyoweza kuokoa)!

Hakuna haja ya kurejesha hifadhidata

Hii hurahisisha mchakato wa kupeleka (baadhi ya urejeshaji wa hifadhidata ni karibu kutowezekana, kama vile urejeshaji wa kufuta). Tunapendelea kurudisha nyuma programu tu. Kwa njia hii, hata ikiwa una hifadhidata tofauti (kwa mfano, SQL na NoSQL), bomba lako la kupeleka litaonekana sawa.

Ni lazima kila wakati iweze kurudisha nyuma programu toleo moja (hakuna zaidi)

Kurudisha nyuma kunapaswa kufanywa tu ikiwa ni lazima. Ikiwa kuna hitilafu katika toleo la sasa ambayo hairekebishwi kwa urahisi, tunapaswa kuwa na uwezo wa kurejesha toleo jipya zaidi la kufanya kazi. Tunadhani kwamba toleo hili la hivi karibuni la kufanya kazi ni la awali. Kudumisha misimbo na upatanifu wa hifadhidata kwa zaidi ya moja ya uchapishaji itakuwa ngumu sana na ghali.

noti. Kwa usomaji zaidi, katika nakala hii tutabadilisha toleo kuu la programu.

Hatua ya 1: Jimbo la Awali

Toleo la programu: 1.0.0
Toleo la DB: v1

Maoni

Hii itakuwa hali ya awali ya maombi.

Mabadiliko ya hifadhidata

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

Mabadiliko ya kanuni

Programu huhifadhi data ya Mtu ndani 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
                + "]";
    }
}

Ubadilishaji jina upya wa safu wima ambao hauoani nyuma

Wacha tuangalie mfano wa jinsi ya kubadilisha jina la safu:

Tahadhari. Mfano ufuatao utavunja mambo kimakusudi. Tunaonyesha hii ili kuonyesha tatizo la uoanifu wa hifadhidata.

Toleo la programu: 2.0.0.BAD

Toleo la DB: v2bad

Maoni

Mabadiliko ya sasa HAYATUruhusu kuendesha matukio mawili (ya zamani na mpya) kwa wakati mmoja. Kwa hivyo, kupelekwa kwa muda wa sifuri itakuwa vigumu kufikia (ikiwa mawazo yanazingatiwa, kwa kweli haiwezekani).

Mtihani wa A/B

Hali ya sasa ni kwamba tunayo toleo la programu 1.0.0, kupelekwa katika uzalishaji, na hifadhidata v1. Tunahitaji kupeleka mfano wa pili wa programu, toleo 2.0.0.BAD, na usasishe hifadhidata kwa v2bad.

Hatua:

  1. mfano mpya wa programu ya toleo unatumika 2.0.0.BADambayo husasisha hifadhidata kwa v2bad
  2. katika hifadhidata v2bad safu last_name haipo tena - ilibadilishwa kuwa surname
  3. Hifadhidata na sasisho la programu lilifanikiwa na visa vingine vinaendelea 1.0.0, wengine - ndani 2.0.0.BAD. Kila kitu kimeunganishwa kwenye hifadhidata v2bad
  4. matukio yote ya toleo 1.0.0 wataanza kutupa makosa kwa sababu watajaribu kuingiza data kwenye safu last_nameambaye hayupo tena
  5. matukio yote ya toleo 2.0.0.BAD itafanya kazi bila matatizo

Kama unavyoona, ikiwa tutafanya mabadiliko ya nyuma yasiyolingana kwenye hifadhidata na programu, majaribio ya A/B hayawezekani.

Urejeshaji wa programu

Wacha tufikirie kuwa baada ya kujaribu kupeleka A/B (takriban. kwa.: mwandishi labda alimaanisha upimaji wa A/B hapa) tuliamua kwamba tunahitaji kurejesha programu kwenye toleo 1.0.0. Wacha tuseme hatutaki kurudisha hifadhidata.

Hatua:

  1. tunasimamisha mfano wa programu ya toleo 2.0.0.BAD
  2. hifadhidata bado v2bad
  3. tangu toleo 1.0.0 haielewi ni nini surname, tutaona makosa
  4. kuzimu imekatika, hatuwezi kurudi nyuma tena

Kama unavyoona, ikiwa tutafanya mabadiliko ya nyuma yasiyolingana kwenye hifadhidata na programu, hatuwezi kurudi kwenye toleo la awali.

Kumbukumbu za utekelezaji wa hati

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

Mabadiliko ya hifadhidata

Hati ya uhamiaji ambayo hubadilisha jina last_name в surname

Chanzo cha maandishi ya Flyway:

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

Hati inayobadilisha jina last_name.

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

Mabadiliko ya kanuni

Tumebadilisha jina la uwanja lastName juu ya surname.

Kubadilisha jina la safuwima kwa njia inayolingana na nyuma

Hii ndiyo hali ya kawaida ambayo tunaweza kukutana nayo. Tunahitaji kufanya mabadiliko ya nyuma yasiyolingana. Tayari tumethibitisha kuwa kwa matumizi ya muda usiopungua sifuri, hatupaswi tu kutumia uhamishaji wa hifadhidata bila hatua za ziada. Katika sehemu hii ya makala, tutafanya utumaji programu mara 3 pamoja na uhamishaji wa hifadhidata ili kufikia matokeo unayotaka huku tukidumisha uoanifu wa kurudi nyuma.

noti. Kumbuka kwamba tuna hifadhidata ya toleo v1. Ina safu first_name и last_name. Inabidi tubadilike last_name juu ya surname. Pia tunayo toleo la programu 1.0.0, ambayo bado haijatumika surname.

Hatua ya 2: Ongeza jina la ukoo

Toleo la programu: 2.0.0
Toleo la DB: v2

Maoni

Kwa kuongeza safu wima mpya na kunakili yaliyomo, tunaunda mabadiliko ya hifadhidata yanayoendana nyuma. Wakati huo huo, ikiwa tutarudisha JAR au kuwa na JAR ya zamani inayoendesha, haitavunjika wakati wa utekelezaji.

Tunatoa toleo jipya

Hatua:

  1. fanya uhamishaji wa hifadhidata ili kuunda safu mpya surname. Sasa toleo lako la DB v2
  2. nakala data kutoka last_name в surname. Makinikwamba ikiwa una data hii nyingi, unapaswa kuzingatia uhamiaji wa kundi!
  3. andika msimbo ambapo zinatumika ZOTE и mpyaNa zamani safu. Sasa toleo la programu yako 2.0.0
  4. soma thamani kutoka kwa safu surname, ikiwa sivyo null, au kutoka kwa last_nameikiwa surname haijabainishwa. Unaweza kufuta getLastName() kutoka kwa nambari, kwani itatoa null unaporejesha ombi lako kutoka 3.0.0 kwa 2.0.0.

Ikiwa unatumia Spring Boot Flyway, hatua hizi mbili zitafanywa wakati wa kuanzisha toleo 2.0.0 maombi. Ikiwa utaendesha zana ya uchapishaji ya hifadhidata kwa mikono, itabidi ufanye mambo mawili tofauti kufanya hivi (kwanza sasisha toleo la db mwenyewe na kisha upeleke programu mpya).

Ni muhimu. Kumbuka kwamba safu mpya iliyoundwa HAIPASWI kuwa SI NULL. Ukirudisha nyuma, programu ya zamani haijui kuhusu safu wima mpya na haitaisakinisha wakati huo Insert. Lakini ukiongeza kizuizi hiki na db yako itakuwa v2, hii itahitaji kuweka thamani ya safu mpya. Ambayo itasababisha ukiukwaji wa vikwazo.

Ni muhimu. Unapaswa kuondoa mbinu getLastName(), kwa sababu katika toleo 3.0.0 Hakuna dhana ya safu katika msimbo last_name. Hii inamaanisha kuwa null itawekwa hapo. Unaweza kuacha njia na kuongeza hundi kwa null, lakini suluhisho bora zaidi itakuwa kuhakikisha kuwa katika mantiki getSurname() umechagua thamani sahihi isiyo ya sifuri.

Mtihani wa A/B

Hali ya sasa ni kwamba tunayo toleo la programu 1.0.0, iliyotumika kwenye uzalishaji, na hifadhidata ndani v1. Tunahitaji kupeleka mfano wa pili wa programu ya toleo 2.0.0ambayo itasasisha hifadhidata kuwa v2.

Hatua:

  1. mfano mpya wa programu ya toleo unatumika 2.0.0ambayo husasisha hifadhidata kwa v2
  2. wakati huo huo baadhi ya maombi yalichakatwa na matukio ya matoleo 1.0.0
  3. sasisho lilifanikiwa na una matukio mengi ya uendeshaji ya programu ya toleo 1.0.0 na matoleo mengine 2.0.0. Kila mtu anawasiliana na hifadhidata ndani v2
  4. toleo 1.0.0 haitumii safu ya jina la ukoo kwenye hifadhidata, lakini toleo 2.0.0 matumizi. Haziingiliani na kila mmoja, na haipaswi kuwa na makosa.
  5. toleo 2.0.0 huhifadhi data katika safu wima ya zamani na mpya, kuhakikisha upatanifu wa nyuma

Ni muhimu. Ikiwa una maswali yoyote ambayo huhesabu vipengee kulingana na maadili kutoka safu ya zamani/mpya, unapaswa kukumbuka kuwa sasa una nakala za thamani (uwezekano mkubwa zaidi bado zinahama). Kwa mfano, ikiwa unataka kuhesabu idadi ya watumiaji ambao jina la mwisho (chochote safu inaitwa) ilianza na barua A, basi hadi uhamishaji wa data ukamilike (oldnew column) unaweza kuwa na data isiyolingana ikiwa utauliza safu mpya.

Urejeshaji wa programu

Sasa tunayo toleo la programu 2.0.0 na hifadhidata ndani v2.

Hatua:

  1. rudisha programu yako kwenye toleo 1.0.0.
  2. toleo 1.0.0 haitumii safu katika hifadhidata surname, kwa hivyo urejeshaji unapaswa kufanikiwa

Mabadiliko ya DB

Hifadhidata ina safu wima iliyopewa jina last_name.

Hati ya chanzo cha Flyway:

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

Ongeza hati surname.

Tahadhari. Kumbuka kuwa HUWEZI KUONGEZA vizuizi vyovyote SI BATILI kwenye safu wima unayoongeza. Ukirudisha nyuma JAR, toleo la zamani halitakuwa na wazo kuhusu safu wima iliyoongezwa na itaiweka kiotomatiki kuwa NULL. Ikiwa kuna kizuizi kama hicho, programu ya zamani itavunjika tu.

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

Mabadiliko ya kanuni

Tunahifadhi data kama last_name, na surname. Wakati huo huo tunasoma kutoka last_name, kwa kuwa safu hii ndiyo inayofaa zaidi. Wakati wa mchakato wa kupeleka, baadhi ya maombi yanaweza kuwa yamechakatwa na mfano wa maombi ambayo bado hayajasasishwa.

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

Hatua ya 3: Kuondoa last_name kutoka kwa msimbo

Toleo la programu: 3.0.0

Toleo la DB:v3

Maoni

Kumbuka kwa.: Inavyoonekana, katika makala asili mwandishi alinakili kimakosa maandishi ya kizuizi hiki kutoka hatua ya 2. Katika hatua hii, mabadiliko yanapaswa kufanywa katika msimbo wa maombi yenye lengo la kuondoa utendaji unaotumia safu wima. last_name.

Kwa kuongeza safu wima mpya na kunakili yaliyomo, tuliunda mabadiliko ya hifadhidata yanayoendana nyuma. Pia, ikiwa tutarudisha JAR au kuwa na JAR ya zamani inayoendesha, haitavunjika wakati wa utekelezaji.

Urejeshaji wa programu

Kwa sasa tuna toleo la programu 3.0.0 na hifadhidata v3. Toleo 3.0.0 haihifadhi data kwa last_name. Hii ina maana kwamba katika surname habari ya kisasa zaidi huhifadhiwa.

Hatua:

  1. rudisha programu yako kwenye toleo 2.0.0.
  2. toleo 2.0.0 matumizi na last_name и surname.
  3. toleo 2.0.0 itachukua surname, ikiwa sio sifuri, vinginevyo -last_name

Mabadiliko ya hifadhidata

Hakuna mabadiliko ya kimuundo katika hifadhidata. Hati ifuatayo inatekelezwa ili kutekeleza uhamishaji wa mwisho wa data ya zamani:

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

Mabadiliko ya kanuni

Kumbuka kwa: Maelezo ya kizuizi hiki pia yalinakiliwa kimakosa na mwandishi kutoka hatua ya 2. Kwa mujibu wa mantiki ya kifungu, mabadiliko katika kanuni katika hatua hii yanapaswa kulenga kuondoa kutoka humo vipengele vinavyofanya kazi na safu. last_name.

Tunahifadhi data kama last_name, na surname. Zaidi ya hayo, tunasoma kutoka kwenye safu last_name, kwa kuwa ni muhimu zaidi. Wakati wa mchakato wa kupeleka, baadhi ya maombi yanaweza kushughulikiwa na mfano ambao bado haujasasishwa.

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

Hatua ya 4: Kuondoa last_name kutoka kwa hifadhidata

Toleo la programu: 4.0.0

Toleo la DB: v4

Maoni

Kutokana na ukweli kwamba msimbo wa toleo 3.0.0 hakutumia safu last_name, hakuna kitu kibaya kitatokea wakati wa utekelezaji ikiwa tutarudi nyuma 3.0.0 baada ya kuondoa safu kutoka kwa hifadhidata.

Kumbukumbu za utekelezaji wa hati

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

Mabadiliko ya DB

Jamaa v3 tunaondoa safu tu last_name na kuongeza vikwazo vilivyokosekana.

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

Mabadiliko ya kanuni

Hakuna mabadiliko kwenye msimbo.

Pato

Tumefaulu kutekeleza badiliko la jina la safu wima ambalo halioani na nyuma kwa kutekeleza utumaji kadhaa unaoendana na nyuma. Ufuatao ni muhtasari wa vitendo vilivyofanywa:

  1. uwekaji wa toleo la programu 1.0.0 с v1 schema ya hifadhidata (jina la safuwima = last_name)
  2. uwekaji wa toleo la programu 2.0.0, ambayo huhifadhi data ndani last_name и surname. Maombi yanasoma kutoka last_name. Hifadhidata iko katika toleo v2zenye safu kama last_nameNa surname. surname ni nakala ya last_name. (KUMBUKA: safu wima hii lazima isiwe na kizuizi kisicho batili)
  3. uwekaji wa toleo la programu 3.0.0, ambayo huhifadhi data ndani pekee surname na anasoma kutoka kwa jina la ukoo. Kama kwa hifadhidata, uhamiaji wa mwisho unafanyika last_name в surname. Pia kizuizi SI NULL kuondolewa kutoka last_name. Hifadhidata sasa iko katika toleo v3
  4. uwekaji wa toleo la programu 4.0.0 - hakuna mabadiliko yanayofanywa kwa kanuni. Usambazaji wa hifadhidata v4, ambayo huondoa last_name. Hapa unaweza kuongeza vikwazo vyovyote vinavyokosekana kwenye hifadhidata.

Kwa kufuata mbinu hii, unaweza kurejesha toleo moja kila wakati bila kuvunja hifadhidata/utangamano wa programu.

Kanuni

Nambari zote zilizotumiwa katika nakala hii zinapatikana Github. Chini ni maelezo ya ziada.

Miradi

Baada ya kuunda hazina, utaona muundo wa folda ifuatayo.

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

Hati

Unaweza kuendesha hati zilizofafanuliwa katika hati zilizo hapa chini, ambazo zitaonyesha mabadiliko yanayoendana nyuma na yasiyopatana kwenye hifadhidata.

Kuona kesi na mabadiliko yanayoendana nyuma, kukimbia:

./scripts/scenario_backward_compatible.sh

Na kuona kesi na mabadiliko ya nyuma yasiyoendana, kukimbia:

./scripts/scenario_backward_incompatible.sh

Spring Boot Sampuli Flyway

Mifano yote imechukuliwa kutoka Spring Boot Sample Flyway.

Unaweza kuangalia http://localhost:8080/flyway, kuna orodha ya maandishi.

Mfano huu pia ni pamoja na koni ya H2 (saa http://localhost:8080/h2-console) kwa hivyo unaweza kutazama hali ya hifadhidata (URL chaguomsingi ya jdbc ni jdbc:h2:mem:testdb).

kuongeza

Pia soma nakala zingine kwenye blogi yetu:

Chanzo: mapenzi.com

Kuongeza maoni