4장. 백그라운드 프로세스
여러분이 COMMIT을 누르는 순간, 디스크에 쓰이는 것은 데이터가 아니라 redo입니다 — 이 한 문장을 이해하면 Oracle의 쓰기 성능과 장애 복구가 한 줄로 꿰어집니다.
① 백그라운드 프로세스 전체 지도 — 누가 어디서 일하나 ② DBWn(게으른 기록)과 LGWR(커밋 시 동기 기록)의 역할 분담 ③ CKPT·SMON·PMON·ARCn·MMON의 임무 ④ 인스턴스 크래시에서 SMON이 데이터를 살려내는 과정
4.1 전체 지도 — 인스턴스를 움직이는 상근 직원들
서버 프로세스(3장)가 "손님(세션)을 응대하는 직원"이라면, 백그라운드 프로세스는 인스턴스가 기동될 때부터 종료될 때까지 각자 맡은 일만 반복하는 상근 직원들입니다. 서버 프로세스가 무거운 일(디스크 쓰기, 로그 관리, 청소)을 직접 하지 않고 이들에게 위임하기 때문에, 개별 쿼리가 빨라집니다.
먼저 전체 지도에서 일곱 주인공의 위치를 눈에 익히세요. 각 프로세스가 SGA의 어느 부분과 디스크의 어느 파일 사이에서 일하는지가 포인트입니다.
DBWn(Database Writer): 버퍼 캐시의 dirty buffer를 데이터파일에 기록합니다. 서두르지 않고 모아서 쓰는 "게으른 기록자"입니다.
LGWR(Log Writer): Redo Log Buffer의 redo entry를 온라인 리두 로그 파일에 씁니다. 커밋 순간만큼은 동기(synchronous)로 — 이 장의 주인공입니다.
CKPT(Checkpoint): 체크포인트 정보를 컨트롤파일과 데이터파일 헤더에 기록하고 DBWn에게 쓰기를 지시합니다. "여기까지는 디스크에 반영됨"이라는 책갈피 관리자입니다.
SMON(System Monitor): 크래시 후 재기동 시 인스턴스 복구를 수행하고, 쓰다 버려진 임시 세그먼트를 청소합니다.
PMON(Process Monitor): 비정상 종료된 프로세스의 뒷정리 — 잡고 있던 락을 풀고 세션 자원을 회수합니다.
ARCn(Archiver): 가득 찬 리두 로그를 아카이브 로그로 복사해 보존합니다(ARCHIVELOG 모드). MMON: AWR 성능 스냅샷을 주기적으로 저장합니다(12장). — 일곱 직원의 지도 완성!
현재 인스턴스에서 실제로 돌고 있는 백그라운드 프로세스는 이렇게 확인합니다.
-- 지금 떠 있는 백그라운드 프로세스 목록
SELECT name, description
FROM v$bgprocess
WHERE paddr <> '00' -- 실행 중인 것만
ORDER BY name;
NAME DESCRIPTION
---- ----------------------------------
CKPT checkpoint
DBW0 db writer process 0
LGWR Redo etc.
PMON process cleanup
SMON System Monitor Process
...
4.2 DBWn — 서두르지 않는 기록자
2장에서 봤듯 UPDATE는 버퍼 캐시만 고치고 끝납니다. dirty buffer를 데이터파일에 실제로 쓰는 것은 DBWn입니다(쓰기 부하가 크면 DBW0, DBW1…처럼 여러 개를 둘 수 있어 n이 붙습니다). DBWn이 움직이는 대표적인 계기는:
- 서버 프로세스가 빈 버퍼를 못 찾을 때 (자리를 만들어야 함)
- 체크포인트가 발생했을 때 (CKPT의 지시)
- 주기적인 한가한 시점의 정리
중요한 것은 DBWn은 커밋과 무관하게 움직인다는 사실입니다. 커밋 안 된 변경도 자리가 필요하면 디스크에 쓰고, 커밋된 변경도 한참 뒤에 쓸 수 있습니다. "그래도 괜찮은" 이유가 다음 절의 LGWR입니다.
4.3 LGWR — 커밋의 실체
커밋의 내구성(durability)을 책임지는 것은 LGWR입니다. 세션이 COMMIT을 실행하면, LGWR이 그 트랜잭션의 redo entry를 온라인 리두 로그 파일에 물리적으로 쓸 때까지 세션은 기다립니다(이 대기가 그 유명한 log file sync 대기 이벤트입니다). 기록이 끝나야 "커밋 완료" 응답이 나갑니다.
왜 데이터 블록 대신 redo를 쓸까요? redo는 로그 파일 끝에 이어 쓰는 순차 쓰기라서 작고 빠릅니다. 반면 데이터 블록은 파일 여기저기에 흩어진 랜덤 쓰기죠. "빠른 순차 쓰기로 안전을 확보하고, 느린 랜덤 쓰기는 나중에 몰아서" — 이것이 Oracle 쓰기 성능의 비밀이며, PostgreSQL의 WAL(pg 9장)과 동일한 설계입니다.
UPDATE 실행 직후의 상태입니다. 버퍼 캐시의 블록은 dirty(새 잔액), Redo Log Buffer에는 "무엇을 어떻게 바꿨는지"의 redo entry가 쌓였습니다. 디스크의 데이터파일은 아직 옛 잔액 그대로입니다.
세션이 COMMIT을 실행합니다. 이제 세션은 기다립니다 — 무엇을? 데이터파일 기록이 아니라 redo 기록을!
LGWR이 redo entry를 온라인 리두 로그 파일에 동기적으로 씁니다. 로그 끝에 이어 쓰는 순차 I/O라 매우 빠릅니다. 이 대기가 log file sync 이벤트입니다.
redo가 디스크에 안착하는 순간 커밋 완료! 주목 — 데이터파일에는 아직 새 값이 없습니다. 그래도 안전합니다. 지금 서버가 죽어도 redo만 있으면 변경을 재현할 수 있으니까요.
dirty 블록은 DBWn이 나중에 여유 있을 때 데이터파일에 씁니다. 정리: 커밋 시 디스크에 쓰는 것은 데이터가 아니라 redo다. LGWR은 단거리 주자, DBWn은 마라토너입니다.
"커밋 시 디스크에 쓰는 것은 데이터가 아니라 redo다." 커밋이 느리면 범인은 대부분 LGWR의 쓰기 경로(log file sync)이고, 데이터파일 I/O가 느린 것은 커밋 지연과 직접 관계가 없습니다. 루프 안에서 건건이 커밋하는 코드가 왜 느린지도 이 문장으로 설명됩니다 — 커밋마다 LGWR 동기 기록을 기다리기 때문입니다.
-- 커밋 대기(log file sync)가 얼마나 발생했는지
SELECT event, total_waits, time_waited_micro/1000000 AS sec
FROM v$system_event
WHERE event = 'log file sync';
EVENT TOTAL_WAITS SEC
-------------- ----------- ------
log file sync 9214432 518.3
4.4 CKPT — "여기까지는 반영됨" 책갈피
CKPT(Checkpoint Process)는 체크포인트 시점마다 컨트롤파일과 데이터파일 헤더에 체크포인트 위치를 기록하고, DBWn에게 dirty buffer 기록을 지시합니다. 체크포인트 위치는 "redo 스트림의 이 지점까지는 데이터파일에 반영 완료"라는 책갈피입니다.
이 책갈피의 존재 이유는 복구 시간 단축입니다. 크래시 후 복구할 때 redo 전체가 아니라 마지막 체크포인트 이후의 redo만 재생하면 되기 때문입니다. 책갈피가 자주 갱신될수록(체크포인트가 잦을수록) 복구는 빨라지지만 평상시 I/O 부담이 늘어나는 트레이드오프가 있습니다 — 7장에서 자세히 다룹니다.
4.5 SMON — 크래시에서 살려내는 복구 반장
SMON(System Monitor)의 대표 임무는 인스턴스 복구(instance recovery)입니다. 정전 등으로 인스턴스가 갑자기 죽으면 메모리(SGA)의 내용은 모두 증발합니다. 커밋됐지만 데이터파일에 아직 안 쓰인 변경(dirty buffer였던 것들)도 함께요. 재기동 시 SMON이 redo와 undo를 이용해 데이터베이스를 일관된 상태로 되돌립니다. 그 밖에 쓰다 버려진 임시 세그먼트 정리 같은 청소 업무도 SMON 담당입니다.
평상시 상태. TX1은 커밋됐지만 데이터파일엔 미반영(redo만 디스크에), TX2는 커밋 전인데 일부 블록이 DBWn에 의해 이미 디스크에 쓰였을 수 있습니다.
크래시! SGA가 증발하면서 디스크에는 "커밋됐는데 없는 변경"과 "커밋 안 됐는데 있는 변경"이 뒤섞인 불완전한 상태가 남습니다.
재기동하면 SMON이 자동으로 인스턴스 복구를 시작합니다. 컨트롤파일의 체크포인트 위치를 확인하고, 그 이후의 redo를 재생할 준비를 합니다.
Roll forward(전진 복구): redo를 순서대로 재생해 크래시 직전의 상태를 통째로 재현합니다. 커밋 여부는 아직 안 따집니다. 이 단계가 끝나면 DB를 열 수 있습니다.
Rollback(후진 복구): 커밋되지 않은 TX2의 변경을 undo(변경 전 값 보관소, 6장)로 되돌립니다. 결과: 커밋된 변경은 하나도 잃지 않고, 커밋 안 된 변경은 하나도 남지 않은 일관된 데이터베이스!
WAL 재생으로 크래시 복구를 하는 PostgreSQL의 리커버리(pg 9장)와 원리가 같습니다. 차이는 undo의 유무 — PG는 옛 버전이 테이블 안에 그대로 있어서(dead tuple) 별도 rollback 단계가 필요 없는 대신, Oracle은 undo를 적용하는 단계가 하나 더 있습니다.
4.6 나머지 상근 직원들 — PMON · ARCn · MMON
| 프로세스 | 이름 | 하는 일 | 없으면 생기는 일 |
|---|---|---|---|
PMON | Process Monitor | 비정상 종료된 프로세스의 뒷정리 — 잡고 있던 락 해제, 트랜잭션 정리, 세션 자원 회수 (19c에서는 CLMN 등 보조 프로세스와 분업) | 죽은 세션이 잡은 락에 다른 세션들이 영원히 대기 |
ARCn | Archiver | 가득 차서 교체된 온라인 리두 로그를 아카이브 위치로 복사 (ARCHIVELOG 모드) | 과거 redo 유실 → 시점 복구(PITR)·백업 복구 불가 |
MMON | Manageability Monitor | AWR 성능 스냅샷을 주기적으로(기본 1시간) SYSAUX에 저장, 메트릭 계산 | 성능 이력 없음 → "어제 왜 느렸지?"에 답 못 함 (12장) |
아카이브 저장 공간이 가득 차면 ARCn이 로그를 복사하지 못하고, 리두 로그를 재사용할 수 없게 된 LGWR이 멈추면서 DB 전체의 쓰기가 정지합니다. Oracle 운영의 고전적인 장애 시나리오이니, ARCHIVELOG 모드에서는 아카이브 공간 모니터링이 필수입니다.
✍️ 이해도 체크
Oracle Database 19c Concepts Guide — Process Architecture 장에서 각 백그라운드 프로세스의 공식 정의와 전체 목록(LREG, MMNL 등 조연들까지)을 확인할 수 있습니다.