사용자 도구

사이트 도구


java:database:migration:flyway

Flyway Java Database Migration

Flyway Gradle Plugin

config 파일 이용

  • 설정 파일을 만들고, 해당 파일을 다음 처럼 호출
    gradle -Dflyway.configFiles=path/to/myAlternativeConfig.conf flywayMigrate
    gradle -Dflyway.configFiles=path/to/myAlternativeConfig.conf,other.conf flywayMigrate
     
    # 환경 설정 이용
    export FLYWAY_CONFIG_FILES=path/to/myAlternativeConfig.conf,other.conf
  • 혹은 flyway 설정에 설정파일도 지정가능
    flyway {
        configFiles = ['/path/to/file']
    }
    // 이 얘기는 공통 설정 프로필은 gradle에 지정하고 프로필별 접속 정보 설정파일을 따로 두고 아래 처럼 할 수도 있다는 얘기
    flyway {
        driver = 'org.mariadb.jdbc.Driver'
        locations = ["filesystem:${file('src/migrations').absolutePath}"]
        encoding = 'UTF-8'
        // ....
        configFiles = ['/path/to/profile.config']
    }
     
    // 혹은 -Pprofile=local 형태로 프로필을 지정하고
    flyway {
        driver = 'org.mariadb.jdbc.Driver'
        // ...
        configFiles = ["${file('src/migrations/confs/flyway-' + profile + '.conf').absolutePath}"]
    }

gradle 에 직접 설정

  • FlywayExtension 기본 뼈대
    // locations 에서 filesystem 사용시 file() 을 사용하지 않으면 상황에 따라 상대경로가 서로 다른 경로로 매핑되므로 주의필요.
    flyway {
        url = 'jdbc:....'
        user = 'dbusername'
        password = 'dbpassword'
        locations = ["filesystem:${file('src/migration/mydb').absolutePath}"]
        schemas = ['dbo']
        encoding = 'UTF-8'
        outOfOrder = true // 여러브랜치에서 서로 다른 날짜로 만들어도 작동하도록
        validateOnMigrate = true
    }

Task 직접 생성

  • Flyway Gradle 3.1 이상 버전에서 작동
  • apply plugin: 'org.flywaydb.flyway'을 실행한 상태에서 생성된 project.flyway extension이 존재할 경우 커스텀 Task가 생성이 올바로 온됐다. 따라서 커스텀 태스크를 사용할 때는 플러그인을 사용하지 말고 커스텀으로만 사용한다.
ext.flyway = null // custom 사용시 flyway extionsion null로 처리.
 
tasks.create(name: 'myFlywayMigrate', type: org.flywaydb.gradle.task.FlywayMigrateTask) {
    extension = new org.flywaydb.gradle.FlywayExtension()
    // extension configurations...
}
 
// FlywayBaselineTask, FlywayCleanTask, FlywayInfoTask, FlywayInitTask(@deprecated)
// FlywayMigrateTask, FlywayRepairTask, FlywayValidateTask

callback

SpringBoot 연동

Version Number

  • Flyway 버전 번호는 날짜 포맷으로 하는게 좋아보인다.yyyy.MM.dd.HH.mm.ss
    • 연속된 숫자로 할 경우 둘 이상의 개발자가 동일 숫자를 지정하여 오류가 발생하기 쉽다.
    • outOfOrder = true Migration 시에 숫자 증분을 하지 않아도 되게 한다.
  • Flyway Migration Creation IntelliJ IDEA 플러그인으로 쉽게 마이그레이션을 생성할 수 있다.

SpringBoot & Flyway

  • SpringBootspring.flyway.enabled=true가 기본값이다. 이 때문에 실수로 spring.flyway.enabled 값을 지정을 안해도 무조건 작동하게 된다. production DB에서도 작동할 경우 DB 날리는 일이 된다.
  • 따라서 SpringBoot application에서는 아예 flyway 에 대한 의존성을 걸지 않는 것을 추천한다.

특정 migration 실패 대응

migration 을 실행했으나, 이미 누군가가 수동으로 마이그레이션을 진행한 상황이라서 migration history 가 실패했거나 존재하지않는 상황일 때 대응하는 방법

migration history는 생성됐으나 success = 0

-- 먼저 데이터 확인
SELECT * FROM flyway_schema_history WHERE version = <실패한MIGRATION버전>;
 
-- 성공으로 강제 update
UPDATE flyway_schema_history SET success = 1 WHERE version = <실패한MIGRATION버전>;

migration history 자체가 생성이 안 됨

  • migration history 가 생성이 안 됐다면, local DB 등에서 migration 을 전체 실행하고 실패한 version 관련 정보를 강제로 넣어준다.
-- MySQL 기준임.
-- local db 에서
SELECT concat(
    'SET @max_rank = (select MAX(installed_rank) from flyway_schema_history);\n',
    'INSERT INTO flyway_schema_history ',
    'SET',
    ' installed_rank = @max_rank + 1',
    ', version = ', fsh.version,
    ', description = ''', fsh.description, '''',
    ', type = ''', fsh.type, '''',
    ', script = ''', fsh.script, '''',
    ', checksum = ''', fsh.checksum, '''',
    ', installed_by = CURRENT_USER()',
    ', installed_on = now()',
    ', execution_time = ', fsh.execution_time,
    ', success = ', fsh.success,
    ';')
FROM flyway_schema_history fsh WHERE version = <실패한MIGRATION버전>;
 
-- 실제 flyway를 적용할 DB에서 위 쿼리를 실행해서 나온 SQL 문을 실행해주면 된다.

migration history 자체가 생성이 안 됨 - skipExecutingMigrations

flyway {
    skipExecutingMigrations = true
}
  • 이 기능을 사용할 수 없으면, local 에서 실행한 history 를 그대로 복사해서 넣거나 해야한다.
java/database/migration/flyway.txt · 마지막으로 수정됨: 2023/06/08 10:20 저자 kwon37xi