비용절감을 위해서는 지속적인 비용 추이에 대한 모니터링이 중요합니다. 이번에는 갑자기 발생하게 된 데이터베이스 서버 비용을 모니터링하던 중 특이 지점을 발견하고 해결한 사례를 소개드립니다. 비용도 절감할 수 있었지만 데이터베이스 성능을 저하시키는 요소를 파악하고 재발방지도 할 수 있었습니다.
위 화면은 Aurora RDS의 특정 인스턴스 비용 추이 그래프입니다. 이를 보면 4월 22일에 약 $25의 비용이 갑자기 발생하고 있음을 알 수 있습니다.
해당 지표는 db.r6i.2xl 인스턴스의 데이터베이스 서버 사용량입니다. 사용량 대비 비용이 0이었던 것을 볼 수 있습니다. 비용이 이전에 없는 것은 RI(Reserved Instance)를 구매했기 때문입니다. RI로 구매한 경우 InstanceUsage가 아닌 HeavyUsage로 별도로 잡히게 됩니다.
보통 이런 경우는 Auto Scaling 정책에 의해서 서버가 늘어난 경우가 많은데요. 이번에도 마찬가지였습니다. 다만 저희가 사용하고 있던 Read Instance가 2대였음에도 클러스터 복제본의 최소 용량을 3으로 유지했기 때문에 늘어났던 서버가 줄어들지 않아서 계속 서버가 늘어난채로 유지되고 있었습니다.
먼저 최소 용량을 2로 조치하니 3대로 늘어났던 Read Instance 한대는 바로 삭제되었습니다. 그리고 Instance가 늘어났던 해당 시점을 보니 CPU 70%를 쳤던 지점이 있었네요. 저희가 Auto Scaling 정책을 CPU 70%로 걸어두었던 터라 바로 서버 한대가 증설되었던 것입니다.
해당 시점에 슬로쿼리가 상대적으로 더 많이 발생하였던 것을 파악할 수 있었습니다. 그리고 원인은 Write Instance에서 수행한 대량 DELETE 작업이었습니다.
Aurora MySQL 환경에서 슬로 쿼리와 대량 DELETE 작업이 겹쳤을 때 어떤 일이 일어날 수 있을까요?
이번 글에서는 실무에서 발생한 실제 사례를 바탕으로, 슬로 쿼리 분석 결과와 이를 유발한 DELETE 작업의 영향, 그리고 이 상황을 안정적으로 해결하기 위한 전략을 정리합니다. AWS Aurora를 운영 중이라면 반드시 참고해야 할 핵심 내용입니다.
2025년 4월 22일, Writer 인스턴스에서 auction_product 테이블을 대상으로 대량 DELETE 작업이 진행되었습니다. 이 작업은 단순한 데이터 정리가 목적이었지만, 이후 예상하지 못했던 문제가 발생했습니다. 바로, Reader 인스턴스에서 대규모 슬로 쿼리 로그가 쏟아지기 시작한 것입니다.
4월 22일과 23일의 슬로 쿼리 요약 비교는 아래와 같습니다.
쿼리 수는 23일이 더 많았지만, 성능 저하는 22일에 집중되어 있었습니다. 그 차이는 무엇이었을까요?
Aurora는 Writer와 Reader가 공통 스토리지를 사용합니다. Writer에서 DELETE가 발생하면 그 내용은 스토리지 레벨의 Undo/Redo를 통해 Reader에게도 전파됩니다. Reader는 Snapshot 일관성을 유지하기 위해 Undo log를 따라가며 과거 데이터를 복구해야 하죠.
이런 구조에서는 다음과 같은 문제가 발생합니다.
Undo chain이 길어지면 Reader CPU, IO 급증
SELECT 쿼리가 오래된 Snapshot을 필요로 할 경우 슬로 쿼리로 전환
경우에 따라 Metadata Lock으로 SELECT 쿼리가 대기 상태로 전환
특히 DELETE 대상이 Reader 쿼리에서 WHERE나 JOIN으로 자주 쓰이는 테이블일 경우, 그 영향은 극대화됩니다. 아래 조금 더 자세한 내용을 기술해보겠습니다.
Aurora 스토리지 구조
Aurora는 Writer와 Reader 인스턴스가 공통된 스토리지 계층을 사용합니다. 따라서 Writer에서 발생한 대량 DELETE 작업은 스토리지 레벨에서 Undo/Redo 전파를 유발합니다. Reader는 해당 영향을 받아 Snapshot 복구 및 Undo Page 처리로 인해 I/O 및 CPU 리소스를 더 많이 사용하게 됩니다.
MVCC 및 Undo 처리 비용
Aurora의 Multi-Version Concurrency Control(MVCC) 구조상, Reader는 과거 버전을 유지하기 위해 Undo log를 따라가야 합니다. 대량 DELETE 작업이 발생하면 Undo chain을 길게 만들면서 Reader의 부하가 커질 수 있습니다.
Metadata Lock 영향
분석된 쿼리 중 일부는 LOCK_TIME이 비정상적으로 긴 것으로 나타났으며, 이는 DELETE나 DDL 작업과 SELECT 쿼리가 충돌하면서 Metadata Lock 대기가 발생했을 가능성이 있습니다.
쿼리 실행 시간 최대 1772초 (약 30분)
rows_examined 2천만 이상
LOCK_TIME이 비정상적으로 긴 SELECT 쿼리 다수
Write 인스턴스에서 실행한 DELETE가 Reader의 성능을 실질적으로 끌어내리고 있었습니다.
방법 1: DELETE ... LIMIT 반복
작은 단위로 나누어 처리하면 Undo 부담이 줄고, 성능에도 긍정적인 영향을 줍니다.
방법 2: Bash 루프 활용
방법 3: pt-archiver (Percona Toolkit)
대량 DELETE에 가장 많이 사용되는 도구입니다.
이 방법을 사용하면 Aurora 내부 기능만으로도 무중단 DELETE가 가능합니다.
Aurora는 고가용성과 성능을 제공하는 클라우드 기반 RDBMS이지만, 그만큼 내부 구조에 대한 이해 없이 대량 작업을 실행하면 예기치 못한 성능 저하로 이어질 수 있습니다. 특히 Writer 인스턴스에서 발생한 대량 DELETE가 Reader 성능에 미치는 간접적 영향은 많은 운영 환경에서 간과되기 쉽습니다.
이번 사례를 통해 알 수 있었던 핵심은 다음과 같습니다.
대량 DELETE는 반드시 Chunk 단위로 점진적 처리되어야 하며, 가능한 경우 업무 시간 외 또는 저부하 시간에 진행하는 것이 좋습니다.
Writer의 DELETE는 Reader에 실질적인 영향을 미칠 수 있습니다.
pt-archiver, LIMIT 반복, Procedure 방식은 환경에 따라 전략적으로 선택 가능합니다. 핵심은 "트랜잭션 범위를 짧게 유지"하고 "한 번에 처리하는 양을 제한"하는 것입니다.
Performance Insights, CloudWatch 등을 통해 삭제 작업 중 Reader 상태를 지속적으로 모니터링해야 합니다.
FinOps 커뮤니티에 함께 하실래요?
저는 최근 48%, $36000의 AWS 비용절감을 달성했습니다.
클라우드 비용을 효율화하고 싶은 분들, 비슷한 고민을 나누고 싶다면 제가 운영 중인 AWS-FINOPS-KR Slack 커뮤니티에 참여하세요. 실제 절감 사례, 질문, 전략 공유를 나누실 수 있습니다.