HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/
Spring Data
Spring Data
/
Flyway
Flyway
Flyway

Flyway

목적동작 원리적용 방법최신 버전으로 Migration 자동으로 할 수 있도록 설정Migration, clean 등 조금 더 세밀하게 관리 → plugin, CLI .. ConfigurationsTroubleShooting

목적

  • 소스코드를 github로 형상 관리하는 것처럼 DB의 변경사항을 형상관리하는 툴임
      1. 예를들어 로컬 DB에 어떤 테이블을 만들고 그다음에 그 테이블을 수정한 것을 형상관리(Migration Script 작성)를 해 놓으면
      1. 다른 DB(local에서 하다가 운영에 배포)에 해당 스키마들을 세팅할 때, Flyway가 알아서 차례대로 Migration Script DDL을 수행하여 똑같은 형태로 table을 생성해줌

동작 원리

[Flyway Documentation - How Flyway Works]
  • flyway_schema_history 라는 테이블을 만들어서 거기에서 아래와 같이 관리한다고 함. 자세한건 링크 참고
notion image
Baseline Migration [ 참고링크 ]
  • 여러 마이그레이션이 적용되고 난 후의 데이터베이스의 상태를 하나의 cumulative한 migration으로 나타내기 위해서 사용하는 방식임

적용 방법

최신 버전으로 Migration 자동으로 할 수 있도록 설정

의존성 추가
implementation 'org.flywaydb:flyway-core:8.5.12' implementation 'org.flywaydb:flyway-mysql:8.5.12'
  • 위 해당 의존성으로 추가하면 flyway관련 Configuration(flyway db url 설정 등)하지 않고, DataSource 관련 configuration(spring.datasource)만 진행하면 ApplicationContext initialization하면서 mysql url 읽고 알아서 Bean Initialization 진행해줌
    • org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class. 여기서 AutoConfiguration 진행됨
classpath 상 db/migration이라는 경로에 migration script를 만들어주어야 함
Flyway failed to initialize: none of the following migration scripts locations could be found:
- classpath:db/migration
만약 이 경로 바꾸고 싶으면 spring.flyway.location 설정으로 변경 가능
Migration script 작성
notion image
  • prefix - version - description - suffix 순서임
    • 예시 : V1_0_1__add_member.sql
  • prefix
    • V는 버전 마이그레이션, R은 반복 마이그레이션 용 접두사(반드시 V또는 R로 시작해야함)
    • 반복 마이그레이션은 어떠한 부작용도 없이 반복적으로 실행 가능한 migration을 말함
      -- migration.sql -- Create a stored procedure to calculate the total sales for a given product CREATE OR REPLACE PROCEDURE calculate_total_sales(product_id INT) AS BEGIN DECLARE total_sales DECIMAL(10,2); -- Calculate the total sales for the product and store it in the 'total_sales' variable SELECT SUM(sales_amount) INTO total_sales FROM sales WHERE product_id = product_id; -- Display the result DBMS_OUTPUT.PUT_LINE('Total sales for product ' || product_id || ': ' || total_sales); END; /
  • version
    • 버전 마이그레이션에서만 명시함.
    • 숫자와 Dot, underscore 조합으로 구성함
    • version과 description사이에는 언더바 2개 반드시 있어야 함
  • description
    • schema_version 테이블에 저장 시 설명으로 사용
  • suffix
    • 확장자 기본은 .sql
  • Versioned migrations are typically used for: [ Docs 참고 ]
    • Creating/altering/dropping tables/indexes/foreign keys/enums/UDTs/…
    • Reference data updates
    • User data corrections
Flyway가 schema 버전을 관리하는 용도의 flyway_schema_history 테이블을 자동으로 만들어주는 옵션 설정
spring: flyway: baseline-on-migrate:true

Migration, clean 등 조금 더 세밀하게 관리 → plugin, CLI ..

Flyway plugin 설정(Gradle, Maven) & 수동으로 migrate, clean 하는 방법
  1. plugin 설정
    1. <build> ... <plugin> <groupId>org.flywaydb</groupId> <artifactId>flyway-maven-plugin</artifactId> <version>9.0.1</version> </plugin> ... </build>
      Maven
      plugins { id "org.flywaydb.flyway" version "9.8.1" }
      Gradle
  1. plugin에서 필요한 Configuration 설정 → flyway.conf 파일 생성
    1. 다양한 방식으로 Configuration이 가능함(Flyway Doc 참고)
      • 환경 변수 방식도 됨
      그 중 flyway.conf 파일 만들어서 관리
      flyway.baselineOnMigrate=true flyway.url=jdbc:mysql://localhost:3306/realworld?serverTimezone=UTC&characterEncoding=UTF-8 flyway.user=root flyway.password=1234 flyway.cleanDisabled=false
  1. plugin 명령어 별로 실행
    1. notion image
gradle Flyway plugin
plugins { id "org.flywaydb.flyway" version "8.2.0" } dependencies { implementation 'org.flywaydb:flyway-core:8.5.12' implementation 'org.flywaydb:flyway-mysql:8.5.12' } flyway { url = "jdbc:mysql://localhost:3306/tenwonmoa?serverTimezone=UTC&characterEncoding=UTF-8" user = "root" password = "root1234" }
  • 정확한 url을 입력해줬는데도 No database found to handle url 이 에러가 뜬다면 버전을 조정해보기 (8.2.0으로 조정한 것) [ 참고 github 이슈 ]
Flyway Configuration key값들 도큐먼트 참고
 

Configurations

  • mixed : whether to allow mixing transactional and non-transactional statements within the same migration. 이걸 가능케 하면 모든 migration들이 transaction 없이 실행될 수가 있음 [ 참고 ]

TroubleShooting

Procedure는 여러 sql 파일에 나누어서 만들어줘야함 ( 이유는 파악 못함.. )
  • 아래와 같이 여러개의 PROCEDURE를 하나의 sql 파일에서 관리하면 migration이 실패함
  • 하나의 sql에 한개씩만 만들면 문제없이 만들어짐
CREATE PROCEDURE [dbo].[spProcBlockList] @i_type INT, @i_ip VARCHAR(22), @i_reason INT, @o_ret INT OUTPUT AS BEGIN SET NOCOUNT ON; SET @o_ret = 0; IF @i_Type = 0 BEGIN SELECT IP FROM block_list END ELSE IF @i_Type = 1 BEGIN INSERT INTO block_list(ip, reason, create_time) VALUES(@i_ip, @i_reason, GETDATE()); SELECT @i_ip END RETURN; END; CREATE OR ALTER PROCEDURE [dbo].[spGetSceneInfo] @o_ret INT OUTPUT AS BEGIN SET NOCOUNT ON; SET @o_ret = 0; SELECT id, room_type, scene_id, max_user_cnt FROM md_scene_info RETURN; END;
 
테이블 구조 변경 후 데이터 삽입 쿼리 하나의 version 으로 관리하면 동작을 안함
테이블 구조 변경하는 쿼리와, 데이터 삽입하는 쿼리 각각 버저닝해야함
이유는 추측상 테이블 구조가 변경이 아직 안되었는데 데이터를 삽입하려고 하니 에러발생하는 것같음
  • INSERT INTO (col1, col2 ..) values (val1, val2, …), (val1, val2, …) 와 같이 여러 값을 동시에 삽입하는 게 정상동작 안함. 한개씩 INSERT 구문 실행해주어야 함
  • Non-transactional query(eg. CREATE INDEX) 를 실행시킬시 계속 hang 걸리는 현상 [ 참고 ]
postgresql에서 인덱스 생성 (CREATE INDEX CONCURRENTLY)하면서 락걸린 문제..
[ Github ] Flyway 9.19.3 migrate hangs forever on second non-transactional migration
[ Github ] Flyway hanging forever on concurrent index creation
테이블 lock 조회 및 kill 하는 방법
  • 해결책
    • postgresql의 Transactional Lock 기능을 끄기 [ Flyway 문서 참고 ]
    • This should be set to false for statements such as CREATE INDEX CONCURRENTLY. (default : true )
    • 위 문서 참고해서 gradle plugin 이용하여 migrate 성공