12장. AWR과 대기 이벤트 — 모니터링
"DB가 느려요"라는 신고 앞에서 감으로 헤매지 않는 방법 — Oracle은 모든 기다림을 이름 붙여 기록합니다. 그 기록을 읽는 법을 배웁니다.
① 대기 이벤트(wait event)라는 진단 언어와 대표 이벤트 5종 ② v$session·v$sql·ASH로 "지금"을 보는 법 ③ AWR 스냅샷 원리와 리포트 읽는 순서 ④ ADDM·Statspack까지, 상황별 도구 선택
12.1 대기 이벤트 — Oracle의 진단 언어
세션은 CPU에서 일하고 있거나, 무언가를 기다리고 있거나 둘 중 하나입니다. Oracle은 기다림의 종류마다 이름을 붙여 놓았습니다 — 이것이 대기 이벤트(wait event)입니다. "느리다"는 막연한 증상이 대기 이벤트를 보는 순간 "디스크 I/O를 기다린다", "락을 기다린다", "커밋 기록을 기다린다"라는 구체적인 병목 유형으로 번역됩니다.
현장에서 만나는 빈도순으로, 이 다섯 개만 외워도 절반은 해결됩니다.
| 대기 이벤트 | 뜻 | 전형적 원인 |
|---|---|---|
db file sequential read | 싱글 블록 디스크 읽기 (이름과 달리 주로 인덱스 경유 접근) | 인덱스 스캔 + 테이블 랜덤 접근이 많음. 과하면 나쁜 CF·비효율 인덱스 의심 |
db file scattered read | 멀티 블록 읽기를 버퍼 캐시 여기저기(scattered)에 적재 | Full Table Scan / Index Fast Full Scan — 풀스캔이 많다는 신호 |
log file sync | 커밋 후 LGWR가 redo를 디스크에 쓸 때까지 대기 | 커밋이 너무 잦음(루프 내 건별 커밋), redo 디스크가 느림 |
buffer busy waits | 같은 버퍼 블록을 두고 세션들이 경합 | 특정 블록에 삽입/변경 집중 (예: 시퀀스 PK 인덱스의 오른쪽 끝 블록) |
enq: TX - row lock contention | 다른 트랜잭션이 잡은 행 락을 대기 | 커밋하지 않는 긴 트랜잭션, 같은 행 동시 갱신 (8장 참고) |
신고가 들어옵니다. "느려요"만으로는 CPU 문제인지, I/O인지, 락인지 알 수 없습니다. 감으로 재시작부터 하면 안 됩니다.
v$session에서 해당 세션의 event 컬럼을 봅니다. Oracle이 "이 세션은 지금 이걸 기다리는 중"이라고 실시간으로 알려줍니다.
이벤트 이름이 곧 분기점입니다. sequential read면 인덱스 I/O, scattered read면 풀스캔, enq: TX면 락 경합. 이번 사례는 scattered read = 풀스캔 다발입니다.
세션의 sql_id로 v$sql을 조회해 문제 SQL의 전문과 통계를 확보합니다. 파티션 키를 가공한 쿼리가 전체 스캔을 돌리고 있었네요.
실행계획으로 확정하고 SQL을 수정하면 대기 이벤트가 사라집니다. 증상 → 이벤트 → SQL → 계획 → 수정. 이 5단계가 Oracle 성능 진단의 표준 동선입니다.
12.2 "지금"을 보는 창 — v$session, v$sql, ASH
실시간 진단의 3종 세트입니다. v$로 시작하는 뷰들은 SGA의 현재 상태를 보여주는 동적 성능 뷰입니다.
-- ① 지금 활동 중인 세션은 무엇을 기다리나
SELECT sid, serial#, username, sql_id, event, state,
seconds_in_wait, blocking_session
FROM v$session
WHERE status = 'ACTIVE' AND username IS NOT NULL;
-- ② 그 세션이 돌리는 SQL의 정체 (sql_id로 조인)
SELECT sql_id, executions, elapsed_time/1e6 AS elapsed_sec,
buffer_gets, disk_reads, sql_text
FROM v$sql
WHERE sql_id = '&sql_id';
순간을 보는 v$session의 약점은 "아까 무슨 일이 있었는지"를 모른다는 것. 그래서 Oracle은 ASH(Active Session History, v$active_session_history)를 둡니다 — 1초마다 모든 활성 세션의 스냅샷을 메모리 버퍼에 기록해 두는 블랙박스입니다. "10분 전 그 순간, 누가 무엇을 기다렸나"를 SQL로 되감아 볼 수 있습니다.
-- 최근 10분간 대기 이벤트 상위 집계 (ASH)
SELECT event, COUNT(*) AS samples -- 샘플 수 ≈ 소요 시간(초)
FROM v$active_session_history
WHERE sample_time > SYSDATE - 10/1440
GROUP BY event ORDER BY samples DESC;
ASH·AWR·ADDM은 Enterprise Edition + Diagnostics Pack 라이선스가 있어야 사용할 수 있습니다. v$active_session_history를 조회하는 것만으로도 팩 사용으로 간주됩니다. 라이선스가 없다면 12.5절의 Statspack이 대안입니다.
12.3 AWR — 성능의 건강검진 기록부
AWR(Automatic Workload Repository)은 인스턴스의 성능 통계를 주기적으로 스냅샷으로 찍어 SYSAUX 테이블스페이스에 보관하는 저장소입니다. 기본 설정은 1시간 간격 스냅샷, 8일 보관이며 MMON 백그라운드 프로세스가 수행합니다. 리포트는 "두 스냅샷 사이의 차이"로 만들어집니다.
MMON이 기본 1시간마다 성능 통계 스냅샷을 찍어 SYSAUX에 저장합니다(기본 8일 보관). 이 축적이 AWR입니다.
11:20부터 12:40까지 장애가 있었다고 합시다. 이미 지나간 일이지만 스냅샷들 사이에 흔적이 남아 있습니다.
장애 구간을 감싸는 두 스냅샷(11:00, 13:00)을 고릅니다. 리포트는 두 시점의 누적 카운터 차이이므로, 구간을 너무 넓게 잡으면 정상 시간대에 희석되어 문제가 흐려집니다.
awrrpt.sql 스크립트로 리포트를 생성합니다. 평상시 리포트를 하나 보관해 두면 "장애 때 vs 평소"의 비교가 가능해져 진단이 훨씬 빨라집니다.
리포트 읽는 순서 — 위에서 아래로 좁혀가기
- Top 10 Foreground Events by Total Wait Time — DB Time을 무엇이 먹었나. CPU가 상위인 것은 정상일 수 있고, I/O·락 이벤트가 상위면 그것이 병목 유형입니다.
- SQL ordered by Elapsed Time / Gets / Reads — 병목 유형을 만든 구체적인 SQL을 찾습니다. 보통 상위 몇 개가 전체의 대부분을 차지합니다.
- 해당 SQL의 실행계획(
DBMS_XPLAN.DISPLAY_AWR또는 DISPLAY_CURSOR)으로 내려가 원인을 확정합니다.
AWR의 핵심 지표 DB Time = 모든 세션이 DB에서 소비한 시간(CPU + 대기)의 총합입니다. 진단이란 결국 "DB Time이라는 물통을 어떤 이벤트가, 어떤 SQL이 채웠는가"를 추적하는 일입니다. Top Events에서 유형을, SQL ordered by에서 범인을 찾는 순서가 그래서 성립합니다.
12.4 사례 연구 — log file sync 급증
가장 교육적인 단골 사례로 흐름을 연습해 봅시다. 어느 날 오후, 갑자기 모든 화면의 저장 버튼이 느려졌습니다.
평소의 커밋: 세션이 COMMIT을 치면 LGWR가 redo 버퍼를 디스크에 기록하고, 완료 신호를 받을 때까지 잠깐(log file sync) 기다립니다. 보통 1ms 미만 — 존재감이 없습니다.
새 배치가 배포됐습니다. 루프 안에서 건별 COMMIT — 50만 건이면 커밋 50만 번입니다.
커밋마다 LGWR의 디스크 기록 완료를 기다려야 하므로 log file sync가 폭증하고, LGWR가 바빠지니 다른 세션의 평범한 커밋까지 줄을 서게 됩니다. 전사적으로 "저장이 느려요"가 터지는 이유입니다.
AWR/ASH에서 log file sync 1위 + user commits 급증을 확인하면 진단 끝. 처방은 루프 밖 배치 커밋입니다. 커밋 횟수는 정상인데 log file sync가 느리다면 그때는 redo 스토리지 성능을 봅니다.
12.5 도구 정리 — ADDM과 Statspack까지
| 도구 | 보는 것 | 언제 쓰나 | 라이선스 |
|---|---|---|---|
v$session | 지금 이 순간의 세션 상태 | 실시간 장애 대응 첫 조회 | 기본 포함 |
v$sql | 공유 풀의 SQL별 누적 통계 | 무거운 SQL Top-N 추출 | 기본 포함 |
| ASH | 1초 단위 활성 세션 이력 | "몇 분 전 순간"의 정밀 분석 | Diagnostics Pack |
| AWR | 시간 단위 스냅샷 리포트 | 구간 비교·사후 분석·추세 | Diagnostics Pack |
| ADDM | AWR을 분석한 자동 진단 보고서 | 스냅샷 생성 시 자동 실행 — 권고사항 훑어보기용 | Diagnostics Pack |
| Statspack | AWR의 전신 격 수동 스냅샷 도구 | Standard Edition 등 팩 라이선스가 없을 때의 무료 대안 | 기본 포함(수동 설치) |
ADDM(Automatic Database Diagnostic Monitor)은 AWR 스냅샷이 생성될 때마다 자동으로 돌면서 "이 구간의 DB Time을 가장 많이 잡아먹은 원인과 권고"를 문장으로 뽑아줍니다. 권고를 맹신하기보다 분석의 출발점으로 삼는 것이 좋습니다. Statspack은 스냅샷을 수동(또는 잡 스케줄)으로 찍고 spreport.sql로 리포트를 만드는 무료 도구로, 리포트 구조와 읽는 순서는 AWR과 유사합니다.
PG의 pg_stat_activity(wait_event 컬럼)가 v$session, pg_stat_statements가 v$sql에 해당합니다(PG 14장 모니터링). 반면 ASH·AWR처럼 이력을 자동 축적하는 내장 장치는 PG 본체에 없어서 별도 확장/외부 도구로 보완합니다 — Oracle 모니터링 스택의 완성도가 돋보이는 지점입니다.
✍️ 이해도 체크
db file scattered read가 Top Events 1위였습니다. 다음으로 봐야 할 곳과 그 이유는?Oracle Database 19c 공식 문서: Performance Tuning Guide — Gathering Database Statistics (AWR), Instance Tuning Using Performance Views (대기 이벤트)