회사 내부에서 flyway 컨퍼런스 한 내용을 요약해서 정리합니다.

초기 설정방법

build.gradle

compile 'org.flywaydb:flyway-core'

application.yml

spring:
  flyway:
    schemas: alice
    locations: classpath:db/migration,classpath:db/callback
    url: jdbc:mariadb:aurora://127.0.0.1:3307,127.0.0.1:3308/xxxx
    user: alice
	baselineOnMigrate: true     # V1__init
	out-of-order: true          # 비순차적 커밋

기존 datasource 에 설정된 user 정보, 패스워드 접속 url 를 flyway 속성에 맞게 넣으시면됩니다.

baselineOnMigrate: true 설명

테이블이 이미 존재하는, 비어있지 않은 스키마(데이터베이스)에서 실행될때, 
자동으로 기준선을 설정할지를 정의하는 옵션.

기준선이란, baseline 까지의 모든 마이그레이션을 제외하고 현재 기준 데이터베이스부터 시작한다는 뜻임. (기존 테이블을 유지할때 사용하면 됨.)

out-of-order: true

마이그레이션을 순서없이 실행할 수 있음.
이미 V1.0 이 있고 V3.0 을 적용했는데 이전 V2.0을 적용할때 에러가 나지 않게 하는 옵션

파일 생성법

init을 이용하여 SCHEMA_VERSION 테이블을 생성하면 V1 로 생성되기 때문에 처음 파일명은 V2 로 생성합니다.
( 위의 application 의 baselineOnMigrate: true 설정이 되어있어야합니다.)

V1__init.sql 은 flyway 에서 검증을 하지 않으므로, 이미 생성되어있는 테이블의 이력관리용으로 사용하거나 빈파일로 처리해도 무방합니다.

파일명은 V 와 숫자로 버전명을 지정하고 under_bar 두개로 시작되어야합니다.

simple1

이미 동작(RUNABLE)한 파일을 삭제 하거나 수정하면,

org.flywaydb.core.api.exception.FlywayValidateException: Validate failed: Migrations have failed validation

위와 같은 오류가 발생합니다.

에러가 발생하는 이유는, flyway 에 맞지 않는 형식이거나 이미 존재하는 테이블명, 존재하지 않는 테이블 명(or 인덱스나 유니크 키가 있다는 등등)등의 이유가 많으므로 해당 스크립트를 실행할 경우 IF NOT EXIST 나 IF EXIST 의 조건절을 넣으시면 좋습니다.

CREATE TABLE IF NOT EXISTS banner (
    id                       bigint auto_increment primary key,
    banner_type_id           bigint       null,
    title                    varchar(100) not null,
ALTER TABLE `product_detail_template_info`
    DROP INDEX IF EXISTS `idx_product_detail_info_product_id`;

브랜치를 사용하기 위한 명명규칙

한명의 전담 DBA가 있고,

분기를 거의 사용하지 않을 경우 예제 샘플처럼 V1, V2 순차적 작업이 좋습니다.

simple2

그러나 여러 개발자가 데이터 변경을 할 경우,

순차적 작업에 의한 충돌이 발생할 수 있기에 단순한 V1, V2 가 아닌,

날자시간분까지로 분리하여 사용합니다.

V 뒤의 접미사를 날짜시간분_행위_테이블명으로 지정합니다.

ex) V202102151212_Create_admin_user.sql

simple3

위의 경우, 생성된 순서와 반영 순서가 뒤섞일 수 있으므로,

순차적으로 마이그레이션을 하는 옵션을 true 에서 false 로 변경합니다.

		out-of-order: true          # 비순차적 커밋

에러 처리 방법

마지막으로 에러가 발생할 경우, 에러가 발생된 sql 파일의 이력을 삭제하는 작업을 진행합니다.

afterMigrateError	After failed Migrate runs

callback/afterMigrateError__repair.sql

DELETE FROM flyway_schema_history WHERE success=false;

참고주소: https://flywaydb.org/documentation/concepts/callbacks

여러가지 Callbacks 스크립트를 작성할 수 있습니다. 마이그레이션 시작 전, 시작 후, 에러가 발생할 때 등등,

여기서는 단순히 마이그레이션 에러가 발생하면, 실패한 이력을 삭제하여, 다음 스크립트가 진행할 수 있게 합니다.

flyway 작업 범위

DDL 만 사용하도록 합니다.

잘못된 flyway 의 경우 생성된 테이블인 flyway_schema_history 의 특정 row까지 삭제 후 재실행할 때,

insert 구문이 있다면 중복 데이터가 들어가거나 오류로 인해 동작하지 않게 됩니다.

해당 기능을 적용하는 범위는 개발에만 테이블을 만들고, 스테이징, 운영 등에 반영이 안되는 휴먼 에러 및 이력 관리 용이므로 ,

단순 DELETE, INSERT 과 같은 DML은 수정 권한을 가진 담당자가 처리하는 것을 원칙으로 합니다.

참고 예제 샘플

https://github.com/youngclown/batch-flyway