Zero Downtime Deployment ug Databases

Zero Downtime Deployment ug Databases

Kini nga artikulo nagpatin-aw sa detalye kung giunsa pagsulbad ang mga isyu sa pagkaangay sa database sa pag-deploy. Isulti namo kanimo kung unsa ang mahimong mahitabo sa imong mga aplikasyon sa produksiyon kung sulayan nimo ang pag-deploy nga wala’y pasiuna nga pagpangandam. Moagi kami sa mga yugto sa lifecycle sa aplikasyon nga gikinahanglan nga adunay zero downtime (gibanabana. lane: dugang pa - zero downtime). Ang resulta sa among mga operasyon mao ang paggamit sa backwards-incompatible database change sa backwards-compatible nga paagi.

Kung gusto nimong masabtan ang mga pananglitan sa code gikan sa artikulo, makit-an nimo kini sa GitHub.

Pasiuna

Zero downtime deployment

Unsa ka misteryoso zero downtime deployment? Mahimo nimong isulti nga kini kung ang imong aplikasyon gi-deploy sa paagi nga malampuson nimo nga gipaila ang usa ka bag-ong bersyon sa aplikasyon sa produksiyon, samtang ang gumagamit wala makamatikod sa pagkadili magamit niini. Gikan sa panan-aw sa tiggamit ug kompanya, kini ang labing kaayo nga posible nga senaryo sa pag-deploy tungod kay gitugotan niini ang mga bag-ong bahin nga ipakilala ug ang mga bug ayohon nga wala’y pagkabalda.

Unsaon pagkab-ot niini? Adunay daghang mga paagi, ania ang usa kanila:

  • i-deploy ang bersyon No. 1 sa imong serbisyo
  • paghimo sa usa ka database migration
  • I-deploy ang bersyon #2 sa imong serbisyo nga parehas sa bersyon #1
  • sa diha nga imong makita nga ang bersyon Num. 2 molihok ingon nga kini kinahanglan, kuhaa ang bersyon No. 1
  • andam na!

Sayon, dili ba? Ikasubo, dili kini yano, ug atong tan-awon kana sa detalye sa ulahi. Karon atong susihon ang laing medyo komon nga proseso sa pagdeploy - blue green deployment.

Nakadungog ka na ba bahin sa asul nga berde nga pag-deploy? Gipadali kini sa Cloud Foundry. Tan-awa lang kini nga artikulo, diin atong gihulagway kini sa mas detalyado. Sa mubo nga pag-summarize, pahinumdoman ka namo kung unsaon paghimo sa blue green nga deployment:

  • siguroha nga duha ka kopya sa imong production code (“asul” ug “berde”) magtrabaho;
  • idirekta ang tanan nga trapiko sa asul nga palibot, i.e. aron ang mga URL sa produksiyon nagpunting didto;
  • pag-deploy ug pagsulay sa tanan nga mga pagbag-o sa aplikasyon sa usa ka berde nga palibot;
  • ibalhin ang mga url gikan sa asul ngadto sa berde nga palibot

Ang asul nga berde nga pag-deploy usa ka pamaagi nga nagtugot kanimo sa dali nga pagpaila sa mga bag-ong bahin nga wala mabalaka bahin sa pagkaguba sa produksiyon. Kini tungod sa kamatuoran nga bisan kung adunay mahitabo, dali ka nga makabalik sa miaging palibot pinaagi lamang sa "pag-flick sa usa ka switch."

Human mabasa ang tanan sa ibabaw, mahimo nimong ipangutana ang pangutana: Unsa ang kalabotan sa zero downtime sa pag-deploy sa Blue green?

Aw, sila adunay daghan nga komon, tungod kay ang pagmentinar sa duha ka kopya sa samang palibot nagkinahanglan ug dobleng paningkamot sa pagmentinar niini. Mao kini ang hinungdan ngano nga ang pipila ka mga team nag-angkon Martin Fowler, sunda ang usa ka kalainan niini nga pamaagi:

Ang laing kapilian mao ang paggamit sa samang database, paghimo og blue-green nga mga switch alang sa web ug domain layers. Niini nga pamaagi, ang database sa kasagaran mahimong problema, ilabi na kung kinahanglan nimo nga usbon ang schema niini aron suportahan ang bag-ong bersyon sa software.

Ug ania kita sa panguna nga problema sa kini nga artikulo. Database. Atong tan-awon pag-usab kini nga hugpong sa mga pulong.

paghimo sa usa ka database migration.

Karon kinahanglan nimong pangutan-on ang imong kaugalingon sa pangutana - unsa man kung ang pagbag-o sa database dili paatras nga katugma? Dili ba maguba ang akong unang bersyon sa app? Sa tinuud, kini gyud ang mahitabo ...

Mao nga, bisan pa sa daghang mga benepisyo sa zero downtime / blue green nga pag-deploy, ang mga kompanya lagmit nga nagsunod sa mosunod nga mas luwas nga proseso alang sa pag-deploy sa ilang mga aplikasyon:

  • pag-andam usa ka pakete nga adunay bag-ong bersyon sa aplikasyon
  • pagsira sa usa ka nagdagan nga aplikasyon
  • pagpadagan sa mga script aron ibalhin ang database
  • pag-deploy ug paglansad og bag-ong bersyon sa aplikasyon

Niini nga artikulo, among i-detalye kung giunsa nimo pagtrabaho ang imong database ug code aron mapahimuslan ang zero downtime deployment.

Mga isyu sa database

Kung ikaw adunay usa ka stateless nga aplikasyon nga wala magtipig bisan unsang datos sa database, mahimo nimo makuha ang zero downtime nga pag-deploy dayon. Ikasubo, kadaghanan sa software kinahanglan nga magtipig data sa usa ka lugar. Mao kini ang hinungdan nga kinahanglan ka maghunahuna sa makaduha sa dili pa maghimo bisan unsang mga pagbag-o sa circuit. Sa dili pa kita mosulod sa mga detalye kon unsaon pag-usab ang schema aron walay downtime nga pag-deploy posible, unahon nato ang pagtagad sa versioning schema.

Bersyon nga laraw

Niini nga artikulo atong gamiton Flyway isip usa ka himan sa pagkontrol sa bersyon (gibanabana. Paghubad: naghisgot kami bahin sa mga paglalin sa database). Natural, magsulat usab kami usa ka aplikasyon sa Spring Boot nga adunay built-in nga suporta sa Flyway ug magbuhat sa paglalin sa schema samtang nag-set up sa konteksto sa aplikasyon. Kung gigamit ang Flyway, mahimo nimong tipigan ang mga script sa pagbalhin sa imong folder sa mga proyekto (sa default sa classpath:db/migration). Dinhi imong makita ang usa ka pananglitan sa ingon nga mga file sa paglalin

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

Niini nga pananglitan atong makita ang 4 nga mga script sa paglalin nga, kung wala gipatuman kaniadto, ipatuman ang sunodsunod kung magsugod ang aplikasyon. Atong tan-awon ang usa sa mga file (V1__init.sql) isip pananglitan.

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

Ang tanan hingpit nga nagpatin-aw sa kaugalingon: mahimo nimong gamiton ang SQL aron mahibal-an kung giunsa ang pagbag-o sa imong database. Alang sa dugang nga impormasyon bahin sa Spring Boot ug Flyway, tan-awa Mga Dokumento sa Spring Boot.

Pinaagi sa paggamit sa usa ka himan sa pagkontrol sa gigikanan nga adunay Spring Boot, nakakuha ka 2 nga dagkong mga benepisyo:

  • gilain nimo ang mga pagbag-o sa database gikan sa mga pagbag-o sa code
  • Ang paglalin sa database mahitabo kauban ang paglansad sa imong aplikasyon, i.e. ang imong deployment nga proseso gipasayon

Pag-troubleshoot sa mga problema sa database

Sa sunod nga seksyon sa artikulo, magpunting kami sa pagtan-aw sa duha nga pamaagi sa pagbag-o sa database.

  • atras nga incompatibility
  • atras nga pagkaangay

Ang una pagaisipon ingon nga usa ka pasidaan nga dili nimo kinahanglan nga himuon ang zero downtime nga pag-deploy nga wala’y pasiuna nga pagpangandam... Ang ikaduha nagtanyag usa ka solusyon kung giunsa nimo mahimo ang usa ka deployment nga wala’y downtime ug sa parehas nga oras magpadayon sa atrasado nga pagkaangay.

Ang among proyekto nga among pagabuhaton usa ka yano nga aplikasyon sa Spring Boot Flyway nga adunay Person с first_name и last_name sa database (gibanabana. hubad: Person usa ka lamesa ug first_name и last_name - kini mao ang mga kaumahan niini). Gusto namong ilisan ang ngalan last_name в surname.

Mga pangagpas

Sa dili pa kita mosulod sa mga detalye, adunay pipila ka mga pangagpas nga kinahanglan natong buhaton mahitungod sa atong mga aplikasyon. Ang nag-unang resulta nga gusto natong makab-ot usa ka yano nga proseso.

Ang nota. Negosyo PRO-TIP. Ang pagpayano sa mga proseso makadaginot nimo ug daghang salapi sa suporta (sa mas daghang tawo ang imong pagtrabaho para sa imong kompanya, mas daghang salapi ang imong madaginot)!

Dili kinahanglan nga i-rollback ang database

Gipasimple niini ang proseso sa pag-deploy (ang ubang mga rollback sa database halos imposible, sama sa pagtangtang rollback). Gipalabi namo nga i-roll back lang ang mga aplikasyon. Niining paagiha, bisan kung naa kay lainlain nga mga database (pananglitan, SQL ug NoSQL), parehas ang hitsura sa imong pipeline sa pag-deploy.

Kanunay nga posible nga ibalik ang aplikasyon usa ka bersyon balik (wala na)

Ang rollback kinahanglan lang buhaton kung gikinahanglan. Kung adunay usa ka bug sa karon nga bersyon nga dili dali masulbad, kinahanglan naton nga ibalik sa labing bag-o nga bersyon sa pagtrabaho. Nagtuo kami nga kini nga labing bag-o nga bersyon sa pagtrabaho mao ang nauna. Ang pagmintinar sa code ug database compatibility alang sa labaw sa usa ka rollout mahimong hilabihan ka lisud ug mahal.

Ang mubo nga sulat. Alang sa labi ka dali mabasa, sa kini nga artikulo usbon namon ang mayor nga bersyon sa aplikasyon.

Lakang 1: Inisyal nga Estado

Bersyon sa app: 1.0.0
Bersyon sa DB: v1

comment

Kini ang mahimong inisyal nga kahimtang sa aplikasyon.

Mga pagbag-o sa database

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

Mga pagbag-o sa code

Ang aplikasyon nagtipig sa datos sa Tawo sa 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
                + "]";
    }
}

Balik nga dili tugma nga pag-ilis sa ngalan sa kolum

Atong tan-awon ang usa ka pananglitan kung unsaon pag-ilis sa ngalan sa kolum:

Pagtagad. Ang mosunod nga pananglitan tinuyo nga makaguba sa mga butang. Gipakita namo kini aron ipakita ang problema sa pagkaangay sa database.

Bersyon sa app: 2.0.0.BAD

Bersyon sa DB: v2bad

comment

Ang kasamtangan nga mga pagbag-o DILI magtugot kanamo sa pagpadagan sa duha ka mga higayon (daan ug bag-o) sa samang higayon. Busa, ang zero downtime deployment mahimong lisud nga makab-ot (kung ang mga pangagpas gikonsiderar, kini sa tinuud imposible).

Pagsulay sa A/B

Ang kasamtangan nga sitwasyon mao nga kita adunay usa ka bersyon sa aplikasyon 1.0.0, gipakatap sa produksiyon, ug database v1. Kinahanglan namon nga i-deploy ang ikaduha nga higayon sa aplikasyon, bersyon 2.0.0.BAD, ug i-update ang database sa v2bad.

Mga lakang:

  1. usa ka bag-ong pananglitan sa bersyon nga aplikasyon ang gipakatap 2.0.0.BADnga nag-update sa database sa v2bad
  2. sa database v2bad kolum last_name wala na - kini giusab ngadto sa surname
  3. Ang database ug pag-update sa aplikasyon nagmalampuson ug pipila ka mga higayon nagdagan 1.0.0, uban - sa 2.0.0.BAD. Ang tanan konektado sa database v2bad
  4. tanan nga mga higayon sa bersyon 1.0.0 magsugod sa paglabay sa mga sayop tungod kay sila mosulay sa pagsal-ot sa data ngadto sa kolum last_namenga wala na
  5. tanan nga mga higayon sa bersyon 2.0.0.BAD motrabaho nga walay problema

Sama sa imong makita, kung maghimo kami pabalik nga dili magkatugma nga mga pagbag-o sa database ug aplikasyon, imposible ang pagsulay sa A/B.

Pag-rollback sa aplikasyon

Ibutang nato nga human sa pagsulay sa pagbuhat sa A/B deployment (gibanabana. per .: ang tagsulat lagmit nagpasabot sa A/B testing dinhi) nakahukom kami nga kinahanglan namong i-roll balik ang aplikasyon sa bersyon 1.0.0. Ingnon ta nga dili nato gusto nga i-rollback ang database.

Mga lakang:

  1. gipahunong namo ang bersyon sa aplikasyon nga pananglitan 2.0.0.BAD
  2. database gihapon v2bad
  3. sukad sa bersyon 1.0.0 dili masabtan kung unsa kini surname, kita makakita og mga sayop
  4. nabungkag na ang impyerno, dili na ta makabalik

Sama sa imong makita, kung mohimo kami ug mga pagbag-o nga dili magkatugma sa database ug aplikasyon, dili kami makabalik sa miaging bersyon.

Mga log sa pagpatuman sa script

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

Mga pagbag-o sa database

Migration script nga nag-usab sa ngalan last_name в surname

Tinubdan nga Flyway script:

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

Script nga nag-usab sa ngalan last_name.

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

Mga pagbag-o sa code

Giusab namo ang ngalan sa field lastName sa surname.

Pag-ilis sa ngalan sa usa ka column sa backwards-compatible nga paagi

Mao ni ang kasagarang sitwasyon nga atong masugatan. Kinahanglan nga maghimo kita ug mga pagbag-o nga dili magkatugma. Napamatud-an na nato nga para sa zero-downtime deployment, dili lang nato i-apply ang database migration nga walay dugang nga mga lakang. Niini nga seksyon sa artikulo, maghimo kami og 3 nga pag-deploy sa aplikasyon kauban ang mga paglalin sa database aron makab-ot ang gitinguha nga resulta samtang gipadayon ang atrasado nga pagkaangay.

Ang nota. Hinumdomi nga kita adunay database sa bersyon v1. Kini adunay mga kolum first_name и last_name. Kinahanglan kitang magbag-o last_name sa surname. Adunay usab kami nga bersyon sa app 1.0.0, nga wala pa magamit surname.

Lakang 2: Idugang ang apelyido

Bersyon sa app: 2.0.0
Bersyon sa DB: v2

comment

Pinaagi sa pagdugang ug bag-ong kolum ug pagkopya sa mga sulod niini, naghimo kami ug mga pagbag-o sa database nga nahiuyon sa likod. Sa samang higayon, kung atong i-rollback ang JAR o adunay daan nga JAR nga nagdagan, dili kini mabuak sa panahon sa pagpatay.

Nagpagawas kami usa ka bag-ong bersyon

Mga lakang:

  1. paghimo og database migration aron makahimo og bag-ong column surname. Karon ang imong DB nga bersyon v2
  2. kopyaha ang datos gikan sa last_name в surname. Pagtagadnga kung daghan ka niini nga datos, kinahanglan nimong tagdon ang batch nga paglalin!
  3. isulat ang code diin sila gigamit DUHA и bag-oug ang daan kolum. Karon ang imong bersyon sa app 2.0.0
  4. basaha ang bili gikan sa kolum surname, kung dili null, o gikan sa last_namekung surname wala gipiho. Mahimo nimong tangtangon getLastName() gikan sa code, tungod kay kini magpagawas null kung gi-roll back ang imong aplikasyon gikan sa 3.0.0 sa 2.0.0.

Kung ikaw naggamit sa Spring Boot Flyway, kining duha ka mga lakang himuon sa panahon sa pagsugod sa bersyon 2.0.0 mga aplikasyon. Kung mano-mano ang imong pagpadagan sa tool sa pag-bersyon sa database, kinahanglan nimong buhaton ang duha ka lainlaing mga butang aron mahimo kini (una nga i-update ang bersyon sa db nga mano-mano ug dayon i-deploy ang bag-ong aplikasyon).

Hinungdanon kini. Hinumdomi nga ang bag-ong nahimo nga kolum DILI DAPAT nga mahimo DILI NALA. Kung maghimo ka ug rollback, ang daan nga aplikasyon wala mahibal-an bahin sa bag-ong kolum ug dili kini i-install sa panahon Insert. Apan kung imong idugang kini nga pagpugong ug ang imong db mahimong v2, magkinahanglan kini og pagtakda sa bili sa bag-ong kolum. Nga mosangpot sa mga paglapas sa mga pagdili.

Hinungdanon kini. Kinahanglan nimong tangtangon ang pamaagi getLastName(), tungod kay sa bersyon 3.0.0 Walay konsepto sa usa ka kolum sa code last_name. Kini nagpasabot nga ang null ibutang didto. Mahimo nimong biyaan ang pamaagi ug idugang ang mga tseke alang sa null, apan ang usa ka labi ka maayo nga solusyon mao ang pagsiguro nga sa lohika getSurname() gipili nimo ang husto nga dili zero nga kantidad.

Pagsulay sa A/B

Ang kasamtangan nga sitwasyon mao nga kita adunay usa ka bersyon sa aplikasyon 1.0.0, gipakatap sa produksiyon, ug ang database sa v1. Kinahanglan namon nga i-deploy ang ikaduha nga higayon sa aplikasyon sa bersyon 2.0.0nga mag-update sa database sa v2.

Mga lakang:

  1. usa ka bag-ong pananglitan sa bersyon nga aplikasyon ang gipakatap 2.0.0nga nag-update sa database sa v2
  2. sa kasamtangan ang pipila ka mga hangyo giproseso pinaagi sa bersyon nga mga higayon 1.0.0
  3. ang pag-update nagmalampuson ug ikaw adunay daghang mga higayon nga nagdagan sa bersyon nga aplikasyon 1.0.0 ug uban pang mga bersyon 2.0.0. Ang tanan nakigkomunikar sa database sa v2
  4. bersyon 1.0.0 wala mogamit sa kolum sa apelyido sa database, apan ang bersyon 2.0.0 mga gamit. Dili sila manghilabot sa usag usa, ug kinahanglan nga wala’y mga sayup.
  5. bersyon 2.0.0 nagtipig og datos sa daan ug bag-ong kolum, nga nagsiguro sa atraso nga pagkaangay

Hinungdanon kini. Kung adunay ka mga pangutana nga nag-ihap sa mga aytem base sa mga kantidad gikan sa daan/bag-o nga kolum, kinahanglan nimong hinumdoman nga ikaw karon adunay mga doble nga kantidad (lagmit nga sila naglalin pa). Pananglitan, kung gusto nimo ihap ang gidaghanon sa mga tiggamit kansang apelyido (bisan unsa ang tawag sa kolum) nagsugod sa sulat A, unya hangtod makompleto ang data migration (oldnew kolum) mahimo kang adunay dili managsama nga datos kung mangutana ka usa ka bag-ong kolum.

Pag-rollback sa aplikasyon

Karon kami adunay bersyon sa app 2.0.0 ug database sa v2.

Mga lakang:

  1. ibalik ang imong aplikasyon sa bersyon 1.0.0.
  2. bersyon 1.0.0 wala mogamit ug kolum sa database surname, mao nga ang rollback kinahanglan nga malampuson

Mga pagbag-o sa DB

Ang database adunay usa ka kolum nga ginganlan last_name.

script sa tinubdan sa 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');

Idugang ang script surname.

Pagtagad. Hinumdumi nga DILI ka makadugang bisan unsang NOT NULL nga mga pagpugong sa kolum nga imong gidugang. Kung imong i-rollback ang JAR, ang daan nga bersyon wala’y ideya bahin sa gidugang nga kolum ug awtomatiko nga ibutang kini sa NULL. Kung adunay ingon nga limitasyon, ang daan nga aplikasyon maguba ra.

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

Mga pagbag-o sa code

Gitipigan namon ang datos ingon last_name, ug sa surname. Sa samang higayon atong gibasa gikan sa last_name, tungod kay kini nga kolum mao ang labing may kalabutan. Atol sa proseso sa pag-deploy, ang pipila ka mga hangyo mahimong giproseso sa usa ka pananglitan sa aplikasyon nga wala pa ma-update.

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

Lakang 3: Pagtangtang sa last_name gikan sa code

Bersyon sa app: 3.0.0

Bersyon sa DB:v3

comment

Nota per.: Dayag, sa orihinal nga artikulo ang tagsulat nasayop nga gikopya ang teksto niini nga block gikan sa lakang 2. Niini nga lakang, ang mga pagbag-o kinahanglan nga himoon sa code sa aplikasyon nga nagtumong sa pagtangtang sa gamit nga naggamit sa kolum. last_name.

Pinaagi sa pagdugang ug bag-ong kolum ug pagkopya sa mga sulod niini, naghimo kami ug mga pagbag-o sa database nga nahiuyon sa likod. Usab, kung atong i-rollback ang JAR o adunay daan nga JAR nga nagdagan, dili kini mabuak sa panahon sa pagpatuman.

Pag-rollback sa aplikasyon

Karon kami adunay bersyon sa app 3.0.0 ug database v3. Bersyon 3.0.0 wala magtipig data sa last_name. Kini nagpasabot nga sa surname ang pinakabag-o nga impormasyon gitipigan.

Mga lakang:

  1. ibalik ang imong aplikasyon sa bersyon 2.0.0.
  2. bersyon 2.0.0 gamit ug last_name и surname.
  3. bersyon 2.0.0 kuhaon surname, kung dili zero, kung dili -last_name

Mga pagbag-o sa database

Wala’y mga pagbag-o sa istruktura sa database. Ang mosunud nga script gipatuman aron mahimo ang katapusang paglalin sa daan nga datos:

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

Mga pagbag-o sa code

Nota per .: Ang paghulagway niini nga block sayop usab nga gikopya sa tagsulat gikan sa lakang 2. Sumala sa lohika sa artikulo, ang mga pagbag-o sa code niini nga lakang kinahanglan nga gitumong sa pagtangtang gikan niini nga mga elemento nga nagtrabaho sa kolum. last_name.

Gitipigan namon ang datos ingon last_name, ug sa surname. Dugang pa, nagbasa kami gikan sa kolum last_name, tungod kay kini mao ang labing may kalabutan. Atol sa proseso sa pag-deploy, ang pipila ka mga hangyo mahimong maproseso sa usa ka higayon nga wala pa ma-upgrade.

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

Lakang 4: Pagtangtang sa last_name gikan sa database

Bersyon sa app: 4.0.0

Bersyon sa DB: v4

comment

Tungod sa kamatuoran nga ang bersyon code 3.0.0 wala gigamit ang kolum last_name, walay daotan nga mahitabo sa panahon sa pagpatay kon kita mobalik sa 3.0.0 human sa pagtangtang sa usa ka kolum gikan sa database.

Mga log sa pagpatuman sa script

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

Mga pagbag-o sa DB

Puwersado v3 tangtangon lang namo ang column last_name ug idugang ang nawala nga mga pagdili.

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

Mga pagbag-o sa code

Walay mga kausaban sa code.

konklusyon

Malampuson namo nga gi-apply ang usa ka backwards-incompatible nga pag-ilis sa ngalan sa column pinaagi sa paghimo og daghang backwards-compatible nga pagdeploy. Sa ubos mao ang usa ka summary sa mga aksyon nga gihimo:

  1. pag-deploy sa bersyon sa aplikasyon 1.0.0 с v1 database schema (ngalan sa kolum = last_name)
  2. pag-deploy sa bersyon sa aplikasyon 2.0.0, nga nagtipig sa datos sa last_name и surname. Ang aplikasyon mabasa gikan sa last_name. Ang database anaa sa bersyon v2nga adunay mga kolum sama sa last_name, ug surname. surname usa ka kopya sa last_name. (NOT: Kini nga kolum kinahanglan walay dili null nga pagpugong)
  3. pag-deploy sa bersyon sa aplikasyon 3.0.0, nga nagtipig lang sa datos sa surname ug mabasa gikan sa apelyido. Sama sa alang sa database, ang katapusan nga paglalin nahitabo last_name в surname. Usa usab ka limitasyon DILI NALA gikuha gikan sa last_name. Ang database anaa na sa bersyon v3
  4. pag-deploy sa bersyon sa aplikasyon 4.0.0 - walay mga kausaban nga gihimo sa code. Pag-deploy sa database v4, nga nagtangtang last_name. Dinhi mahimo nimong idugang ang bisan unsang nawala nga mga pagpugong sa database.

Pinaagi sa pagsunod niini nga pamaagi, mahimo nimo kanunay nga ibalik ang usa ka bersyon nga wala maguba ang pagkaangay sa database/aplikasyon.

code

Ang tanan nga code nga gigamit niini nga artikulo anaa sa Github. Sa ubos mao ang dugang nga paghulagway.

Mga Proyekto

Human sa pag-clone sa repository, imong makita ang mosunod nga istruktura sa folder.

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

Mga script

Mahimo nimong ipadagan ang mga script nga gihulagway sa mga script sa ubos, nga magpakita sa atrasado nga mga pagbag-o sa database.

Aron makita ang kaso nga adunay mga pagbag-o nga nahiuyon sa likod, dagan:

./scripts/scenario_backward_compatible.sh

Ug aron makita kaso nga adunay mga pagbag-o sa likod nga dili magkatugma, dagan:

./scripts/scenario_backward_incompatible.sh

Sample nga Flyway sa Spring Boot

Ang tanan nga mga pananglitan gikuha gikan sa Spring Boot Sample Flyway.

Mahimo nimong tan-awon ang http://localhost:8080/flyway, adunay listahan sa mga script.

Kini nga pananglitan naglakip usab sa H2 console (sa http://localhost:8080/h2-console) aron imong malantaw ang database status (default jdbc URL is jdbc:h2:mem:testdb).

dugang

Basaha usab ang ubang mga artikulo sa among blog:

Source: www.habr.com

Idugang sa usa ka comment