오라클에서 Latch는 Lock과 함께 잠금에 사용되는 장치이다. 그러나 Lock과 틀린것은 latch는 Lock보다 가볍고 SGA 내부의 공유 데이터에 대한 베타적인 잠금을 보장하여 (9i 이상에서는 cache buffer chains Latch는 읽기 전용일 경우 Shared 모드 가능), 메모리 구조의 무결성을 유지하도록 하는것이 목적이다. 따라서 한 순간에 하나의 프로세스만이 latch를 보유할 수 있다는 소리이다 . 또 , SGA에 접근하는 모든 프로세스는 반드시 해당 영역을 관장하는 Latch를 획득해야지만 접근이 가능하다.

 

Latch는 PID , Memory Address , Length로 구성된 메모리 객체이다.

또 Latch는 물리적으로 Shared Pool안에 존재하는 메모리 구조체 이다. Latch는 매우 간단하고 작은 메모리 영역을 사용한다.

 

Latch에는 Parent , Child , Solitary의 세가지 유형이 있다. Parent와 Solitary Latch는 오라클의 커널 코드 안에 정의 되어 있고 ,Child 래치는 인스턴스가 구동될 때 생성이 된다.

 

v$latch_parent , v$latch_children뷰는 Parent , Child Latch에 대한 통계정보가 저장된다.

v$latch는 세 가지 유형의 latch 통계정보를 확인 할 수 있다.

 

Latch는 Lock과 다른 점이 Deadlock이 존재를 하지 않는다는 것이다. 이것은 latch의 동작 메카니즘을 확인해 보면 알 수 있는데 

가령 하나의 Latch를 보유한 Process가 다른 latch를 획득하고자 한다면 반드시 현재 보유한 Latch 보다 높은 level의 Latch만을 획득해야 한다.

예를 들어보면 3이라는 Latch를 보유한 Process가 1 이라는 latch를 추가적으로 획득해야 한다면 Deadlock을 방지 하기 위하여 no-wait 모드로 획득을 시도해야 한다. 만약 no-wait모드로 획득 요청시 실패를 한다면 기존에 획득하고 있던 3 이라는 latch를 놓고 1 이라는 Latch를 획득 후 3 이라는 latch를 시도해야 한다.

 

Latch를 획득하려는 프로세스들은 Latch를 획득 하기 전까지는 계속해서 획득하기 위하여 시도를 하게 되는데 이 획득 하는 방법에 따라서

no-wait 모드와 willing-to-wait 모드가 존재 한다.

 

no-wait 모드로 획득을 시도하는 프로세스들에 대한 통계정보는 v$latch , v$latch_parent , v$latch_children과 같은 레치 관련 뷰의 Immediate_gets와 immediate_misses 컬럼값을 보면 알 수 있다. no-wait모드는 현재 자신이 가진 latch보다 낮은 level의 latch를 요구 할 시에 Deadlock발생을 방지 하기 위하여 획득 시도 후 실패 하면 더 이상 획득 시도를 하지 않는 다는 뜻이다. 좀 더 정확히 말하자면 현재 가지고 있는 latch의 level보다 낮은 level의 Latch를 획득하려고 할 경우 낮은 level의 latch 보다 큰 latch는 모두 해제 하고 낮은 level의 latch 부터 다시 획득을 시도 해야 한다.

 

willing-to-wait 모드로 획득된 Latch 정보는 Gets 와 Misses 컬럼에 통계정보를 저장한다. 일반적인 latch들이 모두 willing-to-wait 모드를 사용한다. gets는  willing-to-wait 모드로 latch를 요청할때 증가한다. 획득 실패시 misses 및 spin_gets값이 1 씩 증가 한다.

willing-to_wait 모드에서 사용되는 방법으로 두가지가 있는데 하나는 Spin 모드이고 다른 하나는 posting 모드 이다.

 

spin 모드는 latch를 획득할 수 있는 시간이 비교적 짧으리라는 기대 속에 처음 latch 획득 시도 후 실패 하면 짧은 시간 sleep-wake를 반복하면서 Latch를 획득 하려고 시도를 하는 것이다. 이 반복 횟수는 _spin_count 횟수 이며 기본값은 2000번이다.

일반적으로 이 모드로 Latch 획득을 시도 하는 것이 일반적이다. sleep했다가 wake 하는 시간 주기도 매번 같은 것이 아니라 어차피 sleep-wake하는 부분에 CPU를 사용하게 되므로 Latch 획득 시 사용하는 cpu 자원 소모를 줄이기 위하여 sleep-wake 횟수가 증가 할 수록 sleep 시간이 증가를 한다. 이 시간은 최대 2초 까지 증가를 한다. 참고로 cpu가 1개인 시스템에서는 spin을 수행하지 않는다. 따라서 확인해 보면 _spin_count도 1값을 나타낸다.

 

posting 모드는 spin 모드와는 다르게 latch 획득 실패 후 Latch wait list에 자신을 등록해 놓은 후 기존에 latch를 획득 하고 있던 Process가 작업이 끝난 후 깨워(post)주기를 바라는 모드이다. latch wait list에 등록이 되어 있다고 등록 순서대로 latch를 획득 할 수 있는 것이 아니라 그 순간 시도하는 process들 끼리 다시 경합을 하게 된다. 이 모드를 사용하는 것은 비교적 latch 사용 기간이 긴 shared pool , library cache latch들이 이 모드를 사용한다.

 

만약 latch를 획득하고 있던 process가 비 정상 종료 된 경우 latch 획득은 어떻게 되는가 ? 무한정 기다리거나 계속해서 spin을 수행하는가 ?

이런 부분때문에 latch cleanup 메카니즘이 필요한데 이는 latch를 획득 후 자신이 변경하고자 하는 부분과 목적을 latch recovery area에 등록을 해 놓는다. 그래서 process 비정상 종료 담당 pmon이 해당 비정상 프로세스가 사용하던 latch에 대해서 cleanup function을 호출하여 latch를 해제 한다. latch 시도를 4번이상 시도한 process는 pmon에게 해당 latch를 보유한 process가 살아 있는지에 대한 체크 요청을 시도 한다.  

 

Latch 획득 루틴은 반드시 Latch를 획득 하여야만 종료가 된다. 그래서 Latch Free Event들이 발생을 하는 것이고 이로 인하여 성능 이슈가 발생이 되는 것이다.

 

Latch 관련 성능 뷰는 다음과 같이 몇개가 존재 하는데 자세한 것은 Oracle Document를 참조 ..

 

v$latch / v$latch_parent / v$latch_children / v$latchholder / v$latch_missed

 

사용되는 Children Latch 종류 및 개수를 확인 하려면 다음 쿼리를 사용하면 된다.

다음의 쿼리 예는 Oracle 10g R2 에서 수행해본 결과 이다.

 

SQL>SELECT name , count(*) FROM v$latch_children GROUP BY name

NAME                                                        COUNT(*)
———————————– ——————–
enqueue hash chains                                          2
channel operations parent latch                         88
name-service namespace bucket                        32
cache buffers chains                                     1024
redo copy                                                         4
redo allocation                                                 20
intra txn parallel recovery                                 40
library cache pin                                                3
resmgr:session queuing                                       1
longop free list parent                                        2
session queue latch                                            1
sim partition latch                                              1
commit callback allocation                                 11
Shared B-Tree                                                  3
virtual circuit queues                                        6
job workq parent latch                                      3
JS queue access latch                                      13
session idle bit                                                 2
ksfv messages                                                  2
checkpoint queue latch                                    16
object queue header operation                          8
flashback copy                                                  6
undo global data                                               3
library cache lock allocation                               3
SQL memory manager workarea list latch           67
JS slv state obj latch                                         4
client/application info                                        2
OS process                                                      22
row cache objects                                           34
shared pool                                                      7
library cache hash chains                                  3
resmgr:actses change state                            150
resmgr:plan CPU method                                    2
shared pool sim alloc                                       17
post/wait queue                                               5
done queue latch                                              1
channel handle pool latch                                  1
granule operation                                            1
buffer pool                                                     8
simulator hash latch                                      32
transaction allocation                                    11
library cache lock                                            3
shared pool simulator                                    17
peplm                                                            3
session switching                                           4
msg queue latch                                             1
message pool operations parent latch             38
slave class                                                    6
msg queue                                                   18
simulator lru latch                                         8
global tx hash mapping                                 47
parallel query stats                                       2
business card                                               8
logminer context allocation                            1
In memory undo latch                                   18 
library cache                                                3
library cache pin allocation                            3
resmgr:actses change group                        150
parallel query alloc buffer                               4
cache buffers lru chain                                    8
object queue header heap                                8
kks stats                                                         4
resmgr:resource group CPU method                    1
JS Sh mem access                                            2

64 rows

 

위의 Latch 개수들은 SGA 크기 및 기타 CPU 개수 등 등 각각의 Oracle Server 환경마다 차이가 있을 수 있다.

단지 , 어떤 것들이 있는지 확인해 보기 위해서 쿼리를 수행해 보길 권한다.

 

실제 운영하면서 많이 보았을 만한 Latch 이름들이 보이리라 생각이 된다.

 

그럼 여기서 각각의 Latch 별 Event 설명을 하기 전에 간단히 Latch Free Event가 나타내는 항목을 확인해 보면

 

v$session_wait 뷰에서 latch Free Event가 나타난다는 것은 프로세스가 willing-to_wait 모드로 _spin_count에 지정된 수치만큼

반복해서 래치를 획득 하려고 시도를 하고 있으나 획득을 못하고 sleep 상태로 되어 있다는 뜻이다.

SPIN은 CPU job 이므로 여러 프로세스에서 동시에 같은 Latch에 대한 경합을 일으키면 latch를 획득하지 못한 프로세스들은 Spin을 시도 하기

때문에 그만 큼 CPU 사용률이 높아 진다.

 

Latch Free Event는 P1 , P2 , P3 인자를 가지고 나타나는데  각각의 뜻은 아래와 같다.

 – P1 : Latch Address

 – P2 : Latch Number

 – P3 : the Number of Tries

 

Latch Free Event가 발생하고 있을 당시에 P1RAW 값을 가지고 v$latch_children 뷰의 addr과 비교를 해보면 어떤 Latch를 획득하기 위해서

대기를 하고 있는지 확인이 가능하다.

 

P1값은 Address에 대한 십진수 이고 P1RAW값은 Address에 대한 Hex값이다

예를 들어 P1값이 536975932 이고 P1RAW값이 0000000020019A3C 이면 P1RAW값에서 앞에 0 을 빼고 넣어서 조회 하면 된다.

 

SELECT NAME , IMMEDIATE_GETS , IMMEDIATE_MISSES , GETS , MISSES , SPIN_GETS , SLEEPS
FROM   v$latch_children
WHERE addr = ‘P1 RAW’ ;

 

 

현재 Latch Holder에 대한 정보 확인 쿼리 입니다.

 

Latch holder의 세션 정보 및 수행하는 쿼리 확인

 

SELECT /*+ ORDERED */
       h.laddr AS latchaddress ,
       h.name ,
       s.username ,
       s.schemaname ,
       s.program ,
       s.sql_hash_value ,
       t.hash_value ,
       t.piece ,
       t.sql_text
FROM   v$latchholder h ,
       v$session s ,
       v$sqltext t
WHERE  h.sid = s.sid
AND    s.sql_address = t.address( + ) ;

 

SQL문이 있을 수도 없을 수도 있으므로 Outer 조인으로 해 줌

By haisins

오라클 DBA 박용석 입니다. haisins@gmail.com 으로 문의 주세요.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다