가동 쀑지 μ‹œκ°„μ΄ μ—†λŠ” 배포 및 λ°μ΄ν„°λ² μ΄μŠ€

가동 쀑지 μ‹œκ°„μ΄ μ—†λŠ” 배포 및 λ°μ΄ν„°λ² μ΄μŠ€

이 λ¬Έμ„œμ—μ„œλŠ” 배포 μ‹œ λ°μ΄ν„°λ² μ΄μŠ€ ν˜Έν™˜μ„± 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법을 μžμ„Ένžˆ μ„€λͺ…ν•©λ‹ˆλ‹€. 사전 μ€€λΉ„ 없이 λ°°ν¬ν•˜λ €κ³  ν•˜λ©΄ ν”„λ‘œλ•μ…˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ–΄λ–€ 일이 λ°œμƒν•  수 μžˆλŠ”μ§€ μ•Œλ €λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ 가동 쀑지 μ‹œκ°„μ΄ μ—†μ–΄μ•Ό ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 수λͺ… μ£ΌκΈ° 단계λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€(λŒ€λž΅. μ°¨μ„ : μΆ”κ°€ - 가동 쀑지 μ‹œκ°„ μ—†μŒ). 우리 μž‘μ—…μ˜ κ²°κ³ΌλŠ” 이전 버전과 ν˜Έν™˜λ˜μ§€ μ•ŠλŠ” λ°μ΄ν„°λ² μ΄μŠ€ λ³€κ²½ 사항을 이전 버전과 ν˜Έν™˜λ˜λŠ” λ°©μ‹μœΌλ‘œ μ μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

κΈ°μ‚¬μ˜ μ½”λ“œ 예제λ₯Ό μ΄ν•΄ν•˜λ €λ©΄ λ‹€μŒμ—μ„œ 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. GitHub의.

μ†Œκ°œ

λ‹€μš΄νƒ€μž„ μ—†λŠ” 배포

정말 μ‹ λΉ„λ‘œμš΄λ°μš”? λ‹€μš΄νƒ€μž„ μ—†λŠ” 배포? μ΄λŠ” μ‚¬μš©μžκ°€ μ‚¬μš©ν•  수 μ—†μŒμ„ μΈμ‹ν•˜μ§€ λͺ»ν•˜λŠ” λ™μ•ˆ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μƒˆ 버전을 ν”„λ‘œλ•μ…˜μ— μ„±κ³΅μ μœΌλ‘œ λ„μž…ν•  수 μžˆλŠ” λ°©μ‹μœΌλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ°°ν¬λ˜λŠ” λ•ŒλΌκ³  말할 수 μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©μž 및 νšŒμ‚¬ κ΄€μ μ—μ„œ λ³Ό λ•Œ μ΄λŠ” 쀑단 없이 μƒˆλ‘œμš΄ κΈ°λŠ₯을 λ„μž…ν•˜κ³  버그λ₯Ό μˆ˜μ •ν•  수 있기 λ•Œλ¬Έμ— κ°€λŠ₯ν•œ μ΅œμƒμ˜ 배포 μ‹œλ‚˜λ¦¬μ˜€μž…λ‹ˆλ‹€.

이것을 λ‹¬μ„±ν•˜λŠ” 방법은 λ¬΄μ—‡μž…λ‹ˆκΉŒ? μ—¬λŸ¬ κ°€μ§€ 방법이 μžˆλŠ”λ°, κ·Έ 쀑 ν•˜λ‚˜λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • μ„œλΉ„μŠ€ 버전 1을 λ°°ν¬ν•˜μ„Έμš”.
  • λ°μ΄ν„°λ² μ΄μŠ€ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ μˆ˜ν–‰
  • 버전 2κ³Ό λ³‘λ ¬λ‘œ μ„œλΉ„μŠ€ 버전 1λ₯Ό λ°°ν¬ν•©λ‹ˆλ‹€.
  • 버전 2κ°€ μ •μƒμ μœΌλ‘œ μž‘λ™ν•˜λŠ” 것을 ν™•μΈν•˜μžλ§ˆμž 버전 1을 μ œκ±°ν•˜μ‹­μ‹œμ˜€.
  • λλ‚œ!

μ‰½μ§€μš”? λΆˆν–‰ν•˜κ²Œλ„ μ΄λŠ” κ·Έλ ‡κ²Œ κ°„λ‹¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이에 λŒ€ν•΄μ„œλŠ” λ‚˜μ€‘μ— μžμ„Ένžˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 이제 또 λ‹€λ₯Έ 일반적인 배포 ν”„λ‘œμ„ΈμŠ€μΈ νŒŒλž€μƒ‰ 녹색 배포λ₯Ό 확인해 λ³΄κ² μŠ΅λ‹ˆλ‹€.

λ“€μ–΄λ³Έ 적이 μžˆλ‚˜μš”? 블루 κ·Έλ¦° 배포? Cloud Foundryλ₯Ό μ‚¬μš©ν•˜λ©΄ 이λ₯Ό 맀우 μ‰½κ²Œ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλƒ₯ 봐 이 λ¬Έμ„œ, μ—¬κΈ°μ„œ 이에 λŒ€ν•΄ 더 μžμ„Ένžˆ μ„€λͺ…ν•©λ‹ˆλ‹€. κ°„λž΅ν•˜κ²Œ μš”μ•½ν•˜μžλ©΄, 블루 κ·Έλ¦° 배포λ₯Ό μˆ˜ν–‰ν•˜λŠ” 방법을 μƒκΈ°μ‹œμΌœ λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

  • ν”„λ‘œλ•μ…˜ μ½”λ“œ 사본 XNUMX개("νŒŒλž€μƒ‰" 및 "녹색")κ°€ μž‘λ™ν•˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
  • λͺ¨λ“  νŠΈλž˜ν”½μ„ 블루 ν™˜κ²½μœΌλ‘œ λ³΄λƒ…λ‹ˆλ‹€. 즉, ν”„λ‘œλ•μ…˜ 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와 ν•¨κ»˜ μ†ŒμŠ€ μ œμ–΄ 도ꡬλ₯Ό μ‚¬μš©ν•˜λ©΄ 두 κ°€μ§€ 큰 이점을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

  • λ°μ΄ν„°λ² μ΄μŠ€ λ³€κ²½ 사항과 μ½”λ“œ λ³€κ²½ 사항을 λΆ„λ¦¬ν•©λ‹ˆλ‹€.
  • λ°μ΄ν„°λ² μ΄μŠ€ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μΆœμ‹œμ™€ ν•¨κ»˜ λ°œμƒν•©λ‹ˆλ‹€. 배포 ν”„λ‘œμ„ΈμŠ€κ°€ λ‹¨μˆœν™”λ©λ‹ˆλ‹€.

λ°μ΄ν„°λ² μ΄μŠ€ 문제 ν•΄κ²°

κΈ°μ‚¬μ˜ λ‹€μŒ μ„Ήμ…˜μ—μ„œλŠ” λ°μ΄ν„°λ² μ΄μŠ€ 변경에 λŒ€ν•œ 두 κ°€μ§€ μ ‘κ·Ό 방식을 μ‚΄νŽ΄λ³΄λŠ” 데 쀑점을 λ‘˜ κ²ƒμž…λ‹ˆλ‹€.

  • 이전 λ²„μ „κ³Όμ˜ λΉ„ν˜Έν™˜μ„±
  • ν•˜μœ„ ν˜Έν™˜μ„±

첫 λ²ˆμ§ΈλŠ” 사전 μ€€λΉ„ 없이 제둜 λ‹€μš΄νƒ€μž„ 배포λ₯Ό μˆ˜ν–‰ν•˜λ©΄ μ•ˆ λœλ‹€λŠ” 경고둜 κ°„μ£Όλ©λ‹ˆλ‹€... 두 λ²ˆμ§ΈλŠ” λ‹€μš΄νƒ€μž„ 없이 배포λ₯Ό μˆ˜ν–‰ν•˜λŠ” λ™μ‹œμ— 이전 λ²„μ „κ³Όμ˜ ν˜Έν™˜μ„±μ„ μœ μ§€ν•  수 μžˆλŠ” 방법에 λŒ€ν•œ μ†”λ£¨μ…˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.

μš°λ¦¬κ°€ μž‘μ—…ν•  ν”„λ‘œμ νŠΈλŠ” κ°„λ‹¨ν•œ Spring Boot Flyway μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 될 κ²ƒμž…λ‹ˆλ‹€. Person с first_name ΠΈ last_name λ°μ΄ν„°λ² μ΄μŠ€(λŒ€λž΅. λ²ˆμ—­: Person λŠ” ν…Œμ΄λΈ”μ΄κ³  fμž…λ‹ˆλ‹€irst_name ΠΈ last_name - 이것은 κ·Έ μ•ˆμ— μžˆλŠ” ν•„λ“œμž…λ‹ˆλ‹€.). 이름을 λ°”κΎΈκ³  μ‹ΆμŠ΅λ‹ˆλ‹€ last_name Π² surname.

κ°€μ •

μ„ΈλΆ€ 사항을 μ‚΄νŽ΄λ³΄κΈ° 전에 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λŒ€ν•΄ λͺ‡ κ°€μ§€ 가정을 ν•΄μ•Ό ν•©λ‹ˆλ‹€. μš°λ¦¬κ°€ λ‹¬μ„±ν•˜κ³ μž ν•˜λŠ” μ£Όμš” κ²°κ³ΌλŠ” μƒλ‹Ήνžˆ κ°„λ‹¨ν•œ ν”„λ‘œμ„ΈμŠ€μž…λ‹ˆλ‹€.

λ©”λͺ¨. λΉ„μ¦ˆλ‹ˆμŠ€ ν”„λ‘œνŒ. ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹¨μˆœν™”ν•˜λ©΄ 지원 λΉ„μš©μ„ 많이 μ ˆμ•½ν•  수 μžˆμŠ΅λ‹ˆλ‹€. νšŒμ‚¬μ—μ„œ μΌν•˜λŠ” μ‚¬λžŒμ΄ λ§Žμ„μˆ˜λ‘ 더 λ§Žμ€ λΉ„μš©μ„ μ ˆμ•½ν•  수 μžˆμŠ΅λ‹ˆλ‹€!

λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό λ‘€λ°±ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

μ΄λŠ” 배포 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹¨μˆœν™”ν•©λ‹ˆλ‹€(μ‚­μ œ λ‘€λ°±κ³Ό 같은 일뢀 λ°μ΄ν„°λ² μ΄μŠ€ 둀백은 거의 λΆˆκ°€λŠ₯함). μš°λ¦¬λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜λ§Œ λ‘€λ°±ν•˜λŠ” 것을 μ„ ν˜Έν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ„œλ‘œ λ‹€λ₯Έ λ°μ΄ν„°λ² μ΄μŠ€(예: 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 배포λ₯Ό μ‹œλ„ν•œ ν›„ (λŒ€λž΅. λ‹Ή: μ €μžλŠ” μ•„λ§ˆλ„ μ—¬κΈ°μ„œ A/B ν…ŒμŠ€νŠΈλ₯Ό μ˜λ―Έν–ˆμ„ κ²ƒμž…λ‹ˆλ‹€.) μš°λ¦¬λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 이전 λ²„μ „μœΌλ‘œ λ‘€λ°±ν•΄μ•Ό ν•œλ‹€κ³  κ²°μ •ν–ˆμŠ΅λ‹ˆλ‹€. 1.0.0. λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό λ‘€λ°±ν•˜κ³  μ‹Άμ§€ μ•Šλ‹€κ³  κ°€μ •ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

단계 :

  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, if 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() XNUMX이 μ•„λ‹Œ μ˜¬λ°”λ₯Έ 값을 μ„ νƒν–ˆμŠ΅λ‹ˆλ‹€.

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, 데이터 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ΄ μ™„λ£Œλ  λ•ŒκΉŒμ§€(old β†’ new μ—΄) μƒˆ 열을 μΏΌλ¦¬ν•˜λ©΄ 데이터가 μΌκ΄€λ˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‘€λ°±

이제 μ•± 버전이 μƒκ²ΌμŠ΅λ‹ˆλ‹€ 2.0.0 그리고 λ°μ΄ν„°λ² μ΄μŠ€ v2.

단계 :

  1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ²„μ „μœΌλ‘œ λ‘€λ°± 1.0.0.
  2. 버전 1.0.0 λ°μ΄ν„°λ² μ΄μŠ€μ˜ 열을 μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. surnameμ΄λ―€λ‘œ 둀백이 성곡해야 ν•©λ‹ˆλ‹€.

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

슀크립트 μΆ”κ°€ 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단계: μ½”λ“œμ—μ„œ last_name 제거

μ•± 버전 : 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, XNUMX이 μ•„λ‹Œ 경우, κ·Έλ ‡μ§€ μ•Šμ€ 경우 -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단계: λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ last_name 제거

μ•± 버전 : 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. (μ°Έκ³ : 이 μ—΄μ—λŠ” null이 μ•„λ‹Œ μ œμ•½ 쑰건이 μžˆμ–΄μ„œλŠ” μ•ˆ λ©λ‹ˆλ‹€.)
  3. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 버전 배포 3.0.0, λ°μ΄ν„°λ§Œ μ €μž₯ν•©λ‹ˆλ‹€. surname μ„±μ—μ„œ μ½μŠ΅λ‹ˆλ‹€. λ°μ΄ν„°λ² μ΄μŠ€μ˜ 경우 λ§ˆμ§€λ§‰ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ΄ μ§„ν–‰ μ€‘μž…λ‹ˆλ‹€. last_name Π² surname. λ˜ν•œ ν•œκ³„ NULL μ•„λ‹˜ μ—μ„œ 제거됨 last_name. λ°μ΄ν„°λ² μ΄μŠ€κ°€ ν˜„μž¬ λ²„μ „μž…λ‹ˆλ‹€ v3
  4. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 버전 배포 4.0.0 - μ½”λ“œλŠ” λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ°μ΄ν„°λ² μ΄μŠ€ 배포 v4, 제거 last_name. μ—¬κΈ°μ—μ„œ λ°μ΄ν„°λ² μ΄μŠ€μ— λˆ„λ½λœ μ œμ•½ 쑰건을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 μ ‘κ·Ό 방식을 λ”°λ₯΄λ©΄ λ°μ΄ν„°λ² μ΄μŠ€/μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν˜Έν™˜μ„±μ„ μ†μƒμ‹œν‚€μ§€ μ•Šκ³  항상 ν•˜λ‚˜μ˜ 버전을 λ‘€λ°±ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ•”ν˜Έ

이 기사에 μ‚¬μš©λœ λͺ¨λ“  μ½”λ“œλŠ” λ‹€μŒμ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κΉƒν—ˆλΈŒ. μ•„λž˜λŠ” μΆ”κ°€ μ„€λͺ…μž…λ‹ˆλ‹€.

ν”„λ‘œμ νŠΈ

μ €μž₯μ†Œλ₯Ό λ³΅μ œν•˜λ©΄ λ‹€μŒκ³Ό 같은 폴더 ꡬ쑰λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

β”œβ”€β”€ 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.

당신은 μ‚΄νŽ΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€ http://localhost:8080/flyway, 슀크립트 λͺ©λ‘μ΄ μžˆμŠ΅λ‹ˆλ‹€.

이 μ˜ˆμ—λŠ” H2 μ½˜μ†”λ„ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€( http://localhost:8080/h2-console) λ°μ΄ν„°λ² μ΄μŠ€ μƒνƒœλ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€(κΈ°λ³Έ jdbc URL은 jdbc:h2:mem:testdb).

μΆ”κ°€

λΈ”λ‘œκ·Έμ—μ„œ λ‹€λ₯Έ 기사도 μ½μ–΄λ³΄μ„Έμš”.

좜처 : habr.com

DDoS 보호, VPS VDS μ„œλ²„κ°€ μžˆλŠ” μ‚¬μ΄νŠΈλ₯Ό μœ„ν•œ μ•ˆμ •μ μΈ ν˜ΈμŠ€νŒ… κ΅¬μž… πŸ”₯ DDoS 곡격 λ°©μ§€ κΈ°λŠ₯이 νƒ‘μž¬λœ μ•ˆμ •μ μΈ μ›Ήμ‚¬μ΄νŠΈ ν˜ΈμŠ€νŒ…, VPS 및 VDS μ„œλ²„λ₯Ό κ΅¬λ§€ν•˜μ„Έμš” | ProHoster