IT기술/Oracle

02 래치 (Latch) 와 락 (Lock)

dobbby 2014. 1. 27. 11:29
반응형

1. 오라클의 동기화 매커니즘

오라클은 거대한 동기화 (Synchronization) 머신이다.

래치와 락의 존재 이유는 동시 작업으로부터 오라클의 자원을 보호하는 것이다.


분류 

 래치 (latch)

락 (lock) 

목적

메모리 구조에 대한 배타적인 접근을 위함

(9i 부터 cache buffers chains latch 들은 읽기 전용시에 공유가 가능함)

락 모드가 호환 가능하면 다수의 프로세스가 동일한 리소스를 공유하는 것을 허용

락 모드가 호환 가능하지 않으면 리소스에 대한 배타적인 접근만 허용 

 사용범위

SGA 내부의 데이터 구조에만 적용

메모리 오브젝트를 임시적으로 보호함

단일 오퍼레이션으로 메모리 구조에 대한 접근 제어

트랜잭션 단위가 아님

테이블, 데이터 블록 및 state object 와 같은 오브젝트를 보호

데이터베이스의 데이터 또는 메타데이터 접근 제어

트랜잭션 단위 

 획득방식

willing-to-wait 또는 no-wait

null, row share, row exclusive, share, 

share row exclusive 또는 exclusive 

 범위

SGA 내부에 정보가 존재하며, 로컬 인스턴스에만 볼 수 있음 - 래치는 인스턴스 레벨로 작동 

데이터베이스 내부에 정보가 존재하며, 모든 인스턴스에서 볼 수 있음 - 락은 데이터베이스 레벨에서 작동 

복잡도

단순한 명령어를 사용하여 구현됨

일반적으로 test-and-set, compare-and-swap 또는 단순한 CPU 명령어

구현이 쉬움 

문맥교환 (context switch)  을 포함한 일련의 명령어들을 사용하여 구현됨

구현이 복잡함

지속기간

아주 짧은 순간만 지속됨

(microsecond 단위) 

일정 시간 동안 지속됨 (트랜잭션 동안) 

큐 (Queue) 

프로세스가 래치 획득을 실패한 후 슬립 (sleep) 상태로 들어갈 때, 해당 요청은 큐 (queue) 로 관리되지 않으며, 요청한 순서대로 서비스되지 않음 (latch wait list 를 이용하여 큐 방식으로 사용되는 래치들은 예외임) 

프로세스가 락 획득을 실패한 후, 해당 요청은 큐 (queue) 로 관리되며, 요청한 순서대로 서비스됨 (NOWAIT 모드는 예외임) 

 데드락

래치는 데드락 (deadlock) 이 발생되지 않도록 구현됨

락은 큐 (queue) 방식을 사용하며, 데드락이 발생될 가능성이 높다. 데드락이 발생될 때마다 트레이스 파일 생성 




2. 래치 (Latch)

1) 래치란?

래치는 유닉스 OS 에서 제공하는 뮤텍스 (Mutex: Mutually Exclusive) 와 같이, 

아주 빠르고 가볍게 특정 리소스에 대한 동기화를 구현하기 위해 고안된 객체이다.

물리적으로 Shared Pool 영역에 존재하는 일종의 메모리 구조체이다.

오라클은 래치와 관련된 작업들의 부하를 최소화하기 위해 래치 획득의 순서를 보장하지 않는다.


2) 래치가 보호하는 리소스

래치가 보호하는 리소스는 SGA 이다.

SQL 을 Shared Pool 의 library cache 영역에 올리기 위해 필요한 Heap 메모리 영역을 할당받기 위해서 반드시 shared pool 래치를 획득해야 한다.

Select 문을 통해 특정 데이터블록을 읽기 위해서 DBA와 클래스에 해당하는 해시 체인에 접근하고자 하는 프로세스는 

반드시 해당 해시 체인을 관장하는 cache buffer chain 래치를 획득해야 한다.

DML 을 통해 데이터를 변경한 모든 프로세스는 PGA 영역에 리두(Redo) 데이터를 생성하는데, 

이 리두 데이터를 리두 버퍼(Redo buffer) 로 복사하기 위해서 반드시 redo copy 래치 획득해야 한다.


래치 획득 실패 프로세스는 래치를 획득할 수 있을 때까지 특정 이벤트를 기다린다.

9i 항상 latch free 대기 이벤트 사용,

10g 부터 별도의 대기이벤트 사용, 나머지 latch free 대기 이벤트를 사용한다.


부모 (Parent) 래치 : 여러 개의 자식 래치를 거느리는 래치

독립 (Solitary) 래치 : 전체 인스턴스에 단 하나만 존재하는 래치

자식 (Child) 래치 : 부모 래치에 속한 래치


부모, 독립 래치는 V$LATCH_PARENT 뷰를 통해 관찰가능

자식 래치는 V$LATCH_CHILDREN 뷰를 통해 관찰가능

해당 버전의 특정 래치가 어디에 해당하는지 위의 뷰들을 통해 확인하는 것이 좋다.


락 자체도 SGA 의 Shared Pool 영역에 존재하는 메모리 구조체이기 때문에 래치를 통해서 보호받는다.


3) 래치 동작 메커니즘

오라클은 래치 획득 과정에서의 데드락을 원천적으로 방지하기 위해 모든 래치에 레벨을 부여한다.

- 래치 레벨

0 ~ 13까지, 한 개 이상의 래치를 보유한 상태에서 또 다른 래치를 획득하고자 하는 프로세스는

가장 최근에 획득한 래치보다 높은 레벨의 래치만을 획득해야 한다.

만일 어던 이유로 인해 현재 보유한 래치보다 낮거나 같은 레벨의 래치를 획득하려면

No-wait 모드로 획득하게 함으로써 데드락으로 인해 무한 대기하는 현상을 방지한다.


- 래치 모드

래치는 기본적으로 Exclusive 모드를 사용

cache buffers chains 래치는 읽기작업인 경우에는 Shared 모드 사용


- 래치 획득

* Willing-to-wait 모드의 래치 획득

기본적으로 Willing-to-wait 모드 사용, 래치를 획득할 수 있을 때까지 대기한다는 의미다.


최초의 래치 획득 실패시 곧바로 슬립하지 않고 스핀을 수행하는 이유는 

첫째, 아주 빠른 시간 안에 다른 프로세스가 래치를 해지할 것이라고 기대하기 때문이며

둘째, 슬립상태로 빠지게 되면 OS 차원에서 Context switching 이 발생하게 되는데 

이 비용이 약간의 CPU 를 소모하면서 스핀을 수행하는 것보다 훨씬 비싸기 때문이다.

래치 경합이 발생하는 상황에서의 높은 CPU 사용률은

실제 작업을 하는 과정에서 발생하는 것이 아니라,

래치 획득을 위해 스핀을 수행하는 과정에서 유발된다는 점에 주의해야 한다.


스핀을 시도하고도 래치를 획득하는데 실패한 프로세스는 슬립상태로 바뀐다.

슬립 상태란 프로세스가 CPU 사용을 포기한다는 의미다.

슬립상태의 프로세스가 깨어나는 방법

첫째 약속된 시간이 되면, 즉 타임아웃이 발생하면 다시 깨어나서 래치를 획득하기 위해 다시 시도한다.

둘째 래치 대기목록에 자신을 등록해 놓고 다른 프로세스가 깨워주기를 기다린다.

대부분 래치는 첫째 방법, shared pool 래치나 library cache 래치와 같은 일부 래치는 두번째 방법 사용한다.


* No-wait 모드의 래치 획득

현재 다른 래치들을 보유하고 있는 프로세스가 현재 보유한 래치 중 

가장 최근에 획득한 래치보다 더 낮거나 같은 레벨의 래치를 획득하고자 할 때는 No-Wait 모드로 획득을 시도한다. 

이러한 경우에 No-Wait  모드를 사용하는 것은 데드락을 피하기 위해서이다.


- 래치 Cleanup

공유 메모리 훼손은 매우 심각한 문제이기 때문에 오라클은 래치를 Cleanup 하는 매커니즘을 제공한다.

프로세스가 래치를 보유한 채로 종료하면 PMON 은 각 래치마다 구현되어 있는 Cleanup function 을 호출한다.

공유 메모리 영역을 원래 상태로 복구하고 작업이 끝나면 PMON 은 래치를 해지한다.


4) 래치 관련 Dynamic Views

V$LATCH 뷰는 모든 래치들의 통계에 대한 합계치 정보 제공

V$LATCH_PARENT 뷰는 독립 래치에 대한 통계값 제공

V$LATCH_CHILDREN 뷰는 모든 개별 자식 래치들에 대한 통계값 제공


cache buffers chains 래치와 같이 여러 개의 자식 래치 거느리는 래치는 

V$LATCH 뷰를 통해 합계치를 조회하거나 V$LATCH_CHILDREN 뷰를 통해 개발 자식 래치의 통계값을 확인

redo writing 래치와 같은 독립 래치는 

V$LATCH_PARENT 뷰를 통해 통계값을 확인할 수 있으며 V$LATCH 뷰와 똑같은 값을 갖는다.


5) 일반적인 래치 관련 대기이벤트들

- latch: cache buffers chains

버퍼 캐시에서 특정 블록을 탐색하고자 하는 프로세스는 cache buffer chains 래치를 획득해야 한다.

이 과정에서 경합이 발생하면 대기하는 이벤트


- latch: cache buffers lru chain

버퍼 캐시에서 프리 버퍼와 더티 버퍼를 탐색하고자 하는 프로세스는 cache buffers lru chain 래치를 획득해야 한다.

이 과정에서 경합이 발생하면 대기하는 이벤트


- latch: shared pool

shared pool 의 힙 영역에서 새로운 청크를 할당받고 자 하는 프로세스는 shared pool 래치를 획득해야 한다.

이 과정에서 경합이 발생하면 대기하는 이벤트


- latch: library cache

library cache 영역을 탐색하고자 하는 프로세스는 library cache 래치를 획득해야 한다.

이 과정에서 경합이 발생하면 대기하는 이벤트


- latch: redo copy

DML 에 의한 변동사항을 리두 버퍼에 기록하고자 하는 프로세스는 작업의 전 과정 동안 redo copy 래치를 획득해야 한다.

이 과정에서 경합이 발생하면 대기하는 이벤트




3. 락 (Lock)

1) 락의 분류

락은 매우 쉬운 개념이지만, 실제로는 상당히 혼란스러운 면이 있다.

이 혼란은 첫째, 락에 대한 정확한 분류가 존재하지 않는다는 것과

둘째, Enqueue 락과 일반 락과의 정확한 구분이 존재하지 않는다는 것에 기인한다.


- Enqueue 락

User Type Lock : TX, TM, UL

System Type Lock : CF, US, CI, TC, JS, ...


- 일반 락

row cache lock

library cache lock, library cache pin

buffer lock


2) 락이 보호하는 리소스

래치가 SGA 를 보호한다면, 락은 데이터베이스 전체를 보호한다고 할 수 있다.

테이블, 트랜잭션, 언두 세그먼트, 테이블스페이스, 잡(Job) 등 데이터베이스 단위에서 필요한 대부분의 리소스들은 락의 보호를 필요로 한다.


Enqueue 락이 보호하는 리소스는 <ResourceType-ID1-ID2> 라는 형태의 리소스 구분자로 정의된다.

락의 이름이 리소스 이름과 일치한다는 사실을 기억하자.


일반 락의 발생 여부 및 경합 여부를 알 수 있는 가장 좋은 방법은 V$SESSION_WAIT 뷰에서 대기현상이 발생하는지 관찰하는 것이다.


3) 락 동작 메커니즘


- 락 모드

락이 보호하는 리소스는 대단히 복잡한 경우가 많기 때문에 이 리소스를 보호하기 위한 방법 또한 복잡할 수 밖에 없다.

락 획득시 사용가능한 모드는 다음과 같다.


 모드 

 설명

 

 None 

 

 Null (N)

 

 Sub-Shared (SS) 또는 Row-Shared (RS) 

 3

 Sub-Exclusive (SX) 또는 Row-Exclusive (RX) 

 4

 Shared (S) 

 5

 Shared-Sub-Exclusive (SSX) 또는

 Shared-Row-Exclusive (SRX) 

 6

 Exclusive (X)


락 모드 호환성 표를 정리하면 다음과 같다.



 

SS 

SX 

SSX 

SS 

SX 

SSX 



- 락 획득

Enqueue 락 획득에 실패한 프로세스는 자신을 Enqueue 리소스의 대기목록 (Waiter List) 에 등록한다.

현재 락을 보유한 프로세스는 락의 사용이 끝나면 락을 해제하고 Enqueue 리소스의 대기목록에서 다음 프로세스를 깨워준다.

락 획득에 실패한 프로세스는 대기목록에 대기상태에 들어갈 때 특정 타임아웃 값을 지니는 알람을 설정한다.

Enqueue 락의 경우에는 타임아웃 시간은 3초이다.

만일 락을 보유한 세션이 3초가 지난 후에도 락을 해제하고 깨워주지 않으면 타임아웃에 의해 3초 후 스스로 깨어난다.

깨어난 프로세스는 데드락이 발생했는지의 여부를 확인한 후 다시 대기살태로 돌아간다.

락을 획득하기 위해 기다리는동안 프로세스는 리소스 유형에 따라 enq: XX-YYYYY 이벤트를 대기하게 된다.

10g 부터는 모든 Enqueue 리소스 유형에 대해 별도의 대기이벤트를 등록했으며,

같은 리소스 유형에 대해서도 상황에 따라 대기이벤트를 세분화해서 정의하고 있다.

가령 같은 TX 락 경합이라고 하더라도 경합이 발생하는 상황에 따라 

enq: TX-row lock contention, enq: TX-allocation ITL entry, enq: TX-index contention, enq: TX-contention 이벤트가 별도로 정의되어 있다.


4) 락 관련 Dynamic Views

Enqueue 락과 관련한 최고의 뷰는 V$LOCK 뷰이다. 이 뷰를 잘 조회하면 Enqueue 락과 관련된 모든 정보를 얻을 수 있다.

V$LOCKED_OBJECT 뷰는 현재 시스템의 모든 트랜잭션에 의해 획득 중인 TM 락에 대한 정보를 제공한다.

V$ENQUEUE_LOCK 뷰는 V$LOCK 뷰와 거의 동일하지만, 실제 Enqueue 현상, 즉 블로킹이 발생한 경우 대기세션에 대한 정보만 조회된다.


5) 일반적인 락 관련 대기이벤트들

10g 부터는 Enqueue 락에 의한 대기현상들은 모두 개별 대기이벤트로 나뉘어서 정의되었으며 심지어 락 경합이 발생하는 상황 별로 나누어진 경우도 있다.





반응형