Oracle RAC Global Cache 대기 이벤트 분석: gc current request와 gc buffer busy 진단 가이드

Oracle RAC 환경에서는 여러 인스턴스가 하나의 데이터베이스를 공유하면서 각 인스턴스의 버퍼 캐시에 저장된 블록을 Global Cache Service를 통해 주고받는다. 이 구조는 서비스 확장성과 가용성을 높여 주지만, 동일한 데이터 블록에 여러 인스턴스의 요청이 집중되면 Global Cache 관련 대기 이벤트가 증가할 수 있다.
대표적인 이벤트가 gc current request와 gc buffer busy다. 두 이벤트 모두 다른 인스턴스에서 블록을 가져오는 과정과 관계가 있지만 발생 원인과 대응 방법은 다르다. 단순히 인터커넥트 속도만 의심하면 실제 원인인 핫 블록, 비효율적인 인스턴스 배치 또는 과도한 동시 갱신을 놓칠 수 있다. Oracle 19c RAC 운영 환경에서 두 이벤트를 구분하고 단계적으로 진단하는 방법을 정리한다.
RAC Global Cache와 블록 전송 구조 이해
일반적인 단일 인스턴스에서는 필요한 블록이 로컬 버퍼 캐시에 없을 때 데이터 파일에서 블록을 읽는다. RAC에서는 다른 인스턴스가 해당 블록을 이미 캐시에 보유하고 있다면 디스크를 다시 읽는 대신 인터커넥트를 통해 블록을 전달받을 수 있다. 이 과정을 Cache Fusion이라고 한다.
블록은 크게 일관된 읽기에 사용하는 CR 모드와 변경 가능한 최신 상태인 Current 모드로 전달된다. 조회 위주의 SQL에서는 gc cr request 계열 이벤트가 나타날 수 있고, INSERT·UPDATE·DELETE처럼 블록을 변경해야 하는 작업에서는 Current 블록 요청이 발생한다.
Global Cache 대기가 존재한다는 사실만으로 성능 장애라고 판단해서는 안 된다. RAC에서는 정상적인 블록 전송 과정에서도 관련 이벤트가 기록된다. 중요한 판단 기준은 대기 횟수보다 평균 대기시간, 전체 DB Time에서 차지하는 비율, 특정 인스턴스와 오브젝트에 대한 집중 여부, 장애 발생 전후의 증가 폭이다.
gc current request 발생 원인과 진단 방법
gc current request는 세션이 데이터 블록을 변경하기 위해 Current 모드로 요청하고 블록이 전달되기를 기다릴 때 관찰된다. 다른 인스턴스가 해당 블록을 보유하고 있거나 아직 변경 내용을 처리하는 중이라면 요청 세션의 대기시간이 길어질 수 있다.
빈번한 원인으로는 여러 인스턴스에서 동일한 테이블의 같은 블록을 동시에 갱신하는 경우, 증가형 키를 사용하는 인덱스의 우측 리프 블록에 INSERT가 집중되는 경우, 작은 테이블이나 인덱스에 DML이 몰리는 경우가 있다. 시퀀스의 캐시 값이 지나치게 작거나 애플리케이션이 특정 행을 반복 갱신하는 구조도 확인해야 한다.
실시간으로 대기 세션을 확인할 때는 다음과 같이 조회할 수 있다.
SELECT inst_id,
sid,
serial#,
event,
wait_class,
seconds_in_wait,
sql_id,
row_wait_obj#
FROM gv$session
WHERE event LIKE 'gc%'
ORDER BY seconds_in_wait DESC;
인스턴스별 누적 수치와 평균 대기시간은 다음 조회로 비교할 수 있다.
SELECT inst_id,
event,
total_waits,
time_waited_micro,
ROUND(time_waited_micro / NULLIF(total_waits, 0) / 1000, 2) avg_wait_ms
FROM gv$system_event
WHERE event LIKE 'gc%request%'
ORDER BY event, inst_id;
특정 인스턴스에서만 평균 대기시간이 높다면 해당 인스턴스의 CPU 포화, LMS 프로세스 지연, 인터커넥트 상태를 함께 살펴봐야 한다. 모든 인스턴스에서 특정 SQL 실행 시점에 동시에 증가한다면 오브젝트 경합이나 애플리케이션의 접근 패턴을 우선 의심하는 편이 효과적이다.
gc buffer busy가 의미하는 블록 경합
gc buffer busy는 필요한 블록에 대한 Global Cache 작업이 진행 중이어서 즉시 사용할 수 없는 상황에서 발생한다. 요청한 블록이 다른 인스턴스로 전송되고 있거나, 블록을 보유한 프로세스가 변경·롤백·핀 작업을 끝내지 못한 경우 대기시간이 길어질 수 있다. Oracle 버전과 세부 상황에 따라 gc buffer busy acquire 또는 gc buffer busy release처럼 구분되어 나타나기도 한다.
gc current request가 블록을 요청하고 전달받는 과정 자체에 초점을 둔다면, gc buffer busy는 요청된 블록이 바쁜 상태라 즉시 처리되지 못하는 경합 성격이 더 강하다. 따라서 인터커넥트 지연만 점검해서는 해결되지 않는 경우가 많다.
핫 블록을 찾을 때는 세그먼트 통계를 활용할 수 있다.
SELECT inst_id,
owner,
object_name,
subobject_name,
object_type,
statistic_name,
value
FROM gv$segment_statistics
WHERE statistic_name IN
('gc buffer busy',
'gc current blocks received',
'gc cr blocks received')
ORDER BY value DESC
FETCH FIRST 30 ROWS ONLY;
상위 오브젝트가 인덱스라면 단조 증가하는 키에 INSERT가 집중되는지 확인해야 한다. 테이블이라면 특정 행이나 제한된 블록에 UPDATE가 몰리는지, 파티션 키가 업무 트래픽을 충분히 분산하는지 점검한다. row_wait_obj#는 문제 오브젝트를 찾는 단서가 되지만 세션 상태가 빠르게 변하므로 여러 차례 수집해 반복적으로 등장하는 대상인지 확인하는 것이 좋다.
운영 중 적용한 트러블슈팅과 해결 방향
개인적으로 RAC의 Global Cache 문제를 분석할 때 가장 효과적이었던 방법은 네트워크부터 의심하기보다 시간대, SQL, 오브젝트, 인스턴스 순서로 범위를 좁히는 방식이었다. 실제 운영 사례에서도 gc current request가 증가해 인터커넥트 문제로 보였지만, 원인은 두 인스턴스에서 동일한 업무 테이블의 상태 행을 짧은 주기로 갱신하던 애플리케이션 로직이었다.
우선 gv$session을 일정 간격으로 조회해 대기 세션의 sql_id, inst_id, row_wait_obj#를 수집했다. 이후 SQL 실행 계획과 gv$segment_statistics를 비교하자 하나의 테이블과 인덱스에서 Global Cache 관련 수치가 집중된 것을 확인할 수 있었다. 서비스를 특정 인스턴스로 일시적으로 배치했을 때 대기가 크게 줄어들어 블록 핑 현상임을 검증했다.
최종적으로는 관련 업무를 하나의 RAC 서비스에 묶어 인스턴스 친화도를 높이고, 불필요하게 반복되던 UPDATE를 줄였다. 커밋 주기도 업무 정합성이 허용하는 범위에서 조정했다. 단순히 인스턴스 자원을 증설하거나 인터커넥트를 변경하지 않고도 Global Cache 대기와 응답시간이 함께 감소했다.
증가형 인덱스의 우측 리프 블록이 문제라면 Reverse Key Index를 검토할 수 있지만 범위 검색이 제한되는 단점이 있다. 해시 파티셔닝이나 업무 키 분산도 대안이 될 수 있으나 운영 구조와 조회 패턴을 함께 검토해야 한다. 시퀀스를 사용한다면 CACHE 값을 충분히 확보하고 RAC에서는 NOORDER 적용 가능 여부를 확인하는 것이 좋다.
인터커넥트 진단도 필요하다. 패킷 손실, 네트워크 오류, 비정상적인 지연, MTU 불일치 여부를 운영체제와 네트워크 계층에서 확인하고 LMS 프로세스가 CPU 스케줄링 지연을 겪는지도 살펴야 한다. 다만 네트워크가 정상이라면 문제의 중심은 대부분 데이터 접근 구조와 블록 소유권 이동에 있다.
Oracle Standard Edition 환경처럼 Diagnostic Pack 사용이 제한되는 경우에는 AWR·ASH에 의존하지 않고 GV$SESSION, GV$SYSTEM_EVENT, GV$SEGMENT_STATISTICS, 실행 계획과 Statspack을 조합해 분석해야 한다. 라이선스 범위를 먼저 확인하는 것도 운영 진단 절차의 중요한 부분이다.
마치며
gc current request와 gc buffer busy는 모두 RAC 인스턴스 사이의 블록 이동과 관련되지만 동일한 원인으로 처리하면 안 된다. 전자는 Current 블록 요청과 전송 지연을 중심으로 보고, 후자는 블록이 다른 작업으로 바쁜 상태인지와 특정 블록의 동시 경합을 집중적으로 살펴봐야 한다.
효율적인 분석 순서는 장애 시간대의 이벤트 증가 확인, 인스턴스별 평균 대기시간 비교, 관련 SQL 식별, 핫 오브젝트 확인, 서비스 배치와 데이터 접근 패턴 검토다. 인터커넥트와 LMS 상태는 이 과정에서 함께 검증하되 모든 Global Cache 문제를 네트워크 문제로 단정하지 않는 것이 중요하다.
RAC 성능 개선의 핵심은 블록을 더 빠르게 전송하는 것만이 아니라 블록이 인스턴스 사이를 불필요하게 이동하지 않도록 설계하는 데 있다. 서비스 기반 워크로드 분리, 핫 블록 완화, 인덱스와 파티션 구조 개선, 반복 갱신 제거를 함께 적용하면 Global Cache 대기를 안정적으로 줄일 수 있다.




댓글 0
첫 댓글을 남겨보세요.