Gc cr/current block busy

EXEM Knowledge Base

Jump to: navigation, 찾기

목차

[편집] Basic Info

gc cr/current block busy 이벤트는 gc cr/current request 이벤트에 대한 Fixed-up 이벤트로, 홀더 노드로부터 블록 이미지를 전송 받는 과정에서 경합이 발생했다는 것을 의미한다. gc cr/current request 이벤트가 gc cr/current block busy 이벤트로 변경되는 흐름은 다음과 같다.

  • 요청 노드의 유저 프로세스가 특정 데이터 블록을 읽고자 한다.
  • 유저 프로세스는 해당 데이터 블록의 적절한 버전이 로컬 버퍼 캐시에 없는 것을 확인하고, 마스터 노드의 LMS 프로세스에 블록 전송을 요청한다. 유저 프로세스는 응답을 받을 때까지 gc cr/current request 이벤트를 대기한다.
  • 마스터 노드(즉, 홀더 노드)의 LMS 프로세스는 요청된 블록에 대해 BL 락을 공유 모드로 획득할 수 있어야 한다. 만일 필요한 모드의 락을 획득하는 과정에서 지연이 발생하면 요청 노드에 블록을 전송하되, 블록을 읽어 들이는 과정에서 경합(Contention)이 발생했음을 같이 알린다.
  • 유저 프로세스는 블록을 전송 받은 후 응답 메시지로부터 경합이 발생했음을 확인하고, gc cr/current request 이벤트를 Fixed-up 이벤트인 gc cr/current block busy 이벤트로 변경한다.

gc cr/current block busy 대기 이벤트는 블록을 전송 받는 과정에서 경합으로 인한 지연(Delay)이 발생했다는 것을 의미한다. 오라클은 “경합(Contention)”과 “혼잡(Congestion)”이라는 두 가지 사유에 의해 글로벌 캐시 동기화 과정에서 지연 현상이 발생하는 것으로 정의하고 있다. 경합(Contention)이 지연의 발생 사유인 경우에는 “Busy”라는 용어를 사용하며, 혼잡(Congestion)이 발생 사유인 경우에는 “Congested”라는 용어를 사용한다는 것을 기억하자.

홀더 노드의 LMS 프로세스가 블록을 전송하는 과정에서 경합에 의한 지연이 발생하는 이유에는 다음과 같은 것들이 있다.

  1. 요청된 블록이 로컬 프로세스에 의해 현재 사용 중인 경우. 현재 변경 중인 블록에 대해서는 버퍼 락(Buffer Lock)이 독점 모드로 획득된 상태이므로, LMS 프로세스는 해당 블록의 변경이 완료될 때까지 대기해야 한다. Update 문에 의해 변경 중이거나, Select 문에 의해 디스크에서 버퍼 캐시로 적재되고 있는 경우를 포함한다.
  2. 리두 플러시(Flush) 과정이 발생하는 경우. 홀더 노드의 로컬 프로세스에 의해 변경된 후 아직 Commit이 이루어지지 않은 블록을 요청 노드로 전송하려면, 블록의 변경 내용을 리두 로그에 기록해야 한다. 이 과정을 “리두 플러시”라고 부른다. 이 과정에서 지연이 발생하면 홀더 노드에서는 gcs log flush sync 이벤트 대기 시간이 높거나, gc cr block flush time 통계 값이나 gc current block flush time 통계 값이 높게 나온다. LMS 프로세스가 블록 전송을 위해 더티 블록에 대한 변경 내역을 로그 파일에 기록하는 경우에는 log file sync 이벤트가 아닌 gcs log flush sync 이벤트를 대기하는 것으로 관찰된다는 사실에 유의하자.

위와 같은 상황의 경쟁이 발생한 경우 오라클은 블록 처리 과정에서 경합이 발생했다고 간주하게 된다.

[편집] 요청 모드와 busy 이벤트

gc cr/current block busy 이벤트가 발생하는 정확한 시점은 블록 요청이 CR 모드인지, Current 모드인지에 따라 약간 다르다.

요청 노드의 CR 모드 요청에 대해 홀더 노드가 아직 Commit이 이루어지지 않은 현재 블록을 전송하는 경우에는 반드시 CR 블록, 즉 변경 이전 이미지를 전송해야 한다. 문제는 홀더 노드의 버퍼 캐시에 CR 이미지가 존재하지 않는 경우이다. 이 경우 현재 블록의 카피 버전인 CR 카피 블록을 생성하고, 언두 이미지를 디스크에서 읽은 후, CR 카피 블록에 롤백을 수행하는 일련의 과정을 거쳐야 한다. 또한 현재 블록에 대한 리두 플러시를 수행한다. 이러한 일련의 과정이 홀더 노드의 LMS 프로세스에 지나친 부하를 주기 때문에, 오라클은 불완전한 이미지의 CR 블록을 요청 노드로 전송한다. 불완전한 CR 블록을 전송 받은 요청 노드가 스스로 완전한 이미지의 CR 블록을 생성하게 된다. 이것을 Light Weight Rule(경량화 법칙)이라고 부른다. V$CR_BLOCK_SERVER 뷰를 조회하면 전체 일관된 읽기 작업 중 Light Weight Rule이 몇 번이나 적용되었는지 확인할 수 있다.

SQL> SELECT cr_requests, light_works FROM v$cr_block_server
 CR_REQUESTS		LIGHT_WORKS
 ------------------		-----------------
   35331145		3866363

Commit이 이루어지지 않은 더티 블록에 대한 CR 모드 요청에 대해서는 주로 gc cr block 2/3-way 류의 이벤트를 Fixed-up 이벤트로 사용한다. 이 과정에서 리두 플러시 과정에서 지연이 발생하면 gc cr block busy 이벤트를 Fixed-up 이벤트로 사용한다.

반면 Commit이 이루어진 더티 블록에 대해 Current 모드의 요청이 발생하면, 즉각 락 다운그레이드가 발생한다. 이 경우 요청 노드는 일반적으로 gc current block 2/3-way 류의 이벤트를 Fixed-up 이벤트로 사용하며, 만일 홀더 노드의 리두 플러시 과정에서 지연이 발생하면 gc current block busy 이벤트를 Fixed-up 이벤트로 사용한다.

[편집] Parameter & Wait Time

[편집] Wait Parameters

gc cr/current block busy 이벤트와 같은 Fixed-up 이벤트는 P1, P2, P3 값이 별도로 부여되지 않으며, Placeholder 이벤트(여기서는 gc cr request 이벤트)와 동일한 값을 가지는 것으로 해석하면 된다.

[편집] Wait Time

[편집] Check Point & Solution

[편집] gc cr block busy 해소방안

gc cr block busy 이벤트에 대한 대기를 해소하기 위한 방법은 다음과 같다.

  • LGWR 프로세스의 성능을 극대화한다. 리두 로그가 위치한 디바이스를 최적으로 구성한다. LGWR 프로세스의 CPU 우선순위를 높이는 것도 좋은 방법이 된다.
  • SQL 튜닝을 통해 읽기 작업과 변경 작업이 동일 블록을 액세스하는 경우의 수를 줄인다.
  • 버퍼 캐시 튜닝을 통해 메모리로 읽어 들인 블록이 캐시에서 밀려나는 경우의 수를 줄인다.
  • 블록 분산 기법(파티셔닝, 리버스 키 인덱스, 시퀀스 캐시 크기)을 이용해 핫 블록이 발생할 확률을 줄인다.

gc cr block busy 이벤트 대기는 블록 경합에 의해 발생하기 때문에, 인터커넥트의 성능과 무관하게 발생할 수 있다는 사실에 유의해야 한다. 즉 블록을 전송하는 과정에서 지연이 발생하는 것이 아니라, 홀더 노드가 블록 전송을 준비하는 과정에서 지연이 발생하는 것이다. 따라서 블록 경합을 줄이거나, 블록 경합 과정에서 발생하는 리두 플러시를 최적화하는 것이 튜닝 방법이 된다. 물론, 인터커넥트의 성능이 낮으면 대기 회수에 비해서 대기 시간은 늘어날 수 있다.

간단한 테스트를 통해 gc cr block busy 이벤트 대기와 블록 변경과의 관계를 확인할 수 있다.

-- 노드 2가 마스터 노드인 rac_test 테이블.
-- 노드 2에서 rac_test 테이블에 대해 Update 수행 후 Commit을 수행하지 않음
SQL#2> UPDATE rac_test SET id = 3;

-- 노드 1에서 rac_test 테이블을 Select. 노드 2에 의해 변경된 블록을 읽어 들인다.
SQL#1> SELECT * FROM rac_test;
SQL#1> /
… (같은 쿼리를 여러 번 수행)
-- 위의 쿼리들에 대해 SQL Trace를 수행한 결과는 다음과 같다.
-- 홀더 노드에서의 리두 플러시에 의해 지연이 발생하고, 이로 인해 요청 노드는 gc cr block busy 이벤트를 대기하는 것을 확인할 수 있다.
-- 단, 리두 플러시 과정에 매우 가볍다면 gc cr block busy 이벤트가 아닌 gc cr block 2/3-way 류의 이벤트로 관찰된다.
select * from rac_test
WAIT #2: nam='SQL*Net message to client' ela= 3 p1=16508 p2=1 p3=0
WAIT #2: nam='gc cr block busy' ela= 68615 p1=14 p2=10344 p3=1
WAIT #2: nam='SQL*Net message from client' ela= 313 p1=16508 p2=1 p3=0
WAIT #2: nam='SQL*Net message to client' ela= 2 p1=16508 p2=1 p3=0
WAIT #2: nam='SQL*Net message from client' ela= 410 p1=16508 p2=1 p3=0

[편집] Event Tip

[편집] Analysis Case