Enqueue

EXEM Knowledge Base

Jump to: navigation, 찾기

목차

[편집] Basic Info

오라클은 Enqueue 락을 이용해 오브젝트를 보호한다. 오라클은 특정 오브젝트를 사용하기 위해 반드시 해당 오브젝트를 보호하는 Enqueue 락을 획득해야 한다. 만일 Enqueue 락을 획득하지 못하면 enqueue 이벤트를 대기한다. enqueue 대기 이벤트는 오라클 9i까지만 사용되며, 오라클 10g부터는 Enqueue 락에 의한 대기현상들은 모두 개별 대기이벤트로 나뉘어서 정의되었으며 심지어 락 경합이 발생하는 상황 별로 나누어진 경우도 있다. 가령 TX 락에 의한 대기현상은 enq: TX - row lock contention, enq: TX - allocate ITL entry, enq: TX - index contention, enq: TX - contention 네 개의 이벤트로 구분되었다. V$SESSION_WAIT 뷰나 V$SESSION 뷰를 이용하면 현재 어떤 락에 대한 경합이 발생하고 있는지 정확하게 알 수 있다. EVENT 컬럼의 값이 “enqueue”이거나 “enq: XXX”이면 Enqueue 락에 의한 경합이 발생한다는 의미이다. V$SESSION_WAIT 뷰의 P1 컬럼 값이 Enqueue 락의 “name|mode”를 의미한다. 다음과 같은 SQL문을 이용해 판독 가능한 값으로 변환할 수 있다.

SQL> select chr(bitand(P1,-16777216)/16777215) ||
chr(bitand(P1,16711680)/65535) "Name",
bitand(P1, 65535) "Mode"
from dual;

V$SESSION_WAIT 뷰의 P2 컬럼은 V$LOCK의 ID1, P3 컬럼은 V$LOCK의 ID2 컬럼과 일치한다. ID1, ID2 값은 Enqueue 락의 종류마다 다르다. 오라클 10g부터는 V$LOCK_TYPE 뷰를 이용해 특정 Enqueue 락의 ID1과 ID2 컬럼 값의 의미를 알 수 있다. enqueue 대기이벤트를 해소하는 방법은 경합이 발생한 Enqueue 락의 종류에 따라 다르다.

[편집] Parameter & Wait Time

[편집] Wait Parameters

  • P1 : Enqueue 정보
  • P2 : Enqueue Resource ID1
  • P3 : Enqueue Resource ID2

[편집] Wait Time

최대 3초까지 기다린다. 만일 Enqueue 락을 획득하기 못하면 획득할 때까지 대기한다.


[편집] Check Point & Solution

[편집] Event Tip

[편집] 락의 분류

락은 매우 쉬운 개념이지만, 실제로는 상당히 혼란스러운 면이 있다. 이 혼란은 첫째, 락에 대한 정확한 분류가 존재하지 않는다는 것과 둘째, Enqueue 락과 일반 락과의 정확한 구분이 존재하지 않는다는 것에 기인하다. 이 두 가지 문제를 먼저 이야기해보자. 오라클 Concept 매뉴얼에서는 락을 다음과 같이 분류하고 있다.

  • DML Lock
  • Row Locks(TX)
  • Table Locks(TM)
  • DDL Lock
  • Latches and Internal Locks
  • Latches
  • Internal Locks
  • Dictionary Cache Locks
  • File and Log Management Locks
  • Tablespace and Rollback Segment Locks

위의 분류는 상당히 논리적인 측면이 강하며, 락의 활용도를 이해하는 데는 도움이 되지만 락의 실제 작동 메커니즘을 이해하는 데는 오히려 혼란을 야기하는 측면이 있다. Steve Adams는 자신의 저서 “Oracle8i Internal Services for Waits, Latches, Locks, and Memory” 에서 다음과 같이 락을 분류하고 있다.

  • Enqueue Locks
  • Row Cache Enqueues
  • Library Cache Locks and Pins
  • DML Locks
  • Buffer Locks
  • Sort Locks

이 분류는 기본적으로 Enqueue 락과 일반 락을 구분하고, 일반 락을 다시 row cache lock, library cache lock/pin, dml lock, buffer lock, sort lock 을 구분하고 있다. 이 분류의 가장 핵심적인 기준은 Enqueue 구조로 관리되는 락과 그렇지 않은 락을 구분하는데 있다. 이 구분을 이해하기 위해서 Enqueue 락과 일반 락의 차이점을 알아보자. Enqueue 락은 Enqueue 구조로 관리되는 락을 말한다. 오라클 10g부터는 대부분의 Enqueue 락에 대해 개별 대기이벤트가 등록되므로 v$event_name 뷰를 조회하면 어떤 종류의 Enqueue 락이 존재하는지 알 수 있다. Enqueue 구조체는 Shared Pool 영역에 저장되며 아래 그림과 같은 구조를 갖는다.

그림:My_enqueue.jpg

그림 Enqueue 구조 Enqueue 락은 <ResourceType-ID1-ID2>를 리소스로 사용한다. 가령 하나의 TM 락은 하나의 테이블을 보호하는데 이 테이블을 유일하게 구분하는 리소스 구분자(Resource Idenitifer)로 <TM-Table's object id-0>의 값을 사용한다. 하나의 인스턴스에 수많은 Enqueue 락이 존재할 수 있기 때문에 그림2와 같이 해시 체인(Hash chain) 구조를 사용한다. 즉 <ResourceType-ID1-ID2>의 리소스 구분자에 해시함수를 적용해서 버킷(Bucket)을 할당하고, 하나의 버킷은 해시 체인 형태로 여러 개의 리소스 구조체를 거느린다. 각 리소스 구조체는 리소스 자체에 대한 정보와 이 리소스에 대한 락을 보유한 프로세스 목록, 대기하고 있는 프로세스 목록, 락 모드를 변경한 프로세스 목록을 거느린다. 이 구조를 이용해서 오라클은 특정 리소스에 대해 정밀한 동기화 메커니즘을 구현한다.

반면, Enqueue 락과 동일한 목적을 가지면서도 다른 방식으로 구현되는 락들이 있다. row cache lock이 대표적인 경우이다. Shared PoolRow Cache 영역을 보호하기 위해 오라클은 row cache lock을 사용하는데, row cache lock은 Enqueue 영역에서 통합 관리하지 않고 개별 Row Cache 메모리 영역 자체에 보유프로세스목록(Owner List)과 대기프로세스목록(Waiter List)을 관리한다. 이런 방식으로 작동하는 락들에는 row cache lock, library cache lock, library cache pin, buffer lock 등이 있다.

본 도움말에서는 위의 두 가지 분류법을 적절히 재구성한 다음과 같은 분류를 사용한다.

  • 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

[편집] 락이 보호하는 리소스

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

Enqueue 락이 보호하는 리소스는 <ResourceType-ID1-ID2>라는 형태의 리소스 구분자로 정의된다. 락의 이름이 리소스 이름과 일치한다는 사실을 기억하자. 가령 TM 락은 TM(테이블)리소스를 보호한다. TX 락은 TX(Transaction) 리소스를 보호하며, US 락은 US(Undo Segment) 리소스를 보호한다. 리소스 구분자를 구성하는 ID1과 ID2의 값은 리소스 유형에 따라 다르며 각 리소스를 유일하게 구분할 수 있는 값을 사용한다. 대표적인 리소스 유형과 구분자의 의미는 다음과 같다.

TM 락: ID1=Object id
TX 락: ID1=USN<<16|SLOT, ID2=Sequence
US 락: ID1=USN
HW 락: ID1=Tablespace#, ID2=DBA of Undo Segment Header
...

Enqueue 락 경합이 발생한 경우 V$LOCK 뷰의 TYPE, ID1, ID2 값이 리소스 구분자 역할을 하며 이 값을 이용해 정확하게 어떤 리소스에 대해 락 경합이 발생하고 있는지 관찰할 수 있다. V$SESSION_WAIT 뷰의 P1, P2, P3 에서도 같은 정보를 얻을 수 있는데, P1=name|mode 이며, P2=ID1, P3=ID2 의 값이다.

Enqueue 락이 아닌 일반 락인 경우에는 별도의 리소스 구조체가 존재하지 않기 때문에 이를 구분하기 위한 리소스 구분자도 존재하지 않는다. 또한 V$LOCK과 같은 통합된 뷰를 통해서 관찰하는 것도 불가능하다. 일반 락의 발생여부 및 경합여부를 알 수 있는 가장 좋은 방법은 V$SESSION_WAIT 뷰에서 대기현상이 발생하는지 관찰하는 것이다. 가령 buffer lock 경합이 발생하면 buffer busy waitsread by other session 이벤트에 대한 대기현상이 발생한다. row cache lock 경합은 row cache lock 이벤트로, library cache locklibrary cache pin 에서의 경합은 library cache lock 이벤트와 library cache pin 이벤트로 관찰된다.

[편집] 락 동작 메커니즘

[편집] 락 모드

락이 보호하는 리소스는 대단히 복잡한 경우가 많기 때문에 이 리소스를 보호하기 위한 방법 또한 복잡할 수 밖에 없다. 이러한 복잡성을 관리하기 위해 오라클은 락을 획득하는 모드를 다양하게 구성한다. 락 획득 시 사용 가능한 모드는 다음과 같다.

모드설명
0 None
1 NUll(N)
2 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)

가령 테이블 변경하고자 하는 프로세스는 해당 테이블에 대해 TM 락을 Exclusive하게 획득해야 한다. 테이블에 대해 DML을 수행하고자 하는 프로세스는 TM 락을 Sub-Exclusive 모드로 획득해야 한다. Sub-Exclusive 모드간에서 상호 호환성이 있기 때문에 동시에 여러 프로세스가 하나의 테이블에 대해 DML을 수행하는 것이 허용된다. 락 모드간에 같이 사용될 수 있는지의 여부를 락 모드 호환성이라고 부르며, 오라클은 락 모드 호환성을 이용해서 리소스에 대한 복잡한 작업들을 동기화한다.

[편집] 락 모드 호환성

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

N SS SX S SSX X
N O O O O O O
SS O O O O O X
SX O O O X X X
S O O X O X X
SSX O O X X X X
X O X X X X X


락에 대한 경합을 이해하려면 락의 모드 및 호환성에 대한 정확한 이해가 필요하다. 가령 특정 프로시저를 실행하는 프로세스는 프로시저에 해당하는 Library Cache Object에 대해 library cache pinShared 모드로 획득해야 한다. 반면 프로시저를 컴파일하려는 프로세스는 library cache pinExclusive하게 획득해야 한다. Shared 모드와 Exclusive 모드는 호환성이 없기 때문에 트랜잭션이 왕성한 시스템에서 프로시저를 컴파일하게 되면 library cache pin에 의한 경합이 발생하게 된다.

[편집] 락 획득

Enqueue 락 획득에 실패한 프로세스는 자신을 Enqueue 리소스의 대기목록(Waiter List)에 등록한다. 현재 락을 보유한 프로세스는 락을 사용이 끝나면 락을 해제하고 Enqueue 리소스의 대기목록에서 다음 프로세스를 깨워준다. 락 획득에 실패한 프로세스는 대기목록에 대기상태에 들어갈 때 특정 타임아웃 값을 지니는 알람을 설정한다. Enqueue 락의 경우에는 타임아웃 시간은 3초이다. 만일 락을 보유한 세션이 3초가 지난 후에도 락을 해제하고 깨워주지 않으면 타임아웃에 의해 3초 후 스스로 깨어난다. 깨어난 프로세스는 데드락이 발생했는지의 여부를 확인한 후 다시 대기상태로 돌아간다. 락을 획득하기 위해 기다리는 동안 프로세스는 리소스 유형에 따라 enq: XX - YYYYY 이벤트를 대기하게 된다. 오라클 10g부터는 모든 Enqueue 리소스 유형에 대해 별도의 대기이벤트를 등록했으며, 같은 리소스 유형에 대해서도 상황에 따라 대기이벤트를 세분화해서 정의하고 있다. 가령 같은 TX 락 경합이라고 하더라도 경합이 발생하는 상황에 따라 enq: TX - row lock contention, enq: TX - allocate ITL entry, enq: TX - index contention, enq: TX - contention 이벤트가 별도로 정의되어 있다.

Row cache lock과 같은 일반 락도 Enqueue 락과 기본적으로 같은 방식으로 작동한다. 다만, 락의 종류에 따라 타임아웃 시간이 모두 다르다. Buffer lock은 일반적으로는 타임아웃이 1초이지만, 연속적으로 buffer lock을 획득하기 위해 대기하는 경우에는 3초이다. Row cache lock은 60초까지 기다리며, library cache lock과 library cache pin은 일반 프로세스에서는 3초를 기다리지만, PMON 프로세스의 경우에는 타임아웃이 1초이다. 래치는 레벨이라는 메커니즘을 통해서 데드락이 발생하는 것을 원천적으로 방지하지만, 락은 데드락의 가능성이 항상 존재한다. 따라서 락을 대기하는 프로세스는 정해진 시간이 되면, 즉 타임아웃이 발생하면 깨어나서 데드락이 발생했는지의 여부를 체크한다. 만일 데드락으로 판정되면 데드락을 발견한 프로세스의 락 요청은 취소되고, 전체 트랜잭션이 아닌 현재 SQL 문장이 롤백된다. 그리고 alert 로그파일에 데드락 정보를 남긴다.

[편집] 락 관련 Dynamic Views

Enqueue 락과 관련한 최고의 뷰는 V$LOCK 뷰이다. 이 뷰를 잘 조회하면 Enqueue 락과 관련된 모든 정보를 얻을 수 있다. 따라서 이 뷰를 정확하게 이해하는 것이 중요하다. 아래는 동일 로우 업데이트에 의해 TX 락 경합이 발생한 경우를 V$LOCK 뷰를 통해 관찰한 예이다.

SQL> select sid, type, ID1, ID2, lmode, request, ctime, block from v$lock where type = 'TX';
SID TYP        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------- --- ---------- ---------- ---------- ---------- ---------- -
143 TX      852011       9963          0          6         60          0
153 TX      852011       9963          6          0         69          1 

153번 세션은 <TX-852011-9963> 리소스에 대해 Exclusive 모드(lmode=6)로 락을 획득한지 69초가 지났으며 다른 락을 블로킹(block=1)하고 있다. 143번 세션은 같은 리소스 <TX-852011-9963>에 대해 Exclusive 모드(request=6)으로 락을 요청한지 60초가 지났다. 즉 153번 세션이 획득한 TX 락이 143번이 요청하는 TX 락을 통해 블로킹하고 있다.

V$LOCKED_OBJECT 뷰는 현재 시스템의 모든 트랜잭션에 의해 획득 중인 TM 락에 대한 정보를 제공한다. 이 뷰는 OBJECT_ID 컬럼을 통해 관련된 오브젝트를 직관적으로 조회할 수 있다. 따라서, 락이 걸린 테이블을 조회할 때 유용하다. V$ENQUEUE_LOCK 뷰는 V$LOCK 뷰와 거의 동일하지만, 실제 Enqueue 현상, 즉 블로킹이 발생한 경우 대기세션에 대한 정보만 조회된다. 즉 어떤 세션이 락을 대기하기 위해 큐에서 대기하고 있는지의 정보만 나온다. 따라서 V$LOCK에 비해 정보의 범위가 떨어진다. 블로킹 관계를 손쉽게 관찰할 수 있는 다른 뷰로는 DBA_WAITERS 뷰가 있다.

락은 래치와는 달리 매우 다양한 리소스를 보호하기 때문에 정확한 정보를 얻기 위해서 많은 정보를 필요로 한다. 리소스 유형에 따라 DBA_OBJECTS, DBA_TABLESPACES, V$SESSION, V$TRANSACTION, V$UNDOSTAT, V$SQL 등 많은 종류의 뷰들을 같이 관찰할 필요가 있다.

Enqueue 락이 아닌 경우에는 V$LOCK 뷰와 같은 통합적인 뷰는 존재하지 않는다. library cache lock의 경우에는 DBA_DDL_LOCKS 뷰나 DBA_KGLLOCK 뷰, 또는 X$KGLLK 뷰를 통해 관찰이 가능하다. library cache pin은 DBA_KGLLOCK 뷰나 X$KGLPN 뷰를 통해서 관찰 가능하다. 메타링크 문서번호 122793.1에 X$KGLLK 뷰나 X$KGLPN 뷰를 이용해서 library cache locklibrary cache pin의 경합관계를 파악하는 방법이 잘 설명되어 있다. row cache lock의 경우에는 V$ROWCACHE_PARENT 뷰를 통해서 간접적인 관찰이 가능하다. 버퍼 캐시 덤프나 row cache 덤프, library cache 덤프, systemstate 덤프 등을 이용해도 관찰이 가능하지만, 테스트나 연구용 그리고 장애분석용으로서만 활용 가능하다.

[편집] Analysis Case