IL-0450 Toss Securities · 2026-10-19 (게시일)database
주문과 체결 API 뒤의 Oracle RAC 에서 커밋이 log file sync 대기로 0.1초 넘게 밀리는 일이 반복됐다
토스증권의 주문과 체결 API 뒤에는 2노드 Oracle RAC 가 있다. 어느 날부터 이 DB 에서 log file sync 대기가 0.1초 넘게 이어지는 일이 반복됐다. Oracle 의 커밋은 LGWR 라는 백그라운드 프로세스가 리두 로그를 디스크에 기록한 뒤에야 끝나므로, LGWR 가 밀리면 그사이 커밋한 세션이 모두 기다리고 API 응답도 늦어졌다. 팀은 스토리지, OS, 네트워크, 애플리케이션, Oracle 을 하나씩 살폈지만 평균 지표에서는 이상을 찾지 못했다.
pidstat 으로 추적하자 지연은 LGWR 가 28번 CPU 에서 실행될 때만 생겼다. 이 서버는 CPU 소켓 4개에 소켓당 물리 코어 8개이고 하이퍼스레딩으로 논리 CPU 64개가 보이며, 소켓마다 NUMA 노드 하나를 이룬다. NIC 포트는 꽂힌 슬롯에 따라 특정 소켓 하나에 연결된다. RAC 인터커넥트용 NIC 2장은 Active-Standby 본딩으로 묶여 있었고, 평소에는 활성 포트 하나만 트래픽을 받았다. 인터커넥트는 두 노드가 캐시 블록을 주고받는 경로로, 클러스터에서 가장 바쁘다. 이 경로의 인터럽트가 모두 소켓 하나의 코어 8개에 몰렸다. NIC 인터럽트는 일반 프로세스보다 먼저 처리된다. 그래서 LGWR 가 이 코어에서 돌던 중에 패킷이 도착하면 커널이 LGWR 를 멈추고 인터럽트부터 처리했고, 그만큼 리두 로그 기록이 늦어졌다. 한 번 밀리는 시간은 아주 짧았지만 트래픽이 몰리는 구간에는 이 일이 계속 반복돼 커밋 대기가 눈에 띄게 길어졌다.
irqbalance 는 NIC 큐와 CPU 의 매핑 제약 때문에 이 장비에 적용되지 않았다. taskset 으로 LGWR 를 고정하는 방법은 기동할 때마다 손으로 설정해야 해서 택하지 않았다. 대신 팀은 인터커넥트 NIC 2장을 각각 다른 소켓에 연결된 슬롯에 다시 꽂고, 본딩을 Active-Active 로 바꿨다. 같은 피크 시간대에 초당 1,000건 넘게 인터럽트를 처리하는 물리 코어가 8개에서 15개로 늘었고, 인터럽트가 몇몇 코어에 얼마나 몰렸는지를 나타내는 Gini 계수는 0.80에서 0.67로 내려갔다. 처음에 문제가 된 0.1초 이상의 log file sync 대기도 대부분 좋아졌다. 같은 조치를 한 다른 RAC 에서는 동시접속자가 28% 많은 날에도 개장 후 첫 10분 평균 CPU 사용률이 36.6%에서 17.4%로 내려갔다. 팀은 그 뒤 운영 중인 Oracle DB 서버 전체에 같은 조치를 적용했다.
- 심각도
- –
- 영향 범위
- Commits on the Oracle RAC database behind the order and execution APIs repeatedly waited over 0.1 s on log file sync, delaying API responses
- 영향 사용자
- –
- 지역
- –
- 감지까지
- –
- 복구까지
- –
증상
주문과 체결을 처리하는 API 뒤의 Oracle RAC 에서 커밋 대기가 0.1초 넘게 이어지는 일이 반복해서 나타났다. 커밋이 밀리면 그 커밋을 기다리던 세션이 모두 함께 멈췄고 API 응답도 그만큼 늦어졌다.
지연은 Oracle 의 log file sync 대기 이벤트에 잡혔다. log file sync 는 세션이 LGWR 가 리두 로그를 디스크에 다 쓸 때까지 기다리는 시간이다. 인스턴스의 커밋 기록은 모두 LGWR 한 프로세스를 거치므로, LGWR 가 잠깐만 밀려도 그사이 커밋한 세션이 전부 기다렸다.
팀은 스토리지부터 OS, 네트워크, 애플리케이션, Oracle 까지 하나씩 살폈다. 평균 지표는 어디서나 정상 범위였고 호스트 CPU 도 남아 있었다. 팀은 지연이 간헐적이라 평균에 묻혔을 수 있다고 보고 LGWR 프로세스를 더 잘게 들여다봤다.
pidstat 으로 LGWR 가 실행되는 CPU 를 기록하자 지연은 LGWR 가 28번 CPU 에서 실행될 때만 생겼다. /proc/interrupts 를 30초 간격으로 두 번 읽어 차이를 보니 NIC 인터럽트가 물리 코어 32개 중 8개, 논리 CPU 로는 64개 중 16개에만 몰려 있었다. 그 물리 코어 8개는 정확히 CPU 소켓 하나 분량이었고, 28번 CPU 도 인터럽트를 전담하던 코어 중 하나였다.
팀은 먼저 irqbalance 로 인터럽트를 다시 나누려 했다. 하지만 이 장비에서는 NIC 큐와 CPU 의 매핑 제약 때문에 설정이 적용되지 않았고, 인터럽트는 계속 같은 코어에 몰렸다. taskset 으로 LGWR 를 다른 소켓의 CPU 에 고정하는 방법도 검토했다. 그러나 Oracle 을 기동할 때마다 손으로 설정해야 해서 운영 중에 빠뜨리기 쉽다고 보고 쓰지 않았다.
증상 지연 시간 증가
원인
- 촉발
- –
감지
DBA 팀이 Oracle 의 log file sync 대기 이벤트에서 커밋이 0.1초 넘게 기다리는 일이 되풀이되는 것을 보고 알아챘다.
조치
- 인터커넥트 NIC 2장을 각각 다른 CPU 소켓에 연결된 슬롯으로 옮겨 꽂았다. 본딩도 Active-Standby 에서 Active-Active 로 바꿔 평소에도 두 포트가 함께 트래픽을 받게 했다.
- 운영 중인 Oracle DB 서버 전체로 같은 조치를 넓혔다.
후속 조치
–
교훈
평균 지표만 보면 코어 하나에 걸린 병목을 놓친다. 호스트 CPU 가 80% 비어 있어도 어떤 코어는 쉴 틈이 없을 수 있다. 지연이 간헐적으로 나면 pidstat -t -p <pid> 1 로 그 프로세스가 어느 CPU 에서 도는지까지 본다. 장치별 인터럽트가 어느 코어에 몰리는지는 /proc/interrupts 를 일정한 간격으로 두 번 읽어 그 차이를 구하면 바로 드러난다.
슬롯 배치도 성능 설계의 일부다. 다중 소켓 서버에서 NIC 와 HBA 포트는 특정 NUMA 노드에 연결되므로, 장비를 도입하거나 증설할 때는 소켓이 고르게 나뉘도록 꽂을 슬롯을 고른다. Active-Standby 본딩은 이중화를 해 주지만, 평소에는 트래픽과 인터럽트를 포트 하나에 모두 싣는다. 핵심 트래픽이 지나는 경로에는 Active-Active 구성과 소켓을 나눈 장착을 함께 검토한다. irqbalance 는 장비와 드라이버에 따라 인터럽트를 다시 나누지 못할 수 있으므로, 먼저 하드웨어와 드라이버의 제약을 확인한다.
출처
관련 사례
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0288CDN77 의 ClickHouse 데이터 파이프라인에서 이중화된 인스턴스 세 곳의 ZooKeeperWait 가 수천 초로 치솟아 복제가 한 시간 넘게 느려졌다CDN77 · 2026같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0305Intercom 의 PlanetScale 샤드 하나에서 복제본이 CPU 100% 로 주 데이터베이스를 따라가지 못해 받은편지함에 최대 2.2시간 전의 데이터가 보였다Intercom · 2026같은 원인 · 공통 데이터베이스
IL-0390PostHog US Cloud 의 Persons Postgres 데이터베이스 쓰기가 크게 느려져 이벤트와 persons 수집이 최대 2일 지연됐다PostHog · 2025같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0287Atlas 와 Cloud Manager 의 모니터링을 받치는 내부 데이터베이스 클러스터의 샤드 하나가 과부하되어 지표 수집과 클러스터 작업이 늦어졌다MongoDB · 2025같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0298Wikimedia sessionstore 의 Cassandra 노드가 디스크가 가득 차 잇따라 죽고 쿼럼을 잃어 편집이 실패했다Wikimedia Foundation · 2025같은 원인 · 공통 데이터베이스
IL-0312max_connections 를 올리려고 재시작한 주 PostgreSQL 데이터베이스가 다시 올라오지 않아 Gadget 의 모든 앱 요청이 멈췄다Gadget · 2024같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0110Grafana Agent 파드가 메모리를 많이 쓰던 노드에 Hangfire 파드가 함께 올라가 시스템 OOM 으로 CrashLoopBackOff 를 반복했고, 노드가 응답을 멈추고 NotReady 가 됐다.DFDS · 2024같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0202갑자기 몰린 쿼리와 데이터베이스 쓰기로 Honeycomb 수집 호스트가 메모리 부족으로 죽었고, 쿠버네티스 CrashLoopBackOff 가 용량 회복을 막아 US1 이벤트 수집이 한 시간 넘게 불안정했다Honeycomb · 2023 · sev1같은 원인 · 공통 데이터베이스
IL-0386Google Cloud 로 옮긴 뒤 GKE 노드에서 Postgres 연결 타임아웃과 memcached i/o timeout 이 간헐적으로 튀었다incident.io · 2023같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0206GKE 파드 안의 Consul 에이전트가 메모리 급증으로 거듭 OOM kill 되어 Rails 파드가 데이터베이스 복제본을 찾지 못했고, 모든 쿼리가 primary 로 몰려 GitLab.com 이 느려졌다.GitLab · 2022같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0496전역 복제 Cassandra 클러스터에서 모든 리전의 인스턴스 CPU 가 100% 로 치솟아 쿼리가 타임아웃됐고, 같은 부하가 이틀 저녁 더 찾아왔다Ably · 2020같은 원인 · 공통 데이터베이스
IL-0443Aurora MySQL reader 가 이유 없이 재시작한 뒤 writer 의 insert latency 가 7배쯤 오르고 replication lag 가 하루 넘게 이어졌다Repro · 2019같은 원인 · 공통 데이터베이스
IL-0037imagePullPolicy가 Always인 DaemonSet이 크래시 루프를 돌며 이미지를 계속 받아, NAT 세 대를 같이 쓰던 리전 전체가 이미지 레지스트리에서 429로 막혔다Datadog · 2019같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0211Mandrill 의 PostgreSQL 샤드 하나가 트랜잭션 ID 랩어라운드를 막으려고 쓰기를 멈춰 약 40시간 동안 메일 발송이 줄었다Mailchimp · 2019같은 원인 · 공통 데이터베이스
IL-0064CPU 를 많이 쓰는 파드가 Google Cloud 노드 하나에 몰려 노드가 커널 패닉으로 죽었고, 다시 배치된 파드가 다음 노드를 또 죽이며 웹사이트와 API 가 멈췄다.Moonlight · 2019같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
IL-0334RDS MySQL 의 bookmarks 테이블이 2TB 파일 크기 한도에 닿아 INSERT 가 실패하고 Instapaper 가 31시간 동안 멈췄다Instapaper · 2017같은 원인 · 공통 데이터베이스
IL-0333사양을 낮춘 RDS PostgreSQL 인스턴스가 피크 부하를 못 버텨 헬스 체크가 실패하고 Buildkite 대시보드가 몇 시간 동안 내려갔다Buildkite · 2016같은 원인 · 공통 데이터베이스
IL-0282US-East 리전의 DynamoDB 스토리지 서버들이 멤버십 정보를 받지 못해 스스로 요청 처리에서 빠지면서 고객 요청의 약 55% 가 실패했다Amazon Web Services · 2015같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0450
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0450/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.