여러 앱 인스턴스로 데이터베이스 마이그레이션을 안전하게 실행하는 방법은 무엇입니까?


10

고속 (1 초 미만) 및 느린 데이터베이스 마이그레이션 (> 30 초)이 혼합 된 응용 프로그램이 있습니다. 현재 CI의 일부로 데이터베이스 마이그레이션을 실행하고 있지만 CI 도구는 여러 환경에서 앱에 대한 모든 데이터베이스 연결 문자열을 알고 있어야합니다. 응용 프로그램을 시작할 때 자체 데이터베이스 마이그레이션을 실행하도록이 프로세스를 변경하려고합니다.

상황은 다음과 같습니다.

이 애플리케이션의 인스턴스는 여러 개 (약 5 개) 있습니다. 그들에게 전화합시다 node1, ..., node5. 각 앱은 단일 SQL Server 인스턴스에 연결되며 롤링 배포를 사용하지 않습니다 (알고있는 한 모든 앱이 동시에 배포 됨)

문제 : 마이그레이션이 오래 진행되고 있다고 가정합니다. 이 경우 node1마이그레이션을 시작한 다음 실행을 시작합니다. 이제 node4시작하고 장기 실행 마이그레이션이 아직 완료되지 않았으므로 node4마이그레이션 실행-> 데이터 손상 가능성이 있습니까? 이 문제를 어떻게 방지 할 수 있습니까, 아니면 걱정할 정도로 중요한 문제입니까?

분산 잠금 (사용 etcd하거나 그 라인을 따라) 으로이 문제를 해결하려고 생각했습니다 . 기본적으로 모든 앱은 잠금을 획득하려고 시도하며 그 중 하나만 가져 와서 마이그레이션을 실행 한 다음 잠금을 해제합니다. 나머지 앱이 시작되어 중요 섹션에 들어가면 모든 마이그레이션이 이미 실행되었으므로 마이그레이션 스크립트가 종료됩니다.

그러나 내 직감은 "이것은 과잉입니다. 더 간단한 해결책이 있어야합니다."라고 말하면서 다른 사람에게 더 좋은 아이디어가 있는지 물어볼 것이라고 생각했습니다.


1
"마이그레이션 상태"테이블을 전역 / 분산 잠금으로 사용하는 것은 어떻습니까? 단일 행은 마이그레이션이 현재 활성화되어 있고 마이그레이션이 마지막으로 실행 된 것을 나타냅니다.
Bart van Ingen Schenau

앱을 비동기 적으로 배포해야합니까?
Ben

답변:


4

이전의 DBA.SE post 에 따르면 SQL Server에 대해 언급 했으므로 스키마 변경 사항을 트랜잭션에 적용 할 수 있습니다. 이를 통해 다른 형태의 DB에 대한 동시 쓰기와 마찬가지로 마이그레이션을 설계 할 수 있습니다. 트랜잭션을 시작하고 실패하면 롤백합니다. 이렇게하면 최악의 데이터베이스 손상 시나리오 중 일부가 방지됩니다 (단, 열 또는 테이블 삭제와 같은 파괴적인 마이그레이션 단계가있는 경우 트랜잭션만으로는 데이터 손실을 막을 수 없습니다).

지금까지 migrations이미 적용된 마이그레이션이 등록 된 테이블이 필요 하므로 애플리케이션 프로세스에서 특정 마이그레이션이 이미 적용되었는지 확인할 수 있습니다. 그런 다음 "SELECT FOR UPDATE"를 사용하여 다음과 같은 마이그레이션을 구현하십시오 (의사 코드).

  • 거래 시작
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • 이전 명령문이 값을 리턴하면 트랜잭션을 종료하십시오.
  • 마이그레이션을 적용하십시오 (실패하면 롤백하고 실패를 기록한 후 트랜잭션을 종료하십시오)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • 거래를 끝내다

그러면 잠금 메커니즘이 "이주가 이미 적용 되었습니까" 테스트에 직접 빌드 됩니다 .

이론적으로이 디자인은 마이그레이션 단계에서 실제로 적용되는 응용 프로그램을 인식하지 못하게합니다. 1 단계는 app1, 2 단계는 app2, 3 단계는 app 3, 4 단계는 app1에 의해 적용될 수 있습니다. 다시, 등등. 그러나 다른 앱 인스턴스가 사용중인 한 마이그레이션을 적용하지 않는 것이 좋습니다. 귀하의 질문에 언급 된 병렬 배포는 이미이 제약 조건을 고려할 수 있습니다.


1

여러 노드가있는 데이터베이스 마이그레이션을 지원하는 라이브러리를 찾을 수 있습니다.

Java 세계에서 두 개의 라이브러리에 대해 알고 있으며 둘 다 필요한 것을 지원합니다.

  • Liquibase : FAQ에서 : Liquibase는 분산 잠금 시스템을 사용하여 한 번에 하나의 프로세스 만 데이터베이스를 업데이트 할 수 있습니다. 다른 프로세스는 잠금이 해제 될 때까지 기다립니다.
  • 플라이 웨이 : 다운로드 페이지에서 : 여러 노드를 병렬로 안전하게 보호 ✓

Java 및 기타 언어를위한 다른 도구도있을 수 있습니다.


이러한 도구를 사용할 수 없거나 원하지 않는 경우 테이블을 잠금 또는 마이그레이션 로그로 사용할 수 있습니다 ( 예 : Doc Browns 답변 참조) .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.