# Aurora RDS의 경쟁 상태(race condition) 발견 사례

> Clean Markdown view of GeekNews topic #24384. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=24384](https://news.hada.io/topic?id=24384)
- GeekNews Markdown: [https://news.hada.io/topic/24384.md](https://news.hada.io/topic/24384.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2025-11-16T05:41:51+09:00
- Updated: 2025-11-16T05:41:51+09:00
- Original source: [hightouch.com](https://hightouch.com/blog/uncovering-a-race-condition-in-aurora-rds)
- Points: 1
- Comments: 1

## Topic Body

- AWS **Aurora RDS**에서 발생한 **경쟁 상태 버그**를 실험적으로 확인하고 AWS로부터 원인 확인을 받은 사례  
- Hightouch는 **이벤트 처리 시스템 확장 중** Aurora의 **failover(장애 조치)** 과정에서 쓰기 인스턴스 전환이 실패하는 현상을 발견  
- 로그 분석 결과, **두 인스턴스가 동시에 쓰기 작업을 수행**해 스토리지 계층 충돌과 프로세스 종료가 발생한 것으로 확인  
- AWS는 **내부 신호 처리 문제**로 인해 이전 writer의 강등이 완료되지 않은 상태에서 새 writer가 승격된 것이 원인이라 공식 확인  
- 이 사례는 **대규모 분산 시스템에서의 동시성 제어 중요성**과, 장애 조치 시 **쓰기 중단 절차의 필요성**을 강조  

---

### 배경
- 2025년 10월 20일, AWS `us-east-1` 리전에 **DNS 관리 시스템의 경쟁 상태 버그**로 인한 장애 발생  
- Hightouch는 이로 인해 **이벤트 처리 백로그**가 급증해 시스템 한계에 도달  
- 처리량 확보를 위해 10월 23일 **Aurora RDS 인스턴스 업그레이드**를 진행했으며, 이 과정에서 새로운 경쟁 상태 버그를 발견  

### Hightouch 이벤트 시스템 구조
- 이벤트 수집 및 전송을 담당하는 시스템은 **Kubernetes**, **Kafka**, **Postgres(Aurora)** 로 구성  
- Postgres는 **배치 메타데이터 큐**로 사용되며, 초당 50만 건 이벤트를 1초 내 처리  
- Aurora PostgreSQL은 **쓰기 전용(primary)** 인스턴스와 **읽기 전용(replica)** 인스턴스, 그리고 **공유 스토리지 계층**으로 구성  

### 업그레이드 계획
- 읽기 인스턴스 추가 → 기존 리더 업그레이드 및 failover 우선순위 부여 → failover 실행 → 기존 writer 업그레이드 → 임시 리더 제거  
- 이 절차는 AWS 문서에 명시된 방식이며, **스테이징 환경에서 부하 테스트를 통해 검증된 절차**였음  

### 업그레이드 시도와 문제 발생
- 10월 23일 16:39 EDT, failover 실행 후 **기존 writer가 다시 primary로 복귀**하는 현상 발생  
- 두 차례 시도 모두 동일한 결과로, **쓰기 불가 오류(DatabaseError: cannot execute UPDATE in a read-only transaction)** 가 일부 서비스에서 발생  
- 로그 분석 결과, **두 인스턴스가 동시에 쓰기 작업을 수행하다 스토리지 충돌로 종료**된 로그 확인  

### 경쟁 상태의 원인
- Aurora의 failover 과정 중 **3단계(기존 writer 강등)와 4단계(새 writer 승격)** 사이에 **경쟁 상태 발생**  
- 이로 인해 두 인스턴스가 동시에 쓰기 권한을 가지며 충돌  
- 쓰기 트래픽을 제거한 상태에서 재시도하자 failover가 정상 완료되어 **경쟁 상태 가설이 입증**됨  

### AWS의 확인 및 대응
- AWS는 내부 검토 후, **writer 강등 신호 처리 오류**가 원인이며 Hightouch의 설정이나 트래픽 패턴과 무관하다고 확인  
- **수정이 로드맵에 포함**되어 있으며, 임시 대응책으로 **failover 중 쓰기 중단**을 권장  

### 최종 조치
- Hightouch는 클러스터 업그레이드를 완료하고,  
  - **의도적 failover 전 쓰기 중단 절차 추가**  
  - **writer 역할 변경 감시 모니터링 강화**  
  - **운영 매뉴얼(playbook) 업데이트**를 수행  

### 주요 교훈
1. **마이그레이션 중 예기치 않은 상태 전환**에 대비한 복구 준비 필요  
2. **관측성(observability)** 확보가 문제 탐지의 핵심  
3. **분산 시스템 구성요소 간 영향 최소화 설계**의 중요성  
4. **테스트 환경과 실제 운영 환경의 차이**를 인식해야 함  

원문에 추가 정보 없음

## Comments



### Comment 46361

- Author: neo
- Created: 2025-11-16T05:41:51+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=45929921) 
- 이 글을 보면 **수동 장애 조치(failover)** 중에도 애플리케이션이 평소처럼 쓰기 트래픽을 유지하려 하면 항상 실패하는 것처럼 보임  
  하지만 몇 가지 의문이 생김. 다른 Aurora 사용자들은 왜 이런 문제를 항상 겪지 않는지, AWS가 모를 리가 있는지, 만약 알고 있다면 왜 **P0급 긴급 이슈**로 다루지 않는지 궁금함  
  혹시 진행 중인 트랜잭션 상태나 타임아웃 같은 **미묘한 조건**이 작용하는 걸지도 모른다는 생각이 듦
  - Azure에서 비슷한 문제를 다뤄본 경험상, 많은 사람들이 겪지만 **재시작으로 해결되니** 그냥 넘어가는 경우가 많음. 근본 원인을 찾기 어렵고, 벤더와 함께 분석하는 과정이 너무 고통스러워서 대부분 포기함
  - 우리도 AWS와 협업하면서 같은 문제를 확인했음. 트래픽 패턴이 특별하지 않았고, 다른 리전에서는 재현되지 않았음. 이건 Aurora의 **근본적인 장애 조치 메커니즘 결함**일 가능성이 높음
  - 예전에 Python + MySQL 조합에서 `SELECT ... FOR UPDATE`가 조용히 실패하고 트랜잭션이 **autocommit 모드로 전환되는 버그**를 겪은 적이 있음. 아무도 관심을 안 가져서 혼자 떠들었는데, 몇 달 뒤 다른 사람도 같은 문제를 겪었다고 연락이 옴. 결국 수정되긴 했지만 이미 관심을 끊은 뒤였음  
    관련 링크: [Stack Overflow 질문](https://stackoverflow.com/questions/945482/why-doesnt-anyone-care-about-this-mysqldb-bug-is-it-a-bug)
  - AWS는 내부 정보를 거의 공개하지 않음. API 수준 이상의 세부 내용을 알려주지 않기 때문에, 이런 문제를 **희귀 케이스**로 치부하고 넘어가는 듯한 느낌을 받음
  - 문제의 일부는 애플리케이션이 **되돌려진 장애 조치(reverted failover)** 에 반응하는 방식 때문일 수도 있음. 캐시가 깨져 잘못된 프라이머리로 계속 쓰기를 시도한 듯함. 이런 실패가 종종 일어나도, 재시도하면 성공하니 사용자들이 AWS에 신고하지 않아 AWS가 인지하지 못했을 가능성도 있음

- Aurora PostgreSQL에서 **예상치 못한 동작**을 여러 번 봤음  
  특히 **Zero Downtime Patching(ZDP)** 중 세션 상태가 잘못 유지되어, 간단한 쿼리조차 `statement_timeout`보다 훨씬 빨리 취소되는 현상을 겪었음  
  내 추측으로는 클라이언트가 재연결될 때, Aurora가 이전 세션의 **오래된 타이머 상태**를 그대로 이어받아 쿼리가 즉시 취소되는 것 같음

- 우리도 쓰기 트래픽이 매우 높은 환경에서 정기적으로 장애 조치를 수행하지만, **AWS JDBC wrapper**를 사용해 자동화된 프로세스로 안정적으로 운영 중임  
  - 실제로는 Aurora의 **스토리지 계층이 ACID 위반을 막아줬음**, 즉 데이터 무결성은 지켜졌음

- Aurora가 이런 기본적인 불변성을 유지해줄 거라 믿고 돈을 내는 건데, 이런 문제가 생기다니 놀라움  
  - 하지만 스토리지 계층 자체는 **동시 쓰기를 차단**해 올바르게 동작했음

- 로그와 AWS의 설명을 보면, 원글 작성자의 가설은 틀린 듯함  
  **프로모션 실패 후 외부 감시 프로세스가 클러스터 상태 불일치를 감지하고 강제 종료(kill -9)** 한 것으로 보임. 스토리지 서브시스템 관련 메시지는 그 이후에 발생한 것임

- Aurora와 RDS Postgres의 **성능 비교**에 대해 묻고 싶음.  
  멀티 AZ나 빠른 장애 조치가 필요 없다면, RDS에서 **gp3 64k IOPS** 구성으로 더 나은 성능을 낼 수 있을까? Aurora는 특히 **insert 성능이 느리고 비용이 높아** 보임. 벤치마크들도 RDS 설정을 명확히 밝히지 않아 신뢰하기 어려움
  - 우리는 Aurora PG 14에서 **1 writer + 1~2 reader 구성**으로 더 나은 성능과 낮은 비용을 얻었음. Aurora는 인스턴스별이 아닌 **클러스터 단위 스토리지 과금**이라 유리함.  
    또한 IOPS를 직접 프로비저닝할 필요가 없고 약 **80k IOPS**를 제공함.  
    IO 과금 방식도 두 가지가 있는데, **pay-per-IO**는 저부하 환경에, **고정 요금 모드**는 IO가 많은 워크로드에 유리함.  
    참고로 **Serverless는 거의 항상 비경제적**이었음. 짧은 피크 타임이 있는 경우에만 유용함
  - 우리 팀은 Aurora Postgres RDS에서 **I/O 비용 폭증**을 겪었음. 단 몇 개의 fuzzy query로 월 $3,000 이상이 나왔고, 원래는 $100 이하였어야 했음
  - Aurora의 **비용, 성능, 지연시간** 모두 실망스러워 결국 **온프레미스 PostgreSQL**로 이전했음
  - Aurora MySQL 기준으로는, 같은 IOPS를 RDS에서 맞추려면 **훨씬 비싼 비용**이 들었음
  - Aurora는 EBS를 사용하지 않으며, **스토리지 타입이나 지연시간을 선택할 수 없음**. 단지 IO 과금 방식을 고를 수 있을 뿐임

- AWS 엔지니어들이 말하는 **“레고 블록 모델”** 이 잘 드러남  
  스토리지 계층을 완전히 독립적으로 설계해, 상위 서비스가 실패해도 **데이터 일관성**은 보장되었음. AWS 엔지니어링의 좋은 사례라고 생각함

- AWS가 “장애 조치 중에는 쓰기를 멈추라”는 권고를 했다고 하는데, **관련 케이스 번호**를 공유받을 수 있는지 궁금함  
  - 우리도 Aurora MySQL을 쓰고 있어서, 이 권고가 **MySQL에도 적용되는지** 확인하고 싶음

- 이런 문제를 겪은 게 나만이 아니라는 걸 알아서 다행임  
  - AWS Support는 처음엔 **복제 지연(replication lag)** 때문이라며 반박했지만, 24시간 전의 오래된 메트릭을 보고 판단했음. 어떤 실패를 겪었는지, 다른 리전에서는 왜 재현되지 않았는지 정말 알고 싶음

- Aurora의 **컴퓨트-스토리지 분리 아키텍처**가 흥미로움  
  MSSQL의 **Hyperscale**도 비슷한 구조인데, Azure 서비스 중 내가 실제로 써볼 만하다고 생각하는 거의 유일한 제품임
