정말 1년동안... 회사핑계로 블로그에 작성하는 시간을 갖지 못했던것 같다.. 반성ㅠㅠ 앞으로 종종 그동안 배운 내용 올리도록 하겠습니다.
만약 다수의 table 변경이나 data 추가, 삭제, 변경등을 기록하고 관리하고 있지 않는다고 한다면,
언제가는 누군가가 변경했던 것에 대해 공유하지 않을 경우 당황스런 순간을 겪게 될것입니다.
소개
Flyway는 오픈소스 Database 마이그레이션 Tool이다.
DB 스키마 변경에 대한 마이그레이션 작업과 변경에 대한 버전관리(형상관리)를 제공한다.
개발자 Local에서 구현되어 테스트 되어진 프로그램의 Source Code는 형상관리 Tool(git, svn, etc...)을 이용하여 변경이력을 관리하고 있지만 database는 어떠한가? 각 개발자의 Local환경에서 개발시 사용되는 database의 schema 변경에 대한 마땅한 이력관리 방법이 존재하지 않는다.
즉 Local개발환경의 database 변경사항을 다른 배포단계의 database에 적용 하려면 어쩔 수 없이 배포전 변경사항을 수동으로 처리 해야줘야 한다. 이런 수동적인 처리방법 때문에 글의 첫 부분과 같은 에피소드들이 발생하게 되는것이다.
flyway는 이런 수동관리의 불편함을 손 쉽게 해결해주는 Tool이다.
설치환경
- intelliJ
- mac
- spring boot 2.6.x
- gradle
- mysql 8버전
Dependency
// pom.xml
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
// build.gradle
implementation group: 'org.flywaydb', name: 'flyway-core', version: '7.7.1'
application.properties
flyway에게 db username과 password를 제공한다. (사용하는 DB의 username, password 동일하게)
아래 2개의 예시와 같이 작성하면 된다.
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/bookdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=validate
spring.sql.init.mode=always
spring.flyway.user=username
spring.flyway.password=password
# mysql database
datasource:
hikari:
driver-class-name: com.mysql.cj.jdbc.Driver
max-lifetime: 28797000
minimum-idle: 6
maximum-pool-size: 100
username: username
password: password
flyway:
enabled: true # true 사용, false 미사용
table: flyway_schema_history # flyway 버전관리 테이블
baseline-on-migrate: true # flyway_schema_history 테이블을 자동으로 생성할지 여부
sql-migration-suffixes: sql # 파일 확장자
baseline-version: 0 # 최초 버전 정보
Flyway 작성하기
패키지 구조
패키지 구조는 위와 같습니다. 반드시 resources/db/migration 위치에서 작성해야 합니다.
만약 경로를 변경하고 싶다면 application.properties 파일에 spring.flyway.location=파일위치 로 수정할 수 있습니다.
sql 네이밍 규칙
- Prefix
- V, U, R 중 하나를 선택합니다.
- V(Version) : 버전 마이그레이션
- U(Undo) : 실행 취소
- R(Repeatable) : 반복 가능한 마이그레이션
- 버전에 상관없이 매번 실행되는 스크립트로 버전 명시가 필요 없습니다.
- 예시로 테스트를 위해 매번 더미데이터를 넣을 때 사용합니다.
- Separator : 구분자로 _ 가 2개인 것을 주의해야 합니다.
- Description : 실질적 파일 명으로 밑줄이나 공백으로 단어를 구분합니다.
- Suffix : 접미사로 보통 .sql을 사용합니다.
V1__init.sql
CREATE TABLE IF NOT EXISTS `flyway`.`member`(
`member_id` BIGINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
PRIMARY KEY (`member_id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
flyway_schema_history 테이블 (DDL 형상관리 해주는 테이블)
이제 스프링부트를 실행시켜주고 WorkBench를 이용해서 yml에 세팅해준 설정대로 생성된 flyway_schema_history를 확인해봅니다.
version 컬럼에 1로 잘 저장된 것을 확인할 수 있습니다.
flyway로 등록된 순간을 기준으로 flyway가 DB버전 관리를 하게 되므로 해당 스크립트를 수정, 삭제를 하면 안됩니다.
여기서 눈여겨 봐야할 정보는 version, checksum, 그리고 success 정도가 될것 같습니다.
- version은 파일의 V 뒤에 붙어있던 숫자로 낮은 순서부터 실행되며 실행 순서대로 테이블에 쌓이는 구조를 가집니다.
- checksum은 파일의 내용을 hashing한 것입니다. 만약 파일의 내용이 달라지면 이 체크섬이 달라지게 됩니다. 한번 체크섬을 만들어 둔 후 파일을 수정한다면 그렇게 되면 누군가에 의해서 형상관리에 문제가 생겼다고 판단하기 때문에 flyway는 에러처리를 하게됩니다. 이럴 경우 해당 파일에 대한 체크섬을 repair한 후 success를 0으로 돌리는 등의 작업이 필요합니다.
- success는 파일 실행에 성공했는지 여부를 나타내는 값입니다. 이 값에 따라서 flyway에서 해당 파일의 내용을 실행할지 말지 정합니다.
발생할 수 있는 에러
Spring Boot가 실행되며 가장 먼저 flyway가 실행되게 됩니다. 이때 발생할 수 있는 에러에 대해서 알아보도록 하겠습니다.
가장 많이 확인하실 수 있는 에러는 한번 flyway로 서비스를 모두 올린 후 일부 파일을 수정하여 checksum이 틀어지게 되어 발생하는 에러입니다. 이때 에러는 아래 처럼 발생하게 됩니다. 이 경우에는 해결하는 방법으로 2가지 방법이 있습니다. 첫번째는 해당 row를 포함한 이후 row를 삭제하고 다시 올리는 방법입니다. 두번째는 checksum을 강제로 수정하고 (repair 또는 수동으로 수정) success를 1로 돌리는 방법입니다. 1번의 방법이 편하기는 하지만 정밀한 조정이 필요하다면 2번 방법을 추천드립니다.
Caused by: org.flywaydb.core.api.FlywayException: Validate failed:
Migration checksum mismatch for migration version 1
-> Applied to database : 1727247623
-> Resolved locally : -1198089893
아래는 누군가가 파일을 삭제하던지 또는 table에서 row를 delete 했을 때 나타나는 에러 로그입니다. 이때는 누군가 의도를 가지고 처리한 것이므로 새롭게 처음부터 실행하는것을 추천드립니다.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Invocation of init method failed; nested exception is org.flywaydb.core.api.FlywayException: Validate failed:
Detected applied migration not resolved locally: 1
repair
repair는 checksum이 틀어지는 등의 문제가 생겼을 때 자동으로 checksum을 맞춰주는 방법입니다. flyway 6에서는 bean을 아래처럼 등록하시면 migrate 하기전 repair를 먼저하여 checksum을 재설정하는 작업을 진행하여 형상이 깨지는것을 막아줍니다.
@Bean
public FlywayMigrationStrategy cleanMigrateStrategy() {
return flyway -> {
flyway.repair();
flyway.migrate();
};
}
알아두면 좋은 점
하나의 파일에 2개의 DDL은 좋지 않습니다. flyway는 checksum을 파일 단위로 관리하며 파일에 문제가 생겼을 때 이 이후의 로직을 실행하지 않기 때문입니다. 따라서 DDL은 파일 하나씩 두는것을 추천합니다.
마치며..
나 역시 프로젝트를 하면서, 이번에는 flyway를 통한 DDL 형상관리를 하려고 한다. 사용하며 더 유익한 정보또는 기능이 있으면
해당 내용을 추가하며 작성하도록 하겠습니다.
📌 참고
https://velog.io/@dhk22/DB-DB-migration-Springboot-Flyway
https://sabarada.tistory.com/193
'Database > MySQL' 카테고리의 다른 글
MySQL 8.0.15 다운로드 및 설치방법 (Windows 10) (0) | 2020.06.20 |
---|
댓글