- Flyway_Schema_History 테이블 자동 복구하기2025년 03월 20일 18시 07분 59초에 업로드 된 글입니다.작성자: do_hyuk
Flyway로 생성된 flyway_schema_history 테이블에는 스키마 변경 내역이 저장되는데 만약 V2 스크립트 파일을 마이그레이션하다가 오류가 발생하게 된다면, flyway_schema_history 테이블에는 V2에 대한 실패 내역이 저장되게 된다.
이후에 실패한 원인을 찾아 V2 스크립트 파일의 명령어를 수정하고 다시 실행한다 해도 이미 V2에 대한 실패 내역이 남아있기 때문에 해당 버전은 flyway가 실행하지 않는다.
그렇다면 수정한 코드로 V3를 새로 만들어서 실행해야하느냐? 물론 이 방식도 존재하지만 간단한 오류를 고치기 위해 항상 새로운 버전을 생성해야하는 것은 번거로운 방법이라 볼 수 있다. 그러면 기존에 에러나 스크립트 파일을 수정한 뒤에 어떻게 다시 적용할 수 있을까?
해결방법
첫 번째, DB에 직접 접근하여 flyway_schema_history 테이블에 실패한 내역이 저장된 행을 직접 삭제한다.
이 방법이 가장 쉽게 떠올릴 수 있는 방식이지만, DB에 직접 접근을 한다는 것 자체가 상당히 귀찮기도 하고 또 DB 관리를 편하게 하기위해 flyway를 사용하는 입장에서 취지와 맞지 않는다.
두 번째, spring에서 자동으로 repair 기능이 실행되도록 한다.
repair란? flyway_schema_history 테이블에 문제가 생겼을 때, 이를 해결하기 위한 flyway의 기능이다.
- 실패한 마이그레이션 항목 제거
- 적용된 마이그레이션의 체크섬, 설명 및 유형을 사용 가능한 마이그레이션의 체크섬과 다시 정렬
- 누락된 모든 마이그레이션을 삭제된 것으로 표시
위와 같은 기능을 해결해주는데, repair는 마이그레이션이 실행될 때에 진행되어야 한다.
Spring의 FlywayMigrationStrategy
스프링에서는 FlywayMigrationStrategy를 제공해주는데,
Flyway 마이그레이션을 초기화하는 데 사용되는 전략으로, 사용자 정의 구현을 @Bean으로 등록하여 기본 마이그레이션 동작을 재정의할 수 있다.
따라서 FlywayMigrationStrategy를 재정의하여, 매 flyway의 migrate 작업이 실행되기 직전 repair를 해준다면 flyway에 문제가 발생해도 적절한 상태에서 migrate 가능하다.
@Configuration public class FlywayConfig { @Bean public FlywayMigrationStrategy flywayMigrationStrategy() { return flyway -> { flyway.repair(); flyway.migrate(); }; } }
실행 결과
migrate 작업이 실행되기 전 repair가 실행되는지 확인해보기 위해 일부로 flyway_schema_history 테이블에 실패 내역을 남긴다.
v2의 실패 내역이 두 번째 행에 저장된 것을 볼 수 있다.
repair 기능이 없이 V2 스크립트만 수정하여 다시 실행을 해본다면 아래와 같은 에러가 발생한다.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'flywayInitializer' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'flywayInitializer' defined in class path resource [org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration$FlywayConfiguration.class]: Validate failed: Migrations have failed validation Detected failed migration to version 2 (update codepost and tilpost schema). Please remove any half-completed changes then run repair to fix the schema history.
간단히 설명하자면 version 2의 마이그레이션이 실패하여 유효성 검사에 실패한 것이다.
스크립트가 수정되었더라도, Flyway는 이미 실행된 마이그레이션의 히스토리를 기반으로 유효성을 검사한다.
만약 수정된 스크립트가 이전 실행 결과와 불일치한다면, 유효성 검사에서 실패할 수 있다.
이제 repair 기능을 적용한 후 다시 실행해보겠다.
예상했던 것과는 다르게 다시 한 번 에러가 발생한 것을 알 수 있다.
SQL State : 42S21 Error Code : 1060 Message : Duplicate column name 'writer_id' ...
위와 같은 에러가 발생한 이유는 테스트 진행을 위해 일부로 실패한 스크립트 구조 흐름을 보면 알 것이다.
// V2 스크립트 파일 흐름 CodePost 테이블에 writer_id, writer_email, writer_nickname 컬럼 추가 TILPost 테이블에 writer_id, writer_email, writer_nickname 컬럼 추가 ------------------------문제 발생 지점------------------------------- CodePost 테이블의 기존 member_id 값을 writer_id로 복사 TILPost 테이블의 기존 member_id 값을 writer_id로 복사 CodePost 테이블의 writer_id를 기준으로 writer_email, writer_nickname 업데이트 TILPost 테이블의 writer_id를 기준으로 writer_email, writer_nickname 업데이트 CodePost 테이블에서 member 외래 키 제거 TILPost 테이블에서 member 외래 키 제거 CodePost 테이블에서 member 컬럼 제거 TILPost 테이블에서 member 컬럼 제거
각 테이블에 새로운 컬럼을 추가하는 명령어는 제대로 동작을 했지만 문제 발생 지점에 Update 문에서 문제가 발생했기 때문에 컬럼 중복 에러가 발생하게 된 것이다.
이처럼 하나의 스크립트에 여러 변경사항을 적용했기 때문에 발생한 상황이고, 이와 같은 상황은 자주 일어날 수 있다고 생각하여 스크립트 작성 시 주의해야 할 점을 제대로 인지해둬야겠다.
Flyway 스크립트 작성 시 참고사항
큰 변경사항은 여러 개의 작은 마이그레이션으로 나누는 것이 좋다.
- 리스크 관리
- 작은 변경사항은 문제 발생 시 파악과 해결이 쉽다.
- 큰 변경사항 중 일부만 실패할 경우, 전체 롤백이 아닌 부분적 수정이 가능하다.
따라서 문제 발생 시 특정 단계까지만 롤백하기 쉬워진다.
- 점진적 적용:
- 서비스 중인 시스템에서 대규모 변경을 한 번에 적용하는 것은 위험할 수 있다.
- 작은 단위로 나누면 변경사항을 점진적으로 적용하고 검증할 수 있다.
- 가독성과 유지보수성:
- 각 마이그레이션 스크립트가 작고 명확할수록 이해하기 쉽고 유지보수하기 좋다.
- 변경 이력을 추적하기 쉬워진다.
- 성능 고려:
- 대규모 변경은 데이터베이스에 큰 부하를 줄 수 있다.
- 작은 변경으로 나누면 각 변경의 영향을 최소화하고 필요 시 시간대를 나누어 적용할 수 있다.
위의 참고 사항을 적용한 스크립트 구조이다.
기존에 V2로 통합되었던 구조를
V2.1에는 새로운 컬럼 추가 쿼리만을 넣고,
V2.2에는 새로운 컬럼에 값을 옮기고 외래키를 삭제하는 쿼리를 넣었다.
post 테이블 변경사항을 롤백한 뒤에 재 실행 해보겠다.
flyway_schema_history 테이블의 v2 실패내역이 성공으로 바뀐것을 확인할 수 있다.
또한 code_post와 til_post의 스키마도 제대로 변경된 것을 확인할 수 있다.
member_id는 삭제되고 writer 컬럼 3개에 데이터가 들어가 있는 모습 '포트폴리오 > AutoReview' 카테고리의 다른 글
Join 연산 무조건 피해야 하나? (0) 2025.03.24 [트러블 슈팅] 2개 이상의 데이터베이스 초기화 기능은 사용하지 말자 (0) 2025.03.22 배포된 데이터베이스의 스키마를 변경해보자(2) (0) 2025.03.15 배포된 데이터베이스의 스키마를 변경해보자(1) (0) 2025.03.11 연관관계 설정은 필수일까? (0) 2025.03.07 댓글