버퍼 캐시(Buffer Cache)에서의 대기이벤트들

latch: cache buffers chains
버퍼 캐시를 사용하기 위해 해시 체인을 탐색하거나 변경하려는 프로세스는 반드시 해당 체인을 관리하는 cache buffers chains래치를 획득해야 한다 - 경합시 latch: cache buffers chains발생
9i부터는 읽기 목적 체인 탐색시 cache buffers chains래치를 Shared 모드로 공유 가능 -> 다만 어차피 실제 읽기위해 버퍼에 접근시 버퍼 헤더 일부를 변경해야 하므로 buffer lock때문에 다시 latch: cache buffers chains대기
cache buffers chains래치 경합이 발생하는 대표적인 경우 : 비효율적인 SQL, 핫블록

비효율적인 SQL
프로세스가 넓은 범위의 인덱스나 넓은 범위의 테이블에 대해 스캔을 수행할 경우 cache buffers chains래치 경합이 광범위하게 발생 가능
ex) 넓은 범위의 인덱스 스캔 -> 불필요한 버퍼 탐색 증가 -> latch: cache buffers chains대기 이벤트
cache buffers chains 래치 경합 발생시 원인을 정확히 밝히는 것이 중요하다
SQL문이 비효율적인지 판단하려면 - SQL문장 자체에 주목해야함 => 플랜이나 SQL Trace등을 이용하면 정확한 분석 가능
뷰를 통해 SQL문제인지 핫블록 문제인지 판단할 수 도 있다
---> V$LATCH_CHILDREN뷰에서 -> cache buffers chains 래치에 해당하는 CHILD#과 GETS, SLEEPS값을 비교 -> '특정' 자식 래치에 사용하는 회수와 경합이 집중되는 경향이 있다면 그놈이 핫블록일 가능성 큼
---> V$SESSION_WAIT뷰에서 -> EVENT=cache buffers chains일때 -> P1RAW가 자식 래치의 주소에 해당함 -> 특정 주소만 과다하게 반복된다면 핫블록일 가능성 큼
Parallel Query 사용도 cache buffers chains 래치 경합을 줄이는 방법이 될 수 있다. || Paraller Query = 대용량 데이터 처리 위해 특별한 경우에만 사용하는것. SGA를 거치지 않고 데이터 파일에서 원하는 데이터를 직접 읽어들인다.

핫블록(Hot Block)
SQL문장 튜닝으로도 cache buffers chains래치 경합이 해결되지 않는경우 -> SQL문이 소수의 특정 블록을 계속해서 스캔하는경우인가 -> 그렇다면 핫블록에 의한 cache buffers chains 래치 경합
핫블록인지 알아보는 것은 몇줄 위에 화살표 해놓은 것들 보시오
핫블록을 해결하려면 -> 동일 블록을 반복해서 스캔하는 설계상의 문제를 해소하도록 한다 -> 어플리케이션 수정이 불가능하다면 -> 핫블록에 속한 로우들을 다른 블록을 분산시킨다
1. PCTFREE를 높게 주거나, 작은 크기의 블록을 사용하여 블록 경합을 줄인다 -> 하나의 블록에 포함되는 로우의 수를 줄이는 방식 -> 핫 블록은 해결될지 몰라도 관리해야할 블록수가 늘어나며 부차적인 문제 발생함
2. 파티셔닝 기법을 사용해서 로우가 물리적으로 다른 블록으로 들어가게끔 한다 -> 테이블에 대해 적용시 클러스터링 팩터 문제 발생 가능성 있음
3. 문제 블록과 해당 블록에 포함된 로우의 ROWID를 정확히 알 수 있다면, 문제가 되는 블록의 로우들을 삭제 후 재삽입한다 - 로우가 다른 블록으로 흩어지게 함 - 블록 덤프와 DBMS_ROWID패키지 이용함 - 인덱스에 대해서는 사용 불가능하고, 핫블록이 고정되어 있지 않고 매번 바뀐다면 적용할 수 없다.
테이블에서 cache buffers chains 래치 경합은 비교적 해결 쉬운데 -> 인덱스는 정렬된 상태로 저장되는 특성 떄문에 임의의 블록으로 분산시키는 것이 힘들다 -> PCTFREE를 높게 주거나 작은 크기 블록 사용하는 것 외엔 특별한 대책이 없음

 

latch: cache buffers lru chain
Working Set(LRU + LRUW)을 탐색 변경시 cache buffers lru chain래치를 획득해야 함 - 경합시 latch: cache buffers lru chain대기 이벤트
cache buffers lru chain를 획득하는 경우
1. 아직 메모리에 올라오지 않은 블록을 읽고자 할 경우 -> 프리 버퍼를 할당받기 위해 LRU 리스트를 탐색 -> cache buffers lru chain래치를 획득해야함
2. DBWR - 더티 버퍼 기록할때 -> LRUW 리스트를 탐색 + 해당 버퍼를 LRU리스트로 옮기는 과정 -> cache buffers lru chain래치를 획득해야 한다.

cache buffers lru chain래치 경합의 가장 주된 원인은 과도한 프리 버퍼의 요청 -> 비효율적인 SQL 문장이 프리 버퍼를 과도하게 요청하는 가장 전형적인 경우
동시에 여러 세션이 비효율적인 SQL문장을 수행하게 되면 프리 버퍼 탐색 과정 + 더티 버퍼 기록 과정에 cache buffers lru chain래치 경합 발생

cache buffers chains래치와 cache buffers lru chain래치 경합간의 차이점
- > 동일 테이블이나 인덱스를 여러 세션이 동시에 스캔하면 cache buffers chains 래치 경합 가능성 높음 - 동일 체인에 대한 경합이 발생하기 때문
- > 다른 테이블이나 인덱스를 여러 세션이 동시에 스캔하면 cache buffers lru chain 래치 경합 가능성이 높다 - 여러 세션이 서로 다른 블록을 메모리에 올리려 -> 프리 버퍼 확보 요청 많아지고 -> working set에 대한 경합이 높아지며 -> cache buffers lru chain래치 경합 발생 || 특히 데이터 변경이 빈번해 LRUW리스트 탐색도 잦아진다면 cache buffers lru chain래치 경합은 더욱 심해짐 || 비효율 인덱스 스캔 문제일 경우 db file sequential read 대기 이벤트와 lru chain 래치 경합이 함께 발생 || 실제로는 cache buffers chains 래치 경합과 cache buffers lru chain래치 경합이 같이 발생하는 경우가 많음

버퍼 캐시의 크기가 자나치게 작거나, 체크포인트 주기가 지나치게 짧은 경우에도 cache buffers lru chain래치 경합이 증가할 수 있음 -> 그래도 이런 경우는 드물고 웬만하면 비효율 SQL일 것임


buffer busy waits / read by other session
오라클이 로우레벨 단위의 락을 제공한다쳐도 - 두개 이상의 로우가 한 블록 내에 있고, 둘을 동시에 변경하려 한다면 - 변경하려는 블록 자체에 대해서는 혼자서만 변경하고 있다는 것을 보장해야한다.
이 경우에 획득해야 하는 락 - buffer lock
buffer lock 획득 모드는 Shared, Exclusive 두종류가 있다. 서로 호환되지 않는 모드로 락을 확득하려 하면 경합이 발생함
buffer lock - 버퍼의 변경을 동기화 하는 역할
하나의 로우를 변경할때 래치-락을 획득하는 과정
1. 변경하려는 로우에 해당하는 블록이 존재하는 위치(해시 체인)에 찾아가기 위해 cache buffer chains 래치를 획득
2. 블록을 담고 있는 버퍼에 대해 buffer lock 획득 + cache buffers chains 래치 해제
3. TX락 획득 - 로우 변경 (TX락 획득 실패시 buffer lock 해제하고 대기한다 - 그 후 1번과정 반복)
4. 로우 변경 + buffer lock 해제

buffer lock을 획득하기 위해 기다리는 동안 -- buffer busy waits 대기 이벤트(가장 일반적), buffer busy global cache/CR (10g에서는 gc buffer busy), write complete waits, read by other session(10g부터)

10g 이전 버전의 buffer busy waits
P1 : 절대 File#
P2 : Block#
P3 : 원인 코드 -> 다양한 대기 원인을 나타내주었음 -> 버전마다 코드 값은 다르다 -> 10g이후 부터는 완전히 바뀌어서 P3는 경합이 발생한 블록의 Class#을 나타낸다

원인코드 (괄호 안은 8.1.5 이하의 코드)
100 (1003) : 블로킹 세션은 버퍼 캐쉬로 블록을 적재하는 중이며, 롤백을 위한 Undo 블록일 가능성이 높다. 해당 정보를 이용하여 새로운 버전의 블록을 생성하기 위해, 배타적인 액세스를 하려는 세션은 대기해야 한다.
110 (1014) : 대기 세션은 블로킹 세션이 버퍼 캐쉬로 적재하고 있는 블록에 대한 현재 이미지를 읽거나, 기록하려고 한다.
120 (1014) : 대기 세션은 블로킹 세션이 버퍼 캐쉬로 적재하고 있는 블록을 현재 모드로 액세스하려고 한다. 버퍼 룩업시에 발생한다.
130 (1013) : 하나 이상의 세션이 버퍼 캐쉬에 존재하지 않는 블록을 액세스하려고 할 경우, 하나의 세션이 db file sequential read 또는 db file scattered read 이벤트를 발생시키면서 I/O 작업을 수행하는 동안, 다른 세션들은 해당 원인코드를 가지고 buffer busy waits 이벤트를 발생시킨다.
200 (1007) : 블로킹 세션이 버퍼 캐쉬 안의 블록을 변경하는 동안, 새로운 버전의 블록을 생성하기 위해, 해당 블록에 배타적인 액세스를 해야 하는 세션은 대기해야 한다.
210 (1016) : 블로킹 세션이 블록을 변경 중일 때 배타적인 모드로 블록의 현재 버전을 원하는 세션은 대기해야 한다. 두 개의 세션이 동일한 블록을 변경하려고 할 때 발생한다.
220 (1016) : 블로킹 세션이 블록을 변경 중일 때 현재 모드로 블록을 액세스하려는 세션은 대기해야 한다.
230 (1010) : 블로킹 세션이 블록을 변경 중일 때 해당 블록을 공유 모드로 액세스하려는 세션은 대기해야 한다.
231 (1012) : 블로킹 세션이 블록을 변경 중일 때, 해당 블록의 현재 버전을 읽고 있는 세션이, 해당 블록에 대한 공유 액세스를 하려고 할 경우에 대기 해야 한다.


10g 이후 버전의 buffer busy waits
10g 이후로 buffer busy waits이 크게 변동 되었다.
변동 사항
1. 기존의 buffer busy waits 이벤트가 read by session과 buffer busy waits 두개로 분화됨. read bu session은 원인코드 130번에 해당하고, buffer busy waits는 220번에 해당함
2. P3의 용도 변경 -> 원인코드 사용되지 않고, 경합이 발생한 블록의 class#를 나타낸다.

Select, Insert, Update등의 구문 수행시 buffer lock이 어떻게 획득되고 buffer busy waits 이벤트 대기가 어떻게 발생하는지를 분석하고 buffer busy waits 이벤트 대기를 줄이자
Select / Select에 의한 read by other session
동시에 같은 블록을 메모리에 올리는 과정에서 발생
여러개의 세션이 동시에 동일한 테이블을 읽어 들일 때 read by other session 이벤트 대기가 광범위하게 나타난다. 정확한 정보는 V$SESSION_WAIT뷰를 이용해 read by other session 대기 이벤트를 캡쳐
-> 읽고자 하는 블록이 이미 SGA에 올라와 있다면 Shared모드로 블록을 읽기 때문에 대기 현상이 발생하지 않는다. 다만 동시에 여러 세션이 새로운 블록을 읽으려 한다면 블록 자체에 대한 락 때문에 경합이 발생하는 것이다.
select/select에 의한 read by other session대기를 줄이는 방법
- SQL 최적화를 통해서 최소한의 I/O만으로 원하는 결과를 가져올 수 있도록 해야 한다.
- SGA 사이즈(또는 버퍼 캐시 사이즈)가 시스템 전반적인 I/O에 비해 작다면 SQL 튜닝 만으로는 문제를 해결할 수 없으며 SGA의 물리적 크기를 늘려 주어야 한다.

Select / Update에 의한 buffer busy waits / read by other session
발생 상황 - 특정 프로세스가 특정 테이블을 변경한다. 데이터의 이전 이미지가 언두 블록에 기록된다 -> 동시에 (혹은 이후에) 많은 프로세스들이 변경된 데이터에 대해 읽기를 시도한다.
변경된 블록을 Select시 읽기 일관성 때문에 CR블록을 읽으려 할 것이다 -> 헌데 CR블록은 버퍼에 들어있지 않고, 언두 블록에 들어있다 -> 여러 세션이 해당 언두 블록을 메모리에 올리려 할때 buffer lock 경합
: select세션이 데이터 읽으려함 -> 헌데 해당 블록이 update에의해 변경된 상태 -> 그렇다면 과거정보를 읽어야하니 언두 블록을 읽자 -> 헌데 그 언두 블록을 읽으려는 세션이 잔뜩이네 -> 이때 그 언두 블록에 대하여 select/select의 경우와 동일한 상황의 buffer lock 경합이 발생하게 됨
-> SQL문을 튜닝해서 논리적 I/O를 줄인다 -> 언두를 읽는 회수도 줄어든다
SGA크기를 적절히 늘려주어 버퍼 캐시에 CR 블록이 오래 상주하게 해준다

Insert / Insert에 의한 buffer busy waits
같은 테이블에 동시에 insert 수행시 문제점
insert/insert에 의한 buffer lock 경합은 프리리스트 때문일 가능성이 큼
-> FREELISTS 값을 1으로 둬 - 마스터프리리스트 하나만이 생성되고 - 동시에 여러 프로세스가 프로 블록을 사용하려할때 - buffer lock경합 발생
그외 insert중 세그먼트 헤더 블록을 변경할 때와, HWM을 이동할 때도 같은 블록을 쓰려하며 경합 발생 가능하다.
ASSM을 사용하면 전반적으로 buffer busy waits가 줄어든다. HW락 경합도 크게 줄어든다 - ASSM을 사용하는 경우에는 비트맵 블록에 대한 buffer busy waits가 주로 발생함
-> 9i 이상 부터는 가능하면 ASSM을 사용한다. ASSM을 사용하면 어떤 환경에서도 극단적인 성능 저하를 피할 수 있다.
ASSM을 사용할 수 없는 환경이라면 freelist, freelist groups의 값을 시스템의 부하를 고려해서 적절히 부여한다. 프리리스트 속성을 기본값으로 두는 것은 매우 위험하다


Update / Update에 의한 buffer busy waits
여러 세션이 동시에 같은 로우 업데이트시 기본적으로 TX 락에 의해 동기화가 이루어진다.
여러 세션이 서도 다른 로우를 동시에 업데이트 할 경우에 -> 마침 각기 다른 로우가 같은 블록안에 들어있었다면 -> buffer lock에 의한 동기화가 필요하다 || 언두 헤더 블록에 대한 경합도 많이 나타난다 -> 여러 프로세스가 update를 진행하게되며 언두 데이터가 많이 생성되기 때문.
TX락 경합이라면 - 락을 획득한 락 홀더의 트랜잭션을 종료하는 것이 해결책이다
헌데 buffer lock 경합이라면 다양한 해결책이 있음.
-> 각각의 로우를 서로 다른 블록으로 분산시켜 준다.
: PCTFREE 값을 높게 준다 // 파티셔닝 기법을 사용하여 다른 블록으로 흩어지게끔 한다 // 작은 블록 크기를 사용하여 한 블록에 여러 로우가 들어갈 수 없게 한다.
각각의 해결법을 통하여 쉽게 해결해 줄 수는 있지만, 또다른 문제가 야기될 수 있음을 유의하여 사용하도록 한다.
PCTFREE 값을 높게 준다 -> 공간 낭비 초래 이로 인해 풀테이블 스캔, 인덱스 풀스캔, 인덱스 범위스캔 성능에 영향준다 // 동일 내용 처리위해 생성해야하는 블록수 증가로 인해 SGA공간도 낭비된다. 이로인해 cache buffers chains 래치 경합이 발생할 수 있다.
파티셔닝 기법을 사용하여 다른 블록으로 흩어지게끔 한다 -> 일단 PCTFREE바꾸는 것 보다는 나은 방법. 업무 로직이 변경되 update 방식이 바뀌거나 할 경우 주의
작은 블록 크기를 사용하여 한 블록에 여러 로우가 들어갈 수 없게 한다 -> 역시 풀테이블 스캔, 인덱스 풀스캔, 인덱스 범위스캔 성능에 영향준다 // 블록 수가 늘어나므로 cache buffer chains 래치와 관련된 성능 문제 발생 가능성 생긴다.


buffer lock 경합을 줄이는 방법 총 정리
1. select / select에 의해 발생하는 read by other session 대기를 줄이는 최선의 방법운 SQL 최적화를 통해 가장 적은 I/O로 원하는 결과를 얻는 것이다. 이 작업을 통해서도 문제가 해결이 되지 않는다면 SGA(버퍼캐시)의 크기가 적절한지 점검해보아야 한다.
2. select / update에 의해 발생하는 read by other session 대기는 select / select에 의한 read by other session 대기와 해결책이 동일하다.
3. insert / insert에 의해 발생하는 buffer busy waits 대기는 적절한 세그먼트 공간 관리 기법을 사용함으로써 해결이 가능하다. 오라클 9k 이상이라면 ASSM을 사용할 것을 권장한다. 오라클 8i라면 FREELISTS 값을 적절히 지정해야 한다. 트랜잭션의 양에 비해 FREELISTS 값이 지나치게 작은 경우에 buffer lock에 의한 경합이 광범위하게 나타난다. FREELISTS 값만으로 해결이 되지 않을때는 _bump_highwater_mark_count 히든 파라미터값을 크게 해주는 것 또한 도움이 된다. 이 히든 파라미터에 대해서는 HW 락 경합과 관련된 대기이벤트에서 자세히 논의할 것이다.
4. update / update에 의해 발생하는 buffer busy waits 대기는 동일 블록에 대해 동시에 업데이트가 이루어지지 않게끔 개선함으로써 해결이 가능하다. update 형태를 고려한 최적의 파티셔닝을 구성하는 것이 좋은 해결책이 된다. PCTFREE를 높게 주거나 작은 크기의 블록 사이즈(9i부터만 가능)를 사용함으로써 블록을 분산시킬수 있으며 이로 인해 buffer lock 경합을 줄어들 수 있다. 하지만 위의 테스트 결과에서 보듯이 테스트를 통해 사이드 이펫트가 없는지 충분한 검토가 필요하다.


write complete waits - buffer lock 경합에 의한 대기
DBWR이 더티 버퍼를 내려 쓸때 -> buffer lock을 exclusive하게 획득 -> 이때 읽거나 변경하려 한다면 -> 쓰기 작업이 끝나기를 기다려야함 -> 이때 발생하는 것이 write complete waits 대기 이벤트
write complete waits 대기 현상이 많이 발생하고 있다면 DBWR의 성능 문제일 가능성이 매우 높다. (실제로 마침 기록중인 버퍼를 읽을 확률이 높지 않기 때문에, 자주 발생한다면 쓰는 시간이 길기 때문일 것임)
DBWR의 성능이 느린 이유
- I/O 시스템의 성능이 느린 경우 : DBWR에서 db file parallel write 대기 시간이 길게 나타난다면 I/O 시스템에 문제가 있다고 판단할 수 있다 -> 이 경우 free buffer waits, write complete waits 또한 같이 발생. -> 로우디바이스나 AIO등을 사용하여 I/O성능 개선 가능하다 -> OS 차원에서 Direct I/O를 사용하는 것도 도움이 된다 -> Direct I/O사용시 CPU 개수가 충분하면 DB_WRITER_PROCESSES값을 조청해 DBWR개수를 늘리기도 한다.
- DBWR의 작업량이 너무 많은 경우 : 체크포인트가 너무 자주 발생할 가능성이 있다 -> FAST_START_MTTR_TARGET이 작다, 리두 파일이 작아서 스위치가 자주 일어난다, Paraller Query로인해 direct path read가 발생한다, truncate, drop, hot backup 이럴때 체크포인트가 발생하니까 체크하도록한다. I/O 시스템의 성능 문제가 없음에도 write complete waits 대기가 자주 발생한다면 DBWR에 불필요한 부하를 주는 요소가 없는지 살펴보도록 한다.
간접적으로 DBWR의 성능을 개선시키는 방법 -> 다중 버퍼 풀 사용 -> 일반적으로 자주 사용되는 것은 default에둔다 -> 비교적 자주 쓰는것은 keep에 둔다. 이유는 - 원래 자주 쓰는 것은 메모리에 계속 남아 있을 가능성이 크겠지만, 비교적 자주쓰는 정도라면 메모리에서 사라지게될 가능성이 높으므로, 원래 자주쓰는것을 default에, 그리고 비교적 자주 쓰는것을 keep에 두어 보관하도록 한다 -> 그리고 자주 안쓰면 recycle에 둔다.
더불어 각각의 버퍼풀은 별도의 cache buffers lru chain 래치를 사용하기에 래치 경합도 감소시킬 수 있다.
-> 이렇게 DBWR과는 직접 관련 없지만, 캐시 메모리에 오래 남게하여 잦은 I/O를 피하는 식으로 간접적인 DBWR성능 개선 효과를 줄 수 있다.


free buffer waits
서버 프로세스가 블록을 메모리에 올리는 과정
1. 사용자가 요청한 블록의 DBA -> 해시 함수 적용 -> 해시 버킷을 찾는다
2. 해시 버킷에 속한 해시 체인을 탐색 -> 요청한 블록에 해당하는 버퍼 헤더가 존재하는지 확인 -> 존재하고 블록이 캐시에 올라와있다면 해당 블록을 사용한다.
3. 버퍼 캐시에 존재하지 않으면 -> LRU리스트에서 프리 버퍼 찾는다 -> 스캔중 더티 버퍼가 발견하면 LRUW리스트로 이동시킨다 -> 그리고 프리버퍼를 찾아서 데이터 파일로부터 블록을 버퍼로 읽어들인다
4. _DB_BLOCK_SCAN_MAX_PCT 파라미터 값만큼 스캔하고도 LRU리스트에서 프리 버퍼를 찾지 못했다면 -> DBWR에게 더티 블록을 디스크에 기록하고 프리 버퍼 확보 하라 요청 -> 쓰기 완료되면 해당 버퍼 사용
이때 4번에서 쓰기작업 완료될때까지 대기 free buffer waits 이벤트를 대기
free buffer waits가 발생하는 경우 ->
비효율적인 SQL: 많은 프리 버퍼를 요청
지나치게 작은 버퍼 캐시 : 캐시 공간이 부족하여
DBWR의 성능 저하 : 이부분에 대해 최악의 상황에서도 어느 정도 성능이 보장되도록 하는 것이 중요
- 로디바이스 AIO를 사용 || Direct I/O사용 + DBWR 여러개 사용
- 체크포인트 회수를 조정하여 DBWR이 너무 자주 황동하지 않도록한다.
- 다중 버퍼 풀을 사용하여 간접적으로 DBWR의 부하를 줄인다.


enq: TC - contention
인위적인 체크포인트를 수행하는 작업 중 일부는 TC락을 획득해야함 - TC락 = Thread Checkpoint Lock 혹은 Tablespace Checkpoint Lock
경합시 enq: TC - contention 대기 이벤트
TC락을 획득하는 과정
1. 서버 프로세스가 TC 락을 X 모드로 획득
2. 서버 프로세스는 획득한 TC락을 SSX모드로 변경하고, CKPT프로세스가 SS 모드로 해당 락을 획득한다. CKPT는 락 획득후 체크 포인트 발생
3. 서버 프로세스는 다시 TC락을 X 모드로 획득 시도한다. 하지만 해당 락이 CKPT에 의해 해제될때까지 enq: TC - contention 이벤트 대기한다.
4. 체크포인트 작업이 완료되면 CKPT는 TC락 해제, 서버 프로세느느 TC락을 획득 - 체크포인트 작업 끝났음을 알게 된다.
-> 여러 프로세스에 의한 경합이 발생하지 않더라도, 단순히 특정 작업이 끝나기를 기다리는 대기이벤트도 있다
enq: TC - contention 대기 이벤트가 발생하는 대표적인 사례 - Parallel Query, 테이블 스페이스 핫백업(Tablespace Hot backup)

Parallel Query
Parallel Query 사용시 체크포인트 발생 이유 -> 슬레이브 세션에 의한 direct path read(버퍼 캐시를 거치지 않고 데이터 파일을 직접 읽는 것)때문
direct path read 사용하는 경우
- 메모리 영역에서 정렬 작업 완료 불가시 임시 세그먼트에 정보를 저장하고 읽는 과정에서 direct path write, direct path read 발생 : 이때의 대기이벤트는 direct path read temp, direct path write temp
- 슬레이브 세션이 데이터를 스캔하기 위해 데이터 파일을 직업 읽어들일때 direct path read : 이때 대기이벤트는 direct path read
- I/O 시스템의 성능 저하고 블록 읽는 속도 느릴때, 오라클이 임시 방편으로 direct path read를 사용함
슬레이브 세션이 직접 데이터를 가져오는 대상이 데이터 파일이다 -> 즉 메모리와 파일사이의 내용이 다르게 될 수도 있다 -> 따라서 읽기전에 체크포인트 발생하여 기록부터 한 뒤에 읽어온다 -> 이때하는 체크포인트는 세그먼트 레벨의 체크 포인트 -> 체크포인트 작업이 끝날때까지 코디네이터세션은 enq: TC - contention 이벤트 대기한다.
10gR2부터는 PQ수행시 체크포인트 알고리즘이 크게 개선되어 TC락 경합이 크게 줄어들었다.

테이블 스페이스 핫백업(Tablespace Hot backup)
alter tablespace ....... begin backup시 -> 테이블스페이스 내의 모든 데이터 파일에 대해 더티 블록을 디스크에 기록 (체크포인트) -> 이떄 enq: TC - contention 대기 이벤트

TC락 경합 원인은 성능상의 문제 보다는 인위적인 체크포인트 수행일 경우가 크다.


enq: CI - contention, enq: RO - contention
경합에 의해 발생하는 것이 아니라, 특정 작업중 선행 작업이 끝나는 것을 보장하기 위해 발생하는 대기 이벤트 중의 하나이다.
만약 특정 테이블을 truncate한다면 -> truncate 수행중 장애 발생시에도 복구가 가능해야 하므로, 버퍼 캐시에 있는 해당 테이블에 대한 더티 버퍼를 먼저 내려 써야할 것이다(체크포인트) -> 이 때에 실제 truncate작업을 진행하기 위해 체크포인트가 끝날때까지 대기해야한다. 이 대기 현상이 enq: CI - contention대기 이벤트
Cross Instance Function : 체크포인트 로그스위치 셧다운 등의 작업을 호출하는것
위의 펑션들은 각각 펑션마다 call, parameter, queue, return이라는 네개의 단계가 있고, 각 단계마다 락을 획득해야한다. 이 락을 CI 락이라고 부른다. CI 락을 획득하기 위해 기다리는 동안 enq: CI - contention 대기 이벤트가 발생한다. RAC 뿐 아니라 Single Instance 환경에서도 발생한다.
이는 경합에 의해 발생하는 것이 아니기 때문에 대체로 성능과는 크게 상관이 없다.
다만 일부 작업 (drop, truncate등)에서 체크포인트가 발생하여 -> 체크포인트 자체의 성능때문에 문제가 발생하여 enq: CI - contention대기 이벤트가 발생할 수도 있다.
체크포인트에 의한 enq: CI - contention대기 현상이 문제가 될 경우의 해결책
1. 오라클 10gR2로 업그레이드한다 -> 10gR2에서는 객체 체크포인트 알고리즘이 크게 개선되었다고한다.
2. DBWR의 성능을 개선시킨다
3. 버퍼 캐시의 크기가 불필요하게 크지 않은지 확인한다 -> 체크포인트를 수행하기 위해서 더티 버퍼를 탐색하게 되는데, 버퍼 캐시가 클수록 관리해야할 더티 버퍼의 양도 많아진다 -> 이때 체크포인트 작업이 지연되면 CI락 대기시간이 늘어나게 된다.

enq: RO - fast object reuse 대기 이벤트 -> 객체가 사용하는 공간(세그먼트)을 삭제하는 작업은 CKPT와 DBWR에 의해 실제로 삭제가 이루어질 때까지 기다리게 되는데 그동안 enq: RO - fast object reuse 이벤트를 대기하게 된다.

레이블 (0)

  • 레이블 없음

0 댓글

로그인 상태가 아닙니다. 변경하는 경우 익명으로 표기됩니다. 이미 계정이 있다면 로그인을 원하실 수 있습니다.

첨부 파일  (0)

첨부 파일 추가하기
공유된 파일이 아직 없습니다.