Buffer busy waits

EXEM Knowledge Base

Jump to: navigation, 찾기

목차

[편집] Basic Info

특정 블록(Block)을 액세스하는 프로세스는 해당 블록에 대해 Buffer Lock을 획득해야 한다. 가령 특정 블록을 변경하려면 해당 블록에 대해 Buffer Lock을 Exclusive 모드로 획득해야 한다. 반면 특정 블록을 읽으려면 해당 블록에 대해 Buffer Lock을 Shared 모드로 획득해야 한다.


만일 프로세스 A가 블록 X에 대해 Buffer Lock을 획득하고 있는 상태에서 프로세스 B가 동일 블록에 대해 호환되지 않는 모드로 Buffer Lock을 획득하지 못하고 대기해야 한다. 이때 발생하는 대기 이벤트가 buffer busy waits 이벤트이다.


buffer busy waits 이벤트가 가장 흔히 목격되는 경우는 동시에 여러 프로세스가 동일 블록에 대해 Insert를 하거나 Update를 하는 경우이다. Insert나 Update 작업은 해당 블록에 대해 Buffer Lock을 Exclusive 모드로 획득할 것을 요구한다. 여러 프로세스가 동시에 동일 블록에 대해 Buffer Lock을 Exclusive 모드로 획득하는 경우에는 Buffer Lock 경합이 발생하게 되고 buffer busy waits 이벤트에 대한 대기로 관찰된다.

[편집] Parameter & Wait Time

[편집] Wait Parameters

buffer busy waits 대기이벤트의 대기 파라미터는 다음과 같다.

  • P1 : File#
  • P2 : Block#
  • P3 : 오라클 10g에서는 블록 클래스(Block Class)를 의미하며, 오라클 9i에서는 Reason Code를 의미한다.

[편집] Wait Time

일반적으로 1초까지 기다린다. 만일 Exclusive 모드로 Buffer Lock을 획득하기 위해 buffer busy waits 이벤트들 1초 대기한 후 다시 대기하는 경우에는 3초까지 기다린다. 특정 블록을 읽고자 하는 세션은 반드시 Buffer Lock을 획득해야 한다.

[편집] Check Point & Solution

블록 클래스에 따른 buffer busy waits 이벤트의 발생 원인과 해결책은 다음과 같다.

[편집] 데이터 블록(블록 클래스 = 1)

사용자 어플리케이션이 동시에 여러 세션이 동일 블록을 변경하게끔 동작하는 경우. 이러한 블록을 흔히 핫블록(Hot Block)이라고 부른다. 핫블록을 해소하는 방법들에는 다음과 같은 것들이 있다. 사용자 어플리케이션의 수정: 어플리케이션 수정을 통해 동시에 여러 프로세스가 동일 블록을 변경하지 않게끔 한다.

  • PCTFREE 값의 조정: PCTFREE 값을 크게 해서 오브젝트를 생성하면 하나의 블록에 들어가는 로우 수가 줄어들고 그만큼 블록 경합이 줄어든다.
  • 우편향 인덱스의 변경: 인덱스의 키가 우편향되어 있으면 인덱스 리프 노드에 대한 블록 경합이 발생할 수 있다. Sequence 값을 이용해 생성된 키 값이 인덱스로 쓰이는 경우가 대표적이다. 리버스 인덱스(Reverse Index)를 이용해 키 값을 분산시키면 블록 경합을 줄일 수 있다.
  • FLM을 사용하는 경우: FLM(Free List Management)을 사용하는 경우에는 오브젝트의 Storage 속성 중 FREELISTS 속성 값을 충분히 크게 주어야 한다. FREELISTS의 값이 1이면 동시에 여러 프로세스가 동일 블록에 Insert를 수행하기 때문에 블록 경합이 생길 수 있다. FREELISTS 속성 값은 동시에 Insert를 수행하는 프로세스의 최대 개수만큼 부여하는 것이 좋다.
  • 파티셔닝: 세그먼트 파티셔닝을 통해 블록을 임의로 분산할 수 있다. 가령 해시 파티션(Hash Partition)과 같은 기법을 통해 하나의 블록에 모여 있던 블록들을 물리적으로 임의의 공간에 분산시키면 블록 경합을 줄이는 효과를 얻을 수 있다.

[편집] 세그먼트 헤더(블록 클래스 = 4)

FLM을 사용하는 경우, Storage 속성 중 FREELISTS 속성 값을 충분히 크게 해준다. 만일 OPS나 RAC 환경이라면 FREELIST GROUPS 속성 값을 인스턴스의 개수와 동일하게 부여한다. FREELIST GROUPS 속성 값을 부여하면 세그먼트 헤더 블록과 별도로 프리리스트 블록을 사용하기 때문에 그만큼 세그먼트 헤더 블록의 경합이 줄어든다.

[편집] 비트맵 블록(블록 클래스 = 8, 9, 10)

ASSM(Automatic Segment Space Management)를 사용하는 경우에는 세 단계의 비트맵 블록에서 경합이 발생할 수 있다. 비트맵 블록에서 발생하는 블록 경합은 오라클 튜닝을 통해 개선할 수 없으며, 어플리케이션의 수정을 통해 과도한 동시 DML을 줄여야 한다.


ASSM은 대규모의 동시 DML에 있어서는 FLM에 비해 약간의 오버헤드를 가지고 있다. 하지만 대부분의 경우 이러한 오버헤드는 무시할 정도이다. ASSM은 FLM에 비해 여러 가지 장점을 제공하면 특히 RAC에서 최적의 성능을 제공한다.

[편집] 언두 헤더 블록(블록 클래스 = 15 + 2*r)

AUM(Automatic Undo Management)를 사용하는 경우에는 언두 헤더에서의 블록 경합은 잘 발생하지 않는다. 수동 모드의 롤백 세그먼트를 사용하는 경우에는 롤백 세그먼트의 개수를 충분히 키워줌으로써 언두 헤더 블록에 대한 경합을 줄일 수 있다.

[편집] Event Tip

[편집] FLM

[편집] ASSM

[편집] Analysis Case

[편집] 1. 블록 분산으로 인한 buffer busy waits 대기현상 감소

아래 그림은 buffer busy waits 이벤트가 과도하게 발생하는 상황을 Maxgauge를 통해 모니터링한 결과이다.
그림:buffer_busy_1.jpg

그림:buffer_busy_2.jpg
그림 buffer busy waits 이벤트 발생 상황


buffer busy waits 이벤트의 발생 이유를 분석한 결과 여러 프로세스가 동시에 동일 블록을 변경하는 과정에서 데이터 블록(블록 클래스 = 1)에서 블록 경합이 발생한 것으로 확인되었다. 즉, 아래 그림과 같은 형태로 특정 테이블에 대한 Update 작업이 이루어지는 것이 원인이었다.
그림:buffer_busy_3.jpg
블록을 랜덤하게 분산시키기 위해 아래와 같이 해시 파티션을 적용하였다.

-- t_buffer_busy_waits 테이블
-- 해시 파티션을 적용해서 로우들을 임의의 블록들로 분산
CREATE TABLE t_buffer_busy_waits ( id NUMBER, name VARCHAR2(10) )
PARTITION BY HASH(id) PARTITIONS 100;

아래 그림은 해시 파티션을 적용한 후, 동일 어플리케이션을 Maxgauge를 통해 모니터링한 결과이다. buffer busy waits 이벤트의 발생이 줄어든 것을 확인할 수 있다.
그림:buffer_busy_4.jpg
V$SYSTEM_EVENT 뷰를 통해 성능 개선 전후의 buffer busy waits 이벤트 대기 시간을 계산한 결과 buffer busy waits 이벤트 대기 시간이 4,120초에서 1,214초로 줄어든 것으로 확인되었다.


[편집] 2. 비효율 SQL에 의한 Buffer Lock 대기현상

오라클 9i 버전에서 Buffer Busy Waits (id 130) 이벤트는 10g 버전에서 Read By Other Session 으로 이벤트명이 변경되었으므로, Read by other session의 Analysis Case로 넘어갑니다.

[편집] 3. 잘못된 FreeList 속성 값에 의한 Buffer Busy Waits 이벤트 발생 현상

문제를 분석하고자 하는 인스턴스는 Active Session이 평균 2~30개로 유지되다가 특정 시점에 300여개 이상으로 급증하는 현상이 발생하였다.

Active Session의 추이 그래프는 다음과 같으며, Active Session이 증가한 시점의 대기 이벤트 목록을 보면, Idle 이벤트(=SQL*Net Message…)를 제외하고 Buffer busy waits 이벤트의 대기가 가장 많이(1199초) 발생하는 것을 알 수 있다. 그림:8_4_1.jpg

Active Session과 Buffer Busy Waits 이벤트 대기의 상관관계를 알아보기 위하여 두 지표의 그래프를 확인해 보면, 증감 추이가 일치함을 알 수 있다. 그림:8_4_2.jpg 따라서, Active Session의 급증현상은 Buffer Busy Waits 이벤트의 발생이 원인임을 추측할 수 있다.

그림:8_4_3.jpg 해당 시점의 Active Session List를 확인해 보면, Buffer Busy Waits 이벤트를 대기하는 세션은 SUBSCRIBE라는 테이블에 모두 INSERT를 하고 있고, Buffer Busy Waits 이벤트의 P3 값인 id는 220번이다. ID 220번은 동일한 블록을 변경하려고 할 때 발생하는 Buffer Lock 경합 현상이다.

Insert에 의한 Buffer busy waits 이벤트의 경합 현상은 대부분 잘못된 프리리스트 값에 의해 발생한다. 여러 개의 세션이 동시에 같은 테이블에 Insert를 수행하는 경우, 세그먼트 영역이 급속히 확장되고, 이 때 세그먼트에 대해 Insert를 하는 실제 프로세스 개수에 비해 프로세스 프리리스트의 개수가 지나치게 작다면 Buffer Busy Waits 이벤트가 발생한다.

실제로, Buffer Busy Waits 이벤트를 대기하는 세션의 Wait 발생 리스트를 확인해 보자. 그림:8_4_4.jpg

Buffer Busy Waits 이벤트를 대기하다가 어느 순간에 HW Enqueue를 대기함을 확인할 수 있다.

Buffer Busy Waits 이벤트와 HW Enqueue 이벤트는 프리리스트와 관련이 있으므로, Insert를 하는 대상 테이블인 SUBSCRIBE의 freelists, freelist groups 속성 값을 조회해본다. 그림:8_4_5.jpg

위와 같이 SUBSCRIBE 테이블은 Freelists 값이 1로 설정되어 있다.

FLM(FreeList Management)로 세그먼트를 관리할 경우, 오라클은 기본적으로 하나의 마스터 프리리스트를 할당하는데, 만일 세그먼트 생성 시 Freelists 값을 1로 주면, 마스터 프리리스트가 프로세스 프리리스트로 활용된다. 마스터 프리리스트 하나만이 생성되기 때문에, 동시에 여러 프로세스가 동일 프리 블록을 사용하게 되고 이로 인해 Buffer Busy Waits 이벤트가 발생한다.

또한, 마스터 프리리스트에는 신규로 확보된 프리블록이 우선적으로 저장되는데, 개별 프로세스가 프리블록을 필요로 하는 시점에 마스터 프리리스트로부터 필요한 수의 프리블록을 얻어온다. 그런데, 마스터 프리리스트에 더 이상 프리블록이 없으면, HW락을 획득하고 HWM를 이용해서 프리블록을 확보한다. 이 과정에서 HW Enqueue가 발생한다.

즉, 여러 세션이 동시에 Insert를 수행하는 테이블의 Freelist 속성값이 1이었기 때문에, buffer lock 경합이 발생하였고 이로 인해 Active Session이 급증하였다. 이 경우, 문제가 되는 테이블의 freelist 값을 동시에 수행되는 프로세스 개수를 고려하여 복수개의 freelist를 사용하도록 테이블을 재 생성하거나, ASSM(Auto Segment Space Management)를 사용하는 방법을 고려하여 해결할 수 있다.