#Backend

963초짜리 쿼리 하나가 HLL 205만까지 끌어올렸습니다

963초짜리 쿼리 하나가 HLL 205만까지 끌어올렸습니다
01

Summary

963초 동안 켜진 스냅샷 하나가 DB를 흔들 때: Aurora MySQL HLL 장애 해결기

격리 수준 변경 대신 쿼리 쪼개기(Chunking)로 undo 로그 적체를 완벽히 진압한 실제 트러블슈팅 사례

아임웹 기술 블로그의 이 글은 Aurora MySQL 환경에서 963초 동안 실행된 단일 대형 쿼리로 인해 HLL(History List Length)이 205만까지 급증했던 장애 분석 및 해결 과정을 다룹니다. 단순 격리 수준 변경의 맹점과 Aurora의 공유 스토리지 구조가 purge 지연에 미치는 영향을 실험으로 밝혀내고, 애플리케이션 단의 청크 조회 방식으로 개선한 실전 노하우를 제공합니다.

  • 01HLL 급증의 주원인이 격리 수준(Isolation Level) 자체가 아닌, 단일 스냅샷(Read View)의 과도한 수명 때문임을 실험을 통해 규명
  • 02Aurora MySQL 환경에서 Reader의 장기 조회가 공유 스토리지를 통해 Writer의 undo log purge를 가로막는 메커니즘 분석
  • 03aurora_read_replica_read_committed(ARRRC) 설정 도입 시 발생할 수 있는 데이터 일관성 파괴(흔들림) 현상 경고
  • 04대규모 단일 조회를 기본 키(PK) 기준 1만 건 단위의 청크(Chunking)로 분할하여 개별 스냅샷의 유지 시간을 최소화
  • 05배치 전체 소요 시간은 증가했으나 HLL 임계값을 안정적으로 방어하여 시스템 장애 가능성을 원천 차단

RECOMMENDATION

대량의 배치를 처리하거나 무거운 조회용 쿼리를 운영 환경에서 실행해야 하는 백엔드 엔지니어 및 DBA에게 추천합니다. 격리 수준 변경에 따른 일관성 리스크를 섣불리 지기보다는, 쿼리를 청크 단위로 쪼개어 스냅샷 수명을 직접 제어하는 실용적인 우회책을 실무에 적용해 보십시오.

The Problem

아임웹 운영 데이터베이스에서 단일 장기 실행 쿼리로 인해 HLL(History List Length) 지표가 임계값의 두 배를 초과한 205만까지 급증하는 알람이 발생하였습니다. 이는 Aurora MySQL의 MVCC 구조상 오래 유지된 스냅샷(Read View)이 커밋된 트랜잭션들의 undo log 정리를 지연시켰기 때문입니다.

The Solution

대형 쿼리를 하나의 트랜잭션 내에서 한 번에 실행하는 대신, 기본 키(PK) 기준 1만 건 범위 단위로 쪼개서 조회하는 청크(Chunking) 방식을 도입하여 개별 스냅샷의 생명 주기를 극도로 단축시키고 무거운 부하는 Reader DB로 분산시켰습니다.

The Result

전체 배치의 안정성이 극대화되어 HLL 최고값이 11,813 수준에서 안정적으로 제어되었으며, 복제 지연(Replica Lag) 역시 최대 26ms 이내로 억제되었습니다.

Trade-off

배치 조회를 수천 개의 작은 쿼리로 분할 처리하고 메모리 상에서 데이터 중복을 병합하게 되면서, 전체 배치 작업 소요 시간은 기존 약 15분에서 45분으로 약 3배가량 늘어났습니다.

03

Key Concepts

Concept · 01

HLL (History List Length)

커밋되었으나 아직 정리(Purge)되지 않은 트랜잭션들의 Undo 로그 목록 길이를 의미합니다. 이 값이 비정상적으로 높으면 디스크 사용량 증가 및 Buffer Pool 압박, 인덱스 성능 저하 등을 유발합니다.

  • 아임웹 메인 DB에서 특정 장기 조회 쿼리로 인해 평소 5천 선에서 관리되던 HLL이 205만 이상으로 폭증했습니다.
Concept · 02

MVCC (Multi-Version Concurrency Control)

동시성 제어를 위해 데이터의 다중 버전을 관리하는 기술로, 쓰기 트랜잭션과 읽기 트랜잭션이 서로를 차단하지 않도록 보장합니다.

  • InnoDB는 MVCC 구현을 위해 변경 전 데이터를 Undo 로그에 남겨 각 트랜잭션이 해당 시점의 Read View를 보도록 제어합니다.
Concept · 03

Chunking

하나의 거대한 데이터 처리를 여러 개의 작은 트랜잭션 혹은 쿼리 단위로 쪼개어 순차적으로 수행하는 성능 최적화 기법입니다.

  • 963초 동안 실행되는 단일 SELECT DISTINCT 쿼리를 PK 기준 1만 건 단위의 청크 쿼리들로 쪼개어 개별 스냅샷의 수명을 단축시켰습니다.