Zero Downtime Deployment සහ Databases

Zero Downtime Deployment සහ Databases

යෙදවීමේදී දත්ත සමුදා අනුකූලතා ගැටළු විසඳන්නේ කෙසේද යන්න මෙම ලිපියෙන් විස්තරාත්මකව විස්තර කෙරේ. ඔබ මූලික සූදානමකින් තොරව යෙදවීමට උත්සාහ කළහොත් ඔබේ නිෂ්පාදන යෙදුම්වලට කුමක් විය හැකිද යන්න අපි ඔබට කියන්නෙමු. අපි ඉන්පසුව ශුන්‍ය අක්‍රීය කාලය ඇති කිරීමට අවශ්‍ය යෙදුම් ජීවන චක්‍ර අදියර හරහා යන්නෙමු (ආසන්න වශයෙන් මංතීරුව: තවදුරටත් - බිංදු අක්‍රිය කාලය) අපගේ මෙහෙයුම් වල ප්‍රතිඵලය වනුයේ පසුපසට නොගැලපෙන දත්ත සමුදාය වෙනස් කිරීම පසුපසට ගැළපෙන ආකාරයෙන් යෙදීමයි.

ඔබට ලිපියෙන් කේත උදාහරණ තේරුම් ගැනීමට අවශ්‍ය නම්, ඔබට ඒවා සොයාගත හැකිය GitHub.

හැඳින්වීම

ශුන්‍ය අක්‍රීය කාල යෙදවීම

මොන ගුප්ත දෙයක්ද ශුන්‍ය අක්‍රීය කාල යෙදවීම? පරිශීලකයා එහි නොපවතින බව නොදකින අතරම, ඔබට යෙදුමේ නව අනුවාදයක් නිෂ්පාදනයට සාර්ථකව හඳුන්වා දිය හැකි ආකාරයෙන් ඔබේ යෙදුම යොදවා ඇති විට මෙය යැයි ඔබට පැවසිය හැකිය. පරිශීලක සහ සමාගම් දෘෂ්ටිකෝණයෙන්, මෙය නව විශේෂාංග හඳුන්වා දීමට සහ බාධාවකින් තොරව දෝෂ නිවැරදි කිරීමට ඉඩ සලසන නිසා හැකි හොඳම යෙදවීමේ අවස්ථාව මෙයයි.

මෙය සාක්ෂාත් කර ගන්නේ කෙසේද? ක්රම කිහිපයක් තිබේ, මෙන්න ඒවායින් එකක්:

  • ඔබගේ සේවාවේ අංක 1 අනුවාදය යෙදවීම
  • දත්ත සමුදා සංක්‍රමණයක් සිදු කරන්න
  • #2 අනුවාදයට සමාන්තරව ඔබේ සේවාවේ #1 අනුවාදය යොදන්න
  • අංක 2 අනුවාදය කළ යුතු ආකාරයට ක්‍රියා කරන බව ඔබ දුටු විගස, අංක 1 අනුවාදය ඉවත් කරන්න
  • ඉවරයි!

ලේසියි නේද? අවාසනාවකට, එය එතරම් සරල නැත, අපි එය පසුව විස්තරාත්මකව බලමු. දැන් අපි තවත් තරමක් පොදු යෙදවුම් ක්‍රියාවලියක් පරීක්ෂා කරමු - නිල් කොළ යෙදවීම.

ඔබ කවදා හෝ අසා තිබේද? නිල් කොළ යෙදවීම? Cloud Foundry මෙය ඉතා පහසු කරයි. නිකමට බලන්න මෙම ලිපිය, අපි මෙය වඩාත් විස්තරාත්මකව විස්තර කරන තැන. කෙටියෙන් සාරාංශ කිරීම සඳහා, නිල් කොළ යෙදවීම සිදු කරන්නේ කෙසේදැයි අපි ඔබට මතක් කරමු:

  • ඔබේ නිෂ්පාදන කේතයේ පිටපත් දෙකක් ("නිල්" සහ "කොළ") ක්‍රියා කරන බවට සහතික වන්න;
  • සියලුම ගමනාගමනය නිල් පරිසරයට යොමු කරන්න, i.e. නිෂ්පාදන URL එහි යොමු වන පරිදි;
  • හරිත පරිසරයක සියලුම යෙදුම් වෙනස්කම් යෙදවීම සහ පරීක්ෂා කිරීම;
  • url නිල් සිට හරිත පරිසරයට මාරු කරන්න

නිල් කොළ යෙදවීම යනු නිෂ්පාදන බිඳවැටීම ගැන කරදර නොවී නව විශේෂාංග පහසුවෙන් හඳුන්වා දීමට ඔබට ඉඩ සලසන ප්‍රවේශයකි. මෙයට හේතුව යම් දෙයක් සිදු වුවද, ඔබට “ස්විචයක් එබීමෙන්” පහසුවෙන් පෙර පරිසරයට ආපසු යා හැකි බැවිනි.

ඉහත සියල්ල කියවීමෙන් පසු, ඔබට ප්‍රශ්නය ඇසිය හැක: බිංදු අක්‍රිය කාලය නිල් කොළ යෙදවීම සමඟ ඇති සම්බන්ධය කුමක්ද?

හොඳයි, එකම පරිසරයක පිටපත් දෙකක් නඩත්තු කිරීම සඳහා ඒවා නඩත්තු කිරීමට දෙගුණයක් උත්සාහයක් අවශ්‍ය වන බැවින්, ඔවුන්ට බොහෝ පොදු දේ ඇත. මේ නිසා තමයි සමහර කණ්ඩායම් චෝදනා කරන්නේ මාටින් ෆෝලර්, මෙම ප්‍රවේශයේ වෙනසක් අනුගමනය කරන්න:

තවත් විකල්පයක් වන්නේ එකම දත්ත සමුදාය භාවිතා කිරීම, වෙබ් සහ වසම් ස්ථර සඳහා නිල්-කොළ ස්විචයන් නිර්මාණය කිරීමයි. මෙම ප්‍රවේශයේදී, දත්ත සමුදාය බොහෝ විට ගැටළුවක් විය හැක, විශේෂයෙන්ම මෘදුකාංගයේ නව අනුවාදයකට සහය දැක්වීම සඳහා එහි යෝජනා ක්‍රමය වෙනස් කිරීමට අවශ්‍ය වූ විට.

මෙන්න අපි මෙම ලිපියේ ප්රධාන ගැටළුව වෙත පැමිණෙමු. දත්ත සමුදාය. අපි මේ වැකිය තවත් බලමු.

දත්ත සමුදා සංක්‍රමණයක් සිදු කරන්න.

දැන් ඔබට ඔබෙන්ම ප්‍රශ්නය ඇසිය යුතුය - දත්ත සමුදාය වෙනස් කිරීම පසුපසට නොගැලපේ නම් කුමක් කළ යුතුද? යෙදුමේ මගේ පළමු අනුවාදය බිඳ වැටෙන්නේ නැද්ද? ඇත්ත වශයෙන්ම, මෙය හරියටම සිදුවනු ඇත ...

එබැවින්, ශුන්‍ය අක්‍රිය / නිල් කොළ යෙදවීමේ විශාල ප්‍රතිලාභ තිබියදීත්, සමාගම් ඔවුන්ගේ යෙදුම් යෙදවීම සඳහා පහත ආරක්ෂිත ක්‍රියාවලිය අනුගමනය කිරීමට නැඹුරු වේ:

  • යෙදුමේ නව අනුවාදයක් සමඟ පැකේජයක් සකස් කරන්න
  • ධාවනය වන යෙදුමක් වසා දමන්න
  • දත්ත සමුදාය සංක්‍රමණය කිරීමට ස්ක්‍රිප්ට් ධාවනය කරන්න
  • යෙදුමේ නව අනුවාදයක් යොදවා දියත් කරන්න

මෙම ලිපියෙන්, ශුන්‍ය අක්‍රීය කාලීන යෙදවීමේ වාසිය ලබා ගැනීම සඳහා ඔබට ඔබේ දත්ත සමුදාය සහ කේතය සමඟ වැඩ කළ හැකි ආකාරය අපි විස්තර කරන්නෙමු.

දත්ත සමුදා ගැටළු

ඔබ සතුව දත්ත ගබඩාවේ කිසිදු දත්තයක් ගබඩා නොකරන අස්ථායී යෙදුමක් තිබේ නම්, ඔබට වහාම ක්‍රියා විරහිත කාලීන යෙදවීම ශුන්‍ය කළ හැක. අවාසනාවකට, බොහෝ මෘදුකාංග වලට දත්ත ගබඩා කිරීමට අවශ්‍ය වේ. පරිපථයේ යම් වෙනසක් කිරීමට පෙර ඔබ දෙවරක් සිතා බැලිය යුත්තේ එබැවිනි. අපි ක්‍රමලේඛය වෙනස් කරන්නේ කෙසේද යන්න පිළිබඳ විස්තර ලබා ගැනීමට පෙර, අක්‍රීය කාල පරිහරණය කළ හැකි පරිදි, අපි පළමුව අනුවාද ක්‍රමය කෙරෙහි අවධානය යොමු කරමු.

අනුවාද යෝජනා ක්රමය

මෙම ලිපියෙන් අපි භාවිතා කරනු ඇත පියාසර මාර්ගය අනුවාද පාලන මෙවලමක් ලෙස (ආසන්න වශයෙන් පරිවර්තනය: අපි කතා කරන්නේ දත්ත සමුදා සංක්‍රමණය ගැන) ස්වාභාවිකවම, අපි Flyway සහාය ඇති අතර යෙදුම් සන්දර්භය සැකසීමේදී ක්‍රම සංක්‍රමණය සිදු කරන Spring Boot යෙදුමක් ද ලියන්නෙමු. Flyway භාවිතා කරන විට, ඔබට ඔබගේ ව්‍යාපෘති ෆෝල්ඩරයේ සංක්‍රමණ විධානාවලි ගබඩා කළ හැක (පෙරනිමියෙන් classpath:db/migration) මෙන්න ඔබට එවැනි සංක්‍රමණ ගොනු සඳහා උදාහරණයක් දැකිය හැකිය

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

මෙම උදාහරණයේදී අපට සංක්‍රමණ ස්ක්‍රිප්ට් 4ක් දක්නට ලැබේ, එය කලින් ක්‍රියාත්මක නොකළේ නම්, යෙදුම ආරම්භ වන විට එකින් එක ක්‍රියාත්මක වේ. අපි ගොනු වලින් එකක් බලමු (V1__init.sql) උදාහරණයක් ලෙස.

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

සෑම දෙයක්ම සම්පූර්ණයෙන්ම ස්වයං-පැහැදිලි වේ: ඔබේ දත්ත සමුදාය වෙනස් කළ යුතු ආකාරය නිර්වචනය කිරීමට ඔබට SQL භාවිතා කළ හැකිය. Spring Boot සහ Flyway පිළිබඳ වැඩි විස්තර සඳහා, පරීක්ෂා කරන්න Spring Boot Docs.

Spring Boot සමඟ මූලාශ්‍ර පාලන මෙවලමක් භාවිතා කිරීමෙන්, ඔබට විශාල ප්‍රතිලාභ 2ක් ලැබේ:

  • ඔබ කේත වෙනස් කිරීම් වලින් දත්ත සමුදා වෙනස්කම් වෙන් කරයි
  • දත්ත සමුදා සංක්‍රමණය සිදු වන්නේ ඔබගේ යෙදුම පෙරළීමත් සමඟය, i.e. ඔබගේ යෙදවීමේ ක්‍රියාවලිය සරල කර ඇත

දත්ත සමුදා ගැටළු දෝශ නිරාකරණය කිරීම

ලිපියේ ඊළඟ කොටසේදී, අපි දත්ත සමුදා වෙනස්කම් සඳහා ප්රවේශයන් දෙකක් දෙස අවධානය යොමු කරමු.

  • පසුගාමී නොගැලපීම
  • පසුගාමී ගැළපුම

පළමු එක ඔබ මූලික සූදානමකින් තොරව ශුන්‍ය අක්‍රීය කාල යෙදවීම සිදු නොකළ යුතු බවට අනතුරු ඇඟවීමක් ලෙස සලකනු ලැබේ... දෙවැන්න ඔබට අක්‍රීය කාලයකින් තොරව යෙදවීමක් සිදු කරන්නේ කෙසේද සහ ඒ සමඟම පසුගාමී අනුකූලතාවක් පවත්වා ගන්නේ කෙසේද යන්න පිළිබඳ විසඳුමක් ඉදිරිපත් කරයි.

අපි වැඩ කරන අපගේ ව්‍යාපෘතිය සරල Spring Boot Flyway යෙදුමක් වනු ඇත Person с first_name и last_name දත්ත ගබඩාවේ (ආසන්න වශයෙන් පරිවර්තනය: Person මේසයක් සහ first_name и last_name - මේ එහි ඇති ක්ෂේත්‍ර) අපට නැවත නම් කිරීමට අවශ්‍යයි last_name в surname.

උපකල්පන

අපි විස්තර ලබා ගැනීමට පෙර, අපගේ යෙදුම් පිළිබඳව අපට කළ යුතු උපකල්පන කිහිපයක් තිබේ. අපට සාක්ෂාත් කර ගැනීමට අවශ්‍ය ප්‍රධාන ප්‍රති result ලය තරමක් සරල ක්‍රියාවලියක් වනු ඇත.

සටහන. ව්යාපාර PRO-TIP. ක්‍රියාවලීන් සරල කිරීම මඟින් ඔබට ආධාර මත විශාල මුදලක් ඉතිරි කර ගත හැකිය (ඔබේ සමාගම සඳහා ඔබ වැඩ කරන පුද්ගලයින් වැඩි වන තරමට ඔබට ඉතිරි කළ හැකි මුදල් වැඩි වේ)!

දත්ත සමුදාය ආපසු හැරවීමට අවශ්ය නොවේ

මෙය යෙදවීමේ ක්‍රියාවලිය සරල කරයි (සමහර දත්ත සමුදාය ආපසු හැරවීම මකාදැමීම වැනි ආපසු හැරවීම පාහේ කළ නොහැක්කකි). අපි යෙදුම් පමණක් ආපසු පෙරළීමට කැමැත්තෙමු. මේ ආකාරයට, ඔබට විවිධ දත්ත සමුදායන් (උදාහරණයක් ලෙස, SQL සහ NoSQL) තිබුණද, ඔබේ යෙදවීමේ නල මාර්ගය එකම ලෙස පෙනෙනු ඇත.

යෙදුම එක් අනුවාදයකින් ආපසු පෙරළීමට සැමවිටම හැකි විය යුතුය (තවත් නැත)

ආපසු හැරවීම සිදු කළ යුත්තේ අවශ්ය විට පමණි. වත්මන් අනුවාදයේ පහසුවෙන් විසඳිය නොහැකි දෝෂයක් තිබේ නම්, අපට නවතම ක්‍රියාකාරී අනුවාදය වෙත ආපසු යාමට හැකි විය යුතුය. මෙම නවතම ක්‍රියාකාරී අනුවාදය පෙර එක යැයි අපි උපකල්පනය කරමු. එකකට වඩා වැඩි ගණනක් සඳහා කේත සහ දත්ත සමුදා අනුකූලතාව පවත්වා ගැනීම අතිශය දුෂ්කර සහ මිල අධික වනු ඇත.

සටහන. වැඩි කියවීමේ හැකියාව සඳහා, මෙම ලිපියෙන් අපි යෙදුමේ ප්රධාන අනුවාදය වෙනස් කරන්නෙමු.

පියවර 1: ආරම්භක තත්වය

යෙදුම් අනුවාදය: 1.0.0
DB අනුවාදය: v1

අදහස්

මෙය යෙදුමේ ආරම්භක තත්වය වනු ඇත.

දත්ත සමුදායේ වෙනස්කම්

DB අඩංගු වේ 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');

කේතය වෙනස් වේ

යෙදුම පුද්ගල දත්ත ගබඩා කරයි 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
                + "]";
    }
}

පසුපසට නොගැලපෙන තීරු නැවත නම් කිරීම

තීරු නාමයක් වෙනස් කරන්නේ කෙසේද යන්න පිළිබඳ උදාහරණයක් බලමු:

අවධානය. පහත උදාහරණය හිතාමතාම දේවල් බිඳ දමනු ඇත. අපි මෙය පෙන්වන්නේ දත්ත සමුදාය අනුකූලතාවයේ ගැටලුව ප්‍රදර්ශනය කිරීමටයි.

යෙදුම් අනුවාදය: 2.0.0.BAD

DB අනුවාදය: v2bad

අදහස්

වත්මන් වෙනස්කම් අපට එකවර අවස්ථා දෙකක් (පරණ සහ නව) ධාවනය කිරීමට ඉඩ නොදේ. මේ අනුව, ශුන්‍ය අක්‍රීය කාල යෙදවීම සාක්ෂාත් කර ගැනීම දුෂ්කර වනු ඇත (උපකල්පනයන් සැලකිල්ලට ගන්නේ නම්, එය ඇත්ත වශයෙන්ම කළ නොහැක්කකි).

A/B පරීක්ෂණය

වර්තමාන තත්ත්වය නම් අප සතුව යෙදුම් අනුවාදයක් තිබීමයි 1.0.0, නිෂ්පාදනය, සහ දත්ත ගබඩාවේ යොදවා ඇත v1. අපි යෙදුමේ දෙවන උදාහරණය, ​​අනුවාදය යෙදවිය යුතුය 2.0.0.BAD, සහ දත්ත සමුදාය යාවත්කාලීන කරන්න v2bad.

පියවර:

  1. අනුවාද යෙදුමේ නව අවස්ථාවක් යොදවා ඇත 2.0.0.BADදත්ත සමුදාය යාවත්කාලීන කරන v2bad
  2. දත්ත සමුදායේ v2bad තීරුව last_name තවදුරටත් නොපවතියි - එය වෙනස් කරන ලදී surname
  3. දත්ත සමුදාය සහ යෙදුම් යාවත්කාලීන කිරීම සාර්ථක වූ අතර සමහර අවස්ථා ක්‍රියාත්මක වේ 1.0.0, වෙනත් - තුළ 2.0.0.BAD. සෑම දෙයක්ම දත්ත සමුදායට සම්බන්ධ වේ v2bad
  4. අනුවාදයේ සියලුම අවස්ථා 1.0.0 ඔවුන් තීරුවට දත්ත ඇතුළු කිරීමට උත්සාහ කරන නිසා දෝෂ විසි කිරීමට පටන් ගනී last_nameතවදුරටත් නොපවතින
  5. අනුවාදයේ සියලුම අවස්ථා 2.0.0.BAD ගැටළු නොමැතිව වැඩ කරනු ඇත

ඔබට පෙනෙන පරිදි, අපි දත්ත සමුදාය සහ යෙදුම වෙත ආපසු නොගැලපෙන වෙනස්කම් සිදු කරන්නේ නම්, A/B පරීක්ෂා කිරීම කළ නොහැක.

අයදුම්පත ආපසු හැරවීම

අපි හිතමු A/B deployment කරන්න හැදුවට පස්සේ (ආසන්න වශයෙන් per.: කතුවරයා මෙහි A/B පරීක්‍ෂණය අදහස් කරන්න ඇති) අපි යෙදුම අනුවාදයට පෙරළීමට අවශ්‍ය බව තීරණය කළෙමු 1.0.0. අපි හිතමු අපිට database එක rollback කරන්න ඕන නෑ කියලා.

පියවර:

  1. අපි අනුවාද යෙදුම් අවස්ථාව නවත්වන්නෙමු 2.0.0.BAD
  2. දත්ත සමුදාය තවමත් පවතී v2bad
  3. අනුවාදයේ සිට 1.0.0 එය කුමක්දැයි තේරෙන්නේ නැත surname, අපි වැරදි දකිනු ඇත
  4. නිරය ලිහිල් වී ඇත, අපට තවදුරටත් ආපසු යා නොහැක

ඔබට පෙනෙන පරිදි, අපි දත්ත සමුදාය සහ යෙදුම වෙත ආපසු නොගැලපෙන වෙනස්කම් සිදු කරන්නේ නම්, අපට පෙර අනුවාදයට ආපසු යා නොහැක.

ස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ ලඝු-සටහන්

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

දත්ත සමුදායේ වෙනස්කම්

නැවත නම් කරන සංක්‍රමණ පිටපත last_name в surname

මූලාශ්‍ර ෆ්ලයිවේ ස්ක්‍රිප්ට්:

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

නැවත නම් කරන පිටපත last_name.

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

කේතය වෙනස් වේ

අපි ක්ෂේත්‍ර නාමය වෙනස් කර ඇත lastName මත surname.

පසුපසට ගැළපෙන ආකාරයෙන් තීරුව නැවත නම් කිරීම

මෙය අපට මුහුණ දිය හැකි වඩාත් පොදු තත්වයයි. අපි පසුපසට නොගැලපෙන වෙනස්කම් කළ යුතුයි. ශුන්‍ය අක්‍රීය කාල යෙදවීම සඳහා, අතිරේක පියවරකින් තොරව දත්ත සමුදා සංක්‍රමණය යෙදිය යුතු නැති බව අපි දැනටමත් ඔප්පු කර ඇත්තෙමු. ලිපියේ මෙම කොටසෙහි, අපි පසුගාමී අනුකූලතාව පවත්වා ගනිමින් අපේක්ෂිත ප්රතිඵලය ලබා ගැනීම සඳහා දත්ත සමුදා සංක්රමණයන් සමඟ යෙදුමේ යෙදවීම් 3 ක් සිදු කරන්නෙමු.

සටහන. අපට අනුවාද දත්ත ගබඩාවක් ඇති බව මතක තබා ගන්න v1. එහි තීරු අඩංගු වේ first_name и last_name. අපි වෙනස් විය යුතුයි last_name මත surname. අපට යෙදුම් අනුවාදයද ඇත 1.0.0, තවමත් භාවිතා නොකරන surname.

පියවර 2: වාසගම එකතු කරන්න

යෙදුම් අනුවාදය: 2.0.0
DB අනුවාදය: v2

අදහස්

නව තීරුවක් එකතු කිරීමෙන් සහ එහි අන්තර්ගතය පිටපත් කිරීමෙන්, අපි පසුපසට ගැළපෙන දත්ත සමුදා වෙනස්කම් සාදන්නෙමු. ඒ සමඟම, අපි JAR ආපසු හැරවීම හෝ පැරණි JAR ධාවනය කර ඇත්නම්, එය ක්‍රියාත්මක කිරීමේදී කැඩී නොයනු ඇත.

අපි නව අනුවාදයක් නිකුත් කරන්නෙමු

පියවර:

  1. නව තීරුවක් සෑදීමට දත්ත සමුදා සංක්‍රමණයක් සිදු කරන්න surname. දැන් ඔබේ DB අනුවාදය v2
  2. දත්ත පිටපත් කරන්න last_name в surname. අවධානය යොමු කරන්නඔබට මෙම දත්ත බොහොමයක් තිබේ නම්, ඔබ කණ්ඩායම් සංක්‍රමණය සලකා බැලිය යුතුය!
  3. ඒවා භාවිතා කරන කේතය ලියන්න දෙකම и новыйහා පැරණි තීරුව. දැන් ඔබගේ යෙදුම් අනුවාදය 2.0.0
  4. තීරුවෙන් අගය කියවන්න surname, එය එසේ නොවේ නම් null, හෝ එල් සිටast_name, නම් surname විශේෂයෙන් දක්වා නැති. ඔබට මකා දැමිය හැකිය getLastName() කේතයෙන්, එය ප්රතිදානය කරනු ඇත null ඔබගේ අයදුම්පත ආපසු හරවන විට 3.0.0 කිරීමට 2.0.0.

ඔබ Spring Boot Flyway භාවිතා කරන්නේ නම්, මෙම පියවර දෙක අනුවාද ආරම්භයේදී සිදු කෙරේ 2.0.0 අයදුම්පත්. ඔබ දත්ත සමුදා අනුවාද මෙවලම අතින් ක්‍රියාත්මක කරන්නේ නම්, මෙය සිදු කිරීම සඳහා ඔබට වෙනස් දේවල් දෙකක් කිරීමට සිදුවේ (පළමුව db අනුවාදය අතින් යාවත්කාලීන කර පසුව නව යෙදුම යොදවන්න).

එය වැදගත් වේ. අලුතින් සාදන ලද තීරුව බව මතක තබා ගන්න නොකළ යුතුය ඔව් NULL නොවේ. ඔබ ආපසු හැරීමක් කරන්නේ නම්, පැරණි යෙදුම නව තීරුව ගැන නොදන්නා අතර එය අතරතුර එය ස්ථාපනය නොකරයි Insert. නමුත් ඔබ මෙම සීමාව එකතු කළහොත් ඔබේ db වනු ඇත v2, මේ සඳහා නව තීරුවේ අගය සැකසීමට අවශ්‍ය වනු ඇත. එය සීමාවන් උල්ලංඝනය කිරීමට තුඩු දෙනු ඇත.

එය වැදගත් වේ. ඔබ ක්රමය ඉවත් කළ යුතුය getLastName(), අනුවාදයේ නිසා 3.0.0 කේතයේ තීරු සංකල්පයක් නොමැත last_name. ඒ කියන්නේ එතන null එක සෙට් වෙනවා. ඔබට ක්‍රමය අතහැර චෙක්පත් එකතු කළ හැක null, නමුත් වඩා හොඳ විසඳුමක් වනුයේ තර්කයේ ඇති බව තහවුරු කර ගැනීමයි getSurname() ඔබ නිවැරදි ශුන්‍ය නොවන අගය තෝරා ඇත.

A/B පරීක්ෂණය

වර්තමාන තත්ත්වය නම් අප සතුව යෙදුම් අනුවාදයක් තිබීමයි 1.0.0, නිෂ්පාදනය මත යොදවා ඇත, සහ දත්ත සමුදාය තුළ v1. අපට අනුවාද යෙදුමේ දෙවන අවස්ථාවක් යෙදවීමට අවශ්‍යයි 2.0.0දත්ත සමුදාය යාවත්කාලීන කරනු ඇත v2.

පියවර:

  1. අනුවාද යෙදුමේ නව අවස්ථාවක් යොදවා ඇත 2.0.0දත්ත සමුදාය යාවත්කාලීන කරන v2
  2. මේ අතර සමහර ඉල්ලීම් අනුවාද අවස්ථා මගින් සකසන ලදී 1.0.0
  3. යාවත්කාලීන කිරීම සාර්ථක වූ අතර ඔබට අනුවාද යෙදුමේ ධාවන අවස්ථා කිහිපයක් තිබේ 1.0.0 සහ වෙනත් අනුවාද 2.0.0. සෑම කෙනෙකුම දත්ත සමුදාය සමඟ සන්නිවේදනය කරයි v2
  4. අනුවාදය 1.0.0 දත්ත ගබඩාවේ වාසගම තීරුව භාවිතා නොකරයි, නමුත් අනුවාදය 2.0.0 භාවිතා කරයි. ඔවුන් එකිනෙකාට බාධා නොකරන අතර, කිසිදු දෝෂයක් නොතිබිය යුතුය.
  5. අනුවාදය 2.0.0 පසුගාමී අනුකූලතාව සහතික කරමින් පැරණි සහ නව තීරු දෙකෙහිම දත්ත ගබඩා කරයි

එය වැදගත් වේ. ඔබට පැරණි/නව තීරුවේ ඇති අගයන් මත පදනම්ව අයිතම ගණන් කරන කිසියම් විමසුම් තිබේ නම්, ඔබට දැන් අනුපිටපත් අගයන් ඇති බව මතක තබා ගත යුතුය (බොහෝ විට ඒවා තවමත් සංක්‍රමණය වෙමින් පවතී). උදාහරණයක් ලෙස, ඔබට ලිපියෙන් ආරම්භ වූ අවසාන නම (තීරුව කුමක් වුවත්) භාවිතා කරන්නන් ගණන ගණන් කිරීමට අවශ්‍ය නම් A, පසුව දත්ත සංක්‍රමණය අවසන් වන තුරු (oldnew තීරුව) ඔබ නව තීරුවක් විමසන්නේ නම් ඔබට නොගැලපෙන දත්ත තිබිය හැක.

අයදුම්පත ආපසු හැරවීම

දැන් අපිට app version එක තියෙනවා 2.0.0 සහ දත්ත සමුදාය තුළ v2.

පියවර:

  1. ඔබගේ යෙදුම අනුවාදයට පෙරළන්න 1.0.0.
  2. අනුවාදය 1.0.0 දත්ත ගබඩාවේ තීරුවක් භාවිතා නොකරයි surname, එබැවින් ආපසු හැරීම සාර්ථක විය යුතුය

DB වෙනස් වේ

දත්ත සමුදායේ නම් තීරුවක් අඩංගු වේ last_name.

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

පිටපත එකතු කරන්න surname.

අවධානය. ඔබ එකතු කරන තීරුවට කිසිදු NOT NULL සීමාවක් එක් කළ නොහැකි බව මතක තබා ගන්න. ඔබ JAR ආපසු හරවන්නේ නම්, පැරණි අනුවාදයට එකතු කළ තීරුව පිළිබඳ අදහසක් නොමැති අතර එය ස්වයංක්‍රීයව NULL ලෙස සකසනු ඇත. එවැනි සීමාවක් තිබේ නම්, පැරණි යෙදුම සරලව කැඩී යයි.

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

කේතය වෙනස් වේ

අපි දත්ත ගබඩා කරන්නේ last_name, සහ surname. ඒ සමගම අපි කියවමු 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;
    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
                + "]";
    }
}

පියවර 3: කේතයෙන් අවසාන_නම ඉවත් කිරීම

යෙදුම් අනුවාදය: 3.0.0

DB අනුවාදය:v3

අදහස්

සටහන per.: පෙනෙන විදිහට, මුල් ලිපියේ කර්තෘ වැරදි ලෙස 2 පියවරෙන් මෙම කොටසේ පෙළ පිටපත් කර ඇත. මෙම පියවරේදී, තීරුව භාවිතා කරන ක්‍රියාකාරීත්වය ඉවත් කිරීම අරමුණු කරගත් යෙදුම් කේතයේ වෙනස්කම් සිදු කළ යුතුය. last_name.

නව තීරුවක් එකතු කිරීමෙන් සහ එහි අන්තර්ගතය පිටපත් කිරීමෙන්, අපි පසුපසට ගැළපෙන දත්ත සමුදා වෙනස්කම් නිර්මාණය කළෙමු. එසේම, අපි JAR ආපසු හැරවීම හෝ පැරණි JAR ක්‍රියාත්මක වේ නම්, එය ක්‍රියාත්මක කිරීමේදී කැඩී නොයනු ඇත.

අයදුම්පත ආපසු හැරවීම

දැනට අපට යෙදුම් අනුවාදය ඇත 3.0.0 සහ දත්ත සමුදාය v3. පිටපත 3.0.0 වෙත දත්ත සුරැකෙන්නේ නැත last_name. මෙයින් අදහස් කරන්නේ තුළ surname වඩාත්ම යාවත්කාලීන තොරතුරු ගබඩා කර ඇත.

පියවර:

  1. ඔබගේ යෙදුම අනුවාදයට පෙරළන්න 2.0.0.
  2. අනුවාදය 2.0.0 භාවිතා කරයි සහ last_name и surname.
  3. අනුවාදය 2.0.0 ගන්නම් surname, එය ශුන්‍ය නොවේ නම්, එසේ නොමැති නම් -last_name

දත්ත සමුදායේ වෙනස්කම්

දත්ත ගබඩාවේ ව්‍යුහාත්මක වෙනස්කම් නොමැත. පැරණි දත්තවල අවසාන සංක්‍රමණය සිදු කිරීම සඳහා පහත ස්ක්‍රිප්ට් ක්‍රියාත්මක වේ:

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

කේතය වෙනස් වේ

සටහන per.: මෙම කොටසෙහි විස්තරය ද කර්තෘ විසින් 2 පියවරෙන් වැරදි ලෙස පිටපත් කර ඇත. ලිපියේ තර්කයට අනුකූලව, මෙම පියවරේදී කේතයේ වෙනස්කම් තීරුව සමඟ ක්‍රියා කරන අංග එයින් ඉවත් කිරීම අරමුණු කර ගත යුතුය. last_name.

අපි දත්ත ගබඩා කරන්නේ last_name, සහ surname. අතිරේකව, අපි තීරුවෙන් කියවමු 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 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
                + "]";
    }
}

පියවර 4: දත්ත සමුදායෙන් අවසන්_නම ඉවත් කිරීම

යෙදුම් අනුවාදය: 4.0.0

DB අනුවාදය: v4

අදහස්

අනුවාද කේතය යන කාරනය නිසා 3.0.0 තීරුව භාවිතා කළේ නැත last_name, අපි ආපසු පෙරළුවහොත් ක්‍රියාත්මක කිරීමේදී නරක කිසිවක් සිදු නොවනු ඇත 3.0.0 දත්ත සමුදායෙන් තීරුවක් ඉවත් කිරීමෙන් පසුව.

ස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ ලඝු-සටහන්

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 වෙනස් වේ

සාපේක්ෂව v3 අපි තීරුව ඉවත් කරමු last_name සහ නැතිවූ සීමා එකතු කරන්න.

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

කේතය වෙනස් වේ

කේතයේ වෙනස්කම් නොමැත.

නිගමනය

පසුපසට ගැළපෙන යෙදවීම් කිහිපයක් සිදු කිරීමෙන් අපි පසුපසට නොගැළපෙන තීරු නම වෙනස් කිරීමක් සාර්ථකව යෙදුවෙමු. සිදු කරන ලද ක්‍රියාවන්හි සාරාංශයක් පහත දැක්වේ:

  1. යෙදුම් අනුවාදය යෙදවීම 1.0.0 с v1 දත්ත සමුදා සැලැස්ම (තීරු නම = last_name)
  2. යෙදුම් අනුවාදය යෙදවීම 2.0.0, දත්ත ගබඩා කරන last_name и surname. යෙදුම කියවන්නේ last_name. දත්ත සමුදාය අනුවාදයේ ඇත v2වැනි තීරු අඩංගු වේ last_name, සහ surname. surname l හි පිටපතකිast_name. (සටහන: මෙම තීරුවේ ශුන්‍ය නොවන සීමාවක් නොතිබිය යුතුය)
  3. යෙදුම් අනුවාදය යෙදවීම 3.0.0, තුළ පමණක් දත්ත ගබඩා කරයි surname සහ වාසගමෙන් කියවයි. දත්ත සමුදාය සම්බන්ධයෙන් ගත් කල, අවසාන සංක්‍රමණය සිදුවෙමින් පවතී last_name в surname. එසේම සීමාවකි NULL නොවේ වෙතින් ඉවත් කර ඇත last_name. දත්ත සමුදාය දැන් අනුවාදයේ ඇත v3
  4. යෙදුම් අනුවාදය යෙදවීම 4.0.0 - කේතයේ කිසිදු වෙනසක් සිදු නොකෙරේ. දත්ත සමුදාය යෙදවීම v4, ඉවත් කරන last_name. මෙහිදී ඔබට දත්ත සමුදාය වෙත අතුරුදහන් වූ සීමාවන් එක් කළ හැක.

මෙම ප්‍රවේශය අනුගමනය කිරීමෙන්, ඔබට සෑම විටම දත්ත සමුදාය/යෙදුම් ගැළපුම බිඳ දැමීමකින් තොරව එක් අනුවාදයක් ආපසු හැරවිය හැක.

කේතය

මෙම ලිපියේ භාවිතා කර ඇති සියලුම කේත මෙහි ඇත Github. පහත දැක්වෙන්නේ අමතර විස්තරයකි.

ව්යාපෘති

ගබඩාව ක්ලෝන කිරීමෙන් පසු, ඔබට පහත ෆෝල්ඩර ව්‍යුහය පෙනෙනු ඇත.

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

ස්ක්‍රිප්ට්

ඔබට පහත ස්ක්‍රිප්ට් වල විස්තර කර ඇති ස්ක්‍රිප්ට් ධාවනය කළ හැක, එමඟින් දත්ත සමුදායට පසුගාමී-ගැළපෙන සහ නොගැලපෙන වෙනස්කම් පෙන්වනු ඇත.

බලන්න පසුපසට ගැළපෙන වෙනස්කම් සහිත නඩුව, ධාවනය:

./scripts/scenario_backward_compatible.sh

සහ දැකීමට පසුපසට නොගැලපෙන වෙනස්කම් සහිත නඩුව, ධාවනය:

./scripts/scenario_backward_incompatible.sh

Spring Boot Sample Flyway

සියලුම උදාහරණ උපුටා ගන්නා ලදී Spring Boot Sample Flyway.

ඔබට බලන්න පුළුවන් http://localhost:8080/flyway, ස්ක්‍රිප්ට් ලැයිස්තුවක් ඇත.

මෙම උදාහරණයට H2 කොන්සෝලය ද ඇතුළත් වේ (at http://localhost:8080/h2-console) එබැවින් ඔබට දත්ත සමුදා තත්ත්වය නැරඹිය හැකිය (පෙරනිමි jdbc URL වේ jdbc:h2:mem:testdb).

මීට අමතරව

අපගේ බ්ලොග් අඩවියේ වෙනත් ලිපිද කියවන්න:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න