SQL) 데이터베이스 아키텍쳐 Ⅴ

jinsung·2025년 12월 3일

SQL

목록 보기
12/46
post-thumbnail

10. 대기 이벤트

대기 이벤트가 뭔데?

오라클 인스턴스는 많은 프로세스(또는 쓰레드)들이 역할을 분담해서 각자 맡은 바 임무를 수행한다. 함께 일을 하는 동안 프로세스 간 커뮤니케이션과 상호작용이 필요하고 때로는 다른 프로세스가 일을 마칠 때까지 기다려야만 하는 상황이 자주 발생한다. 그러면 오라클 프로세스는 일을 계속 진행할 수 있는 조건이 충족 될 때까지 수면상태에 빠지는데, 이를 대기 이벤트라고 한다. 대기 이벤트가 발생할 때마다 오라클은 그 상태정보를 파일 또는 SGA에 메모리 내에 저장한다.
대기 이벤트를 시스템 커널 레벨에서 설명하면, 프로세스가 할 일을 모두 마쳤거나 다른 프로세스를 기다려야 하는 상황에서 CPU를 쥔 채 대기하면 불필요하게 CPU 자원을 낭비하는 것이므로 CPU를 OS에 반환하고 수면 상태에 빠지는 것을 말한다.

  1. 일이 없는 프로세스가 CPU를 OS에 반환하고 수면상태로 빠짐
    -> 그 프로세스는 wait queue로 옮김

  2. OS는 wait queue에 있는 프로세스를 스케쥴링 대상에서 제외 시킨다

  3. 선행 프로세스가 일을 마치면 OS에게 그 사실을 알려 자신을 기다리던 수면 상태의 프로세스를 깨우도록 신호를 보냄

  4. OS는 그 프로세스를 runnable queue에 옮겨 CPU를 할당시켜 일을 재개할 수 있도록 스케쥴링한다.


대기 이벤트는 언제 발생 하는데?

다른 프로세스가 일을 끝 마치기를 기다릴 때 발생하는 대기 이벤트가 지속적으로 많이 발생하면 데이터베이스에 병목이 있음을 알리는 신호지만 모든 대기 이벤트가 그렇지만은 않다. 서버 프로세스가 사용자의 명령이나 신호를 기다릴 때 나타나는 대기 이벤트나 서버 프로세스가 할 일이 없기 때문에 발생하는 대기 이벤트들은 idle 대기 이벤트이기 때문에 데이터베이스 튜닝 시 무시해도 된다.
그렇다면 대기 이벤트는 언제 발생할까??

1. 자신이 필요로 하는 특정 리소스가 다른 프로세스에 의해 사용 중 일 때

  • 자신이 읽으려는 버퍼에 다른 프로세스가 쓰기 작업을 진행 중이라면 선행 프로세스가 일을 마칠 때까지 기다려야 한다.
  • buffer busy waits, latch free, enqueue 등 대기 이벤트

2. 다른 프로세스에 의해 선행 작업이 완료되기를 기다릴 때

  • 예를 들어, DBWR가 Dirty 버퍼를 디스크에 기록할 때는 먼저 LGWR가 로그 버퍼에 있는 Redo entry를 Redo Log 파일에 기록하는 작업이 선행돼야 한다.
  • write complete, checkpoint completed, log file sync, log file switch 등

3. 할 일이 없을 때 (= idle 대기 이벤트)

  • 예를 들어, 병렬 쿼리를 수행하면 자신이 맡은 일을 먼저 끝마치는 병렬 Slave 프로세스가 생기는데 그럴 때면 다른 Slave들이 일을 마칠 때까지 대기 상태에서 기다린다.
  • SQL *Net message from client, PX Deq: Execution Mag 등

그러면 대기 이벤트는 언제 종료 돼?

대기 이벤트가 발생한 오라클 프로세스들은 타임아웃을 설정하고 수면 상태에 들어간다. 만약 선행 프로세스가 자신을 깨우지 않더라도 타임아웃에 설정된 시간이 도래할 때마다 자신이 기다리던 리소스가 사용 가능해졌거나 해야 할 일이 생겼는지 확인한다. 타임아웃 값은 대기 이벤트 마다 모두 다르다. 예를 들어 log file sync는 1초, buffer busy wait는 3초이다.
대기가 자주 발생하는 것도 문제지만 타임아웃이 자주 발생한다면 대기 이벤트에 의한 지연 시간이 길어지는 것이므로 큰 문제가 된다.

대기 중인 프로세스가 활동을 재개하는 시점은 언제일까?

1. 대기 상태에 빠진 프로세스가 기다리던 리소스가 사용 가능해짐
2. 작업을 계속 진행하기 위한 선행작업이 완료됨
3. 할 일이 생김


v$latch 뷰를 조회해 각 래치 종류별로의 항목들을 알아보자

참고로 래치를 얻는 과정 자체가 경합을 의미하지는 않는다. 공유된 자원을 읽으려면 래치를 얻는 것은 당연한 일이라 gets 항목 값이 증가된다고 문제는 없지만, 그 과정에서 다른 프로세스와의 경합이 발생하는지를 봐야하고, 발생한다면 동시성이 저하되므로 문제가 된다.

1. gets : 래치 요청 횟수를 말한다

2. misses : 래치를 요청했는데 다른 프로세스에 의해 자원이 사용 중이어서 첫 번째 시도에서 곧바로 래치를 얻지 못한 횟수이다

3. spin_gets : 래치를 요청한 첫 번째 시도에서 곧바로 얻지는 못 했지만, 이후 spin하는 과정에서 래치 획득에 성공한 횟수이다

  • spin_gets = gets - misses

4. sleeps : 래치를 요청했는데 자원이 사용 중이어서 곧바로 래치를 얻지 못했고 정해진 횟수만큼 계속 spin 했는데도 결국 래치를 얻지 못해 대기 상태로 빠진 횟수이다

  • 이 때 발생하는 대기 이벤트가 latch free이다
  • 래치는 Lock처럼 큐잉 메커니즘이 작동하지 않아서 래치 획득에 성공 할 때까지 반복적인 액세스 시도가 있을 뿐, 우선권이 부여되지는 않음
    -> 가장 먼저 래치를 요구했던 프로세스가 가장 늦게 얻을 수도 있다

11. Shared Pool

Shared Pool이란 SGA의 중요한 구성요소 중 하나로 Dictionary Cache와 Library Cache로 나뉜다

1. Dictionary Cache

말 그대로, 오라클 딕셔너리 정보를 저장해 두는 캐시영역으로서 Row 단위로 읽고 쓰기 때문에 '로우 캐시'라고도 불린다. 데이터의 입출력을 빠르게 하기위한 캐시영역이다. 테이블, 인덱스 같은 오브젝트와 테이블스페이스, 데이터파일, 세그먼트, 익스텐트, 사용자, 제약, Sequence, DB Link에 관한 정보들을 캐싱한다.

2. Library Cache

라이브러리 캐시는 사용자가 던진 SQL과 그 실행계획을 저장해두는 캐시영역이다.

실행계획(execution plan)이란?

사용자가 SQL이라는 명령어를 통해 결과집합을 요청하면 이를 최적으로 수행하기 위한 처리 루틴을 말한다. 사용자가 SQL을 실행하여 데이터를 추출하려고 할 때 옵티마이저가 수립하는 작업절차를 뜻한다.

라이브러리 캐시는 같은 SQL에 대한 반복적인 하드파싱을 최소화하기 위한 새로운 캐시 공간이고 최적화 원리는 캐싱된 SQL과 그 실행계획의 재사용성을 높히는 데에 있다.

profile
Data Engineer

0개의 댓글