
격리 수준 변경 대신 쿼리 쪼개기(Chunking)로 undo 로그 적체를 완벽히 진압한 실제 트러블슈팅 사례
아임웹 기술 블로그의 이 글은 Aurora MySQL 환경에서 963초 동안 실행된 단일 대형 쿼리로 인해 HLL(History List Length)이 205만까지 급증했던 장애 분석 및 해결 과정을 다룹니다. 단순 격리 수준 변경의 맹점과 Aurora의 공유 스토리지 구조가 purge 지연에 미치는 영향을 실험으로 밝혀내고, 애플리케이션 단의 청크 조회 방식으로 개선한 실전 노하우를 제공합니다.
대량의 배치를 처리하거나 무거운 조회용 쿼리를 운영 환경에서 실행해야 하는 백엔드 엔지니어 및 DBA에게 추천합니다. 격리 수준 변경에 따른 일관성 리스크를 섣불리 지기보다는, 쿼리를 청크 단위로 쪼개어 스냅샷 수명을 직접 제어하는 실용적인 우회책을 실무에 적용해 보십시오.
아임웹 운영 데이터베이스에서 단일 장기 실행 쿼리로 인해 HLL(History List Length) 지표가 임계값의 두 배를 초과한 205만까지 급증하는 알람이 발생하였습니다. 이는 Aurora MySQL의 MVCC 구조상 오래 유지된 스냅샷(Read View)이 커밋된 트랜잭션들의 undo log 정리를 지연시켰기 때문입니다.
대형 쿼리를 하나의 트랜잭션 내에서 한 번에 실행하는 대신, 기본 키(PK) 기준 1만 건 범위 단위로 쪼개서 조회하는 청크(Chunking) 방식을 도입하여 개별 스냅샷의 생명 주기를 극도로 단축시키고 무거운 부하는 Reader DB로 분산시켰습니다.
전체 배치의 안정성이 극대화되어 HLL 최고값이 11,813 수준에서 안정적으로 제어되었으며, 복제 지연(Replica Lag) 역시 최대 26ms 이내로 억제되었습니다.
Trade-off
배치 조회를 수천 개의 작은 쿼리로 분할 처리하고 메모리 상에서 데이터 중복을 병합하게 되면서, 전체 배치 작업 소요 시간은 기존 약 15분에서 45분으로 약 3배가량 늘어났습니다.
커밋되었으나 아직 정리(Purge)되지 않은 트랜잭션들의 Undo 로그 목록 길이를 의미합니다. 이 값이 비정상적으로 높으면 디스크 사용량 증가 및 Buffer Pool 압박, 인덱스 성능 저하 등을 유발합니다.
동시성 제어를 위해 데이터의 다중 버전을 관리하는 기술로, 쓰기 트랜잭션과 읽기 트랜잭션이 서로를 차단하지 않도록 보장합니다.
하나의 거대한 데이터 처리를 여러 개의 작은 트랜잭션 혹은 쿼리 단위로 쪼개어 순차적으로 수행하는 성능 최적화 기법입니다.