v2 DB 무중단 마이그레이션 - 100-hours-a-week/KTB4-17th-wiki GitHub Wiki
DB 마이그레이션 테스트
1. 마이그레이션 테스트
1.1. 목적
- 서비스 요청이 들어오는 상태에서 기존 v1 DB를 v2 RDS로 전환
- 전환 과정의 API 에러율과 읽기/쓰기 불가 시간 측정
- 데이터 누락 및 중복 여부 확인
- v2 RDS 전환 실패 시 기존 v1 DB로 롤백 가능한지 확인
1.2. 마이그레이션 방식
1.2.1. 쓰기 중단 + CDC 방식
- Full Load: v1 DB의 기존 데이터를 v2 RDS로 복제
- CDC: 마이그레이션 중 발생하는 변경 데이터를 지속적으로 복제
v1 DB
→ 기존 데이터 복제
→ 변경 데이터 실시간 반영
→ 쓰기 중단
→ 복제 지연 = 0
→ v2 RDS 전환
→ 성공 시 Commit / 실패 시 Rollback
1.2.2. 메시지 큐 도입
v1 DB
→ 기존 데이터 복제
→ 변경 데이터 실시간 반영
→ 쓰기 요청은 큐에 보관하고 조회는 계속 처리
→ 쓰기 중단
→ 복제 지연 = 0
→ v2 RDS 전환
→ 큐에 대기 중인 쓰기 반영
→ 성공 시 Commit / 실패 시 Rollback
1.3. 테스트 대상 API
| 구분 | API |
|---|---|
| 쓰기 | POST /api/v1/chat-rooms/{chatRoomId}/messages |
| 읽기 | GET /api/v1/chat-rooms/{chatRoomId}/messages?size=20 |
1.4. Rollback 기준
: 3분 이내 정상화되지 않거나 복구 불가능한 오류가 확인되면 부하를 중지하고 즉시 수동 Rollback한다.
- [롤백 조건]
- Backend Task 실패가 3회 발생
- ALB Health Check가 2회 연속 실패
- Health Check 응답시간이 5초를 초과
2. 마이그레이션 환경 구성
2.1. 기본 구성
- Source DB
- 현재 서비스에서 사용 중인 기존 DB
- Target RDS
- 마이그레이션 후 사용할 신규 DB
- AWS DMS
- Source DB의 기존 데이터와 변경 데이터를 Target RDS로 복제
- Backend (v2 ECS)
- 전환 전: Source DB 사용
- 전환 후: Target RDS 사용
2.2. 테스트 데이터
- 테스트 계정: 총 130명
- 부하 테스트용: 120명
- 프로브용: 10명
- 테스트용 채팅방: 65개
- 기본 쓰기 데이터: 채팅방당 메시지 500건
- 각 쓰기 요청에 고유 ID를 부여하여 중복 쓰기 방지
2.3. 모니터링
- DMS
- CloudWatch를 통해 CDC 지연 확인
- 애플리케이션
- k6를 통해 API 성공/실패 요청 수 측정
- AWS 인프라
- Backend 서비스 수(ECS 컨테이너 개수)
- ALB Health Check 확인
- WhaTap
- SQL 실행 시간, 호출 건수
2.4. 데이터 정합성 검증 : full outer join 방식, checksum방식
(1) 양적 검증: 데이터의 갯수나 존재유무
-
기존: row수 세기 → 양방향
GROUP BY결과를FULL OUTER JOIN으로 비교Source 테이블과 Target 테이블을 동일한 기준으로
GROUP BY한 뒤 두 결과를FULL OUTER JOIN하여 집계치 차이를 검증.
[ 동작 방식 ]
채팅방 id로 group by를 각각 진행
| chat_room_id | row_count |
|---|---|
| 100 | 50 |
| 200 | 30 |
| 300 | 20 |
source와 target에 FULL OUTER JOIN 진행 → 채팅 건수 비교
| chat_room_id | Source 건수 | Target 건수 |
|---|---|---|
| 100 | 50 | 50 |
| 200 | 30 | 28 |
| 300 | 20 | 0 |
| 400 | 0 | 10 |
(2) 질적 검증: 데이터 값, 관계, api확인
- checksum: source와 target의 데이터 일치 여부 확인
- DB마이그레이션 전후 테이블의 행,컬럼값 비교.
[ 동작 방식 ]
select권한 확인
→ 테이블 마다 checksum 쿼리 생성함
→ `CRC32`로 행의 값을 숫자로 만듦
→ 그 결과를 XOR로 합침 (최종 checksum= h1 xor h2 xor h3)
→ source와 target의 체크썸 비교
출처: https://dev.mysql.com/doc/refman/8.4/en/checksum-table.html
3. 단계별 마이그레이션 테스트
3.1. 쓰기 중단 + CDC 마이그레이션
- 상태: 10 RPS 성공
- DB 전환 중 쓰기를 중단하고 요청 실패율 및 쓰기 불가 시간 측정
3.1.1. 테스트 결과
- 부하: 쓰기 10 RPS, 읽기 10 RPS
- Backend 중단부터 RDS 첫 정상 응답까지: 6분 46초
| 부하 | 쓰기 불가 시간 | API 실패율 | DB 오류 | 결과 |
|---|---|---|---|---|
| 10 RPS | 6분 46초 | 67.8% | 0건 | 성공 |
3.1.2. API 요청 결과
- 전체 요청: 12,397건
- 실패 요청: 8,401건
- 실패율: 67.8%
실패 원인
| 원인 | 건수 |
|---|---|
| Backend 중단으로 인한 503 | 5,002건 |
| Target Backend 기동 대기 중 503 | 2,422건 |
| 신규 Backend 등록 중 502 | 948건 |
| DB Connection/Query 오류 | 0건 |
3.1.3. API 지연 시간
- 전환 전 정상 구간 p95
- 쓰기: 162ms
- 읽기: 155ms
- k6 성공 요청 전체 p95: 3.284초
- v2 Backend 기동 직후의 지연 포함
3.1.4. 데이터 정합성
- 결과: 만족
- 프로브 쓰기 성공: 2,049건
- v2 RDS 저장: 2,049건
- 데이터 누락: 0건
- 데이터 중복: 0건