틈틈히 OWI 책을 보면서 공부하는데..

가장 기본이 되는 Latch 와 Lock 관련하여 정리하여 올려본다.


아는 내용도 있지만 그래도 다시 한번 익히는 좋은기회겸..

또 몰랐던 내용도 알 수 있는 거라 공부하면서 Word 로 정리 해봤다.


흠....이쁘게 정리할 수도 있지만...그냥 편하게...ㅎㅎ

복사해서 필요한것만 find 하도록...


 

래치와 락 (latch & lock) - OWI

By. Louis Kim 

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

분류

래치(Latch)

(Lock)

목적

하나의 목적을 수행함 : 메모리 구조에 대한 배타적인 접근을 위함 ( 오라클 9i 부터cache buffers chains latch 들은 읽기 전용시에 공유가 가능함

두 가지 목적을 수행함: 락 모드가 호환가능하면 다수의 프로세스가 동일한 리소스를 공유하는 것을 허용하며, 락 모드가 호환 가능하지 않으면 리소스에 대한 배타적인 접근만 허용함

사용범위

SGA 내부의 데이터 구조에만 적용. 메모리 오브젝트를 임시적으로 보호함. 단일 오퍼레이션으로 메모리 구조에 대한 접근 제어. 트랜잭션 단위가 아님

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

데이터베이스의 데이터 또는 베타데이터 접근 제어. 트랜잭션 단위

획득방식

두 가지 모드로 요청이 가능 : willing-to-wait 또는 no-wait

6가지 모드로 요청이 가능 : null, row share, row exclusive, share, share row exclusive 또는 exclusive

범위

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

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

복잡도

단순한 명령어를 사용하여 구현됨. 일반적으로 test-and-set, compare-and-swap 또는 단순한 CPU명령어. 구현이 쉬움

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

지속기간

아주 짧은 순간만 지속됨 (microsecond 단위)

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

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

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

데드락

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

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

 


 

Latch (래치)

-       가벼운 락(lightweight lock) 으로 분류 (아주 빠른 속도로 작동하게끔 구현된 경량화된 락)

-       Shared pool 영역에 존재하는 일종의 메모리 구조체

-       매우 간단하고 작은 메모리영역을 사용하며, 래치를 획득(get)하고 해제(release)하는 작업들 또한 하드웨어 맞게 극도로 최적화 되어 있음

-       래치를 획득하고 해제하는 과정은 원자성(atomicity)이 보장

-       래치 획득의 순서를 보장하지 않음. 순서가 보장되어야 하는 작업은 락에서 진행

-       래치는 SGA 리소스를 보호하기 위함

-       SQL문을 실행하고자 하는 프로세스는 SQLshared pool library cache 영역에 올려야하는데, 이 때 heap 메모리 영역을 할당받기 위해 반드시 shared pool 래치를 획득 필요

-       하나의 프로세스만이 힙으로부터 청크(chunk)를 할당받을 수 있음

-       select문의 경우 특정 데이터블록을 읽기 위해 데이터블록의 DBA Class에 해당하는 Hash chain에 접근하고자 하는 모든 프로세스는 반드시 Hash chain을 관장하는 cache buffers chains Latch를 획득해야 함

-       DML를 실행하기 위해서는 PGA영역에 Redo 데이터를 생성 / Redo dataRedo buffer로 복하기 위해 redo copy latch 가 필요

-       Latch 획득하기 위해서 특정 대기 이벤트가 필요 (latch free 대기 이벤트 / p1=address , p2=latch# 래치 이름 획득)

-       Child latch를 사용하는 메모리 영역들도 있음

-       Buffer cache 의 경우 각각의 hash chain을 독립적으로 관리할 수 있는 구조로 되어 있기에 복수개의 cache buffer chains latch 를 사용

Parent Latch(부모래치) : 여러 개의 자식 latch를 거느릴 수 있음

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

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

부모 래치와 독립 래치는 V$LATCH_PARENT 뷰를 이용하여 관찰 가능

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

-       In Memory Undo 의 경우 10g 이후부터 생긴 것이며 KTI-UNDO 영역을 보호하기 위한 in memory undo latch 가 있음


 

래치 동작 메커니즘

-       여러 프로세스가 동시에 래치를 획득하는 과정에서 데드락 현상 발생(서로 가지고 있는 래치를 요구하는 경우)

-       데드락 발생을 피하기 위해서 자신 보다 낮은 래치의 경우 no-wait 또는 자신이 획득한 래치 레벨보다 높은 레벨을 요청

래치 모드

-       래치는 기본적으로 Exclusive 모드 사용(한 순간에 하나의 프로세스만이 래치를 보유)

-       특정 래치에 대해서는 Shared mode 를 사용( Cache buffers chains Latch)

래치 획득

-       Willing-to wait 모드 래치 획득

n  래치 획득하기 위해서 기본적으로 willing-to-wait 모드를 사용(래치를 획득할 때까지 대기를 의미) – 실패 시 적절한 회수만큼 루프를 돌며 획득 시도 (_SPIN_COUNT 기본 2000) – 이후에도 실패 시 래치가 풀릴때가지 sleep

n  Sleep 을 바로 하지 않고 spin 하는 이유

1.     아주 빠른 시간안에 다른 프로세스가 래치를 해지할 것이라고 기대

2.     슬립 상태로 빠지게 되면 OS차원에서 Context switching이 발생(이것이 약간의 CPU를 소모하기 때문에 비용적인 측면에서 sleep 보다는 spin이 나음)
cf) spin
과정에서 Active 상태로 CPU를 계속 점유하기 위해서 일정 시간 소량의CPU를 소모(Active wait)  -> 래치 경합에 의해서 많은 수의 프로세스가 동시에 스핀을 수행할 경우 높은 CPU 사용율을 보일 수 있음(래치 경합을 줄이기 위해 CPU를 늘이는 것은 더욱더 상황을 악화 위험)

n  Sleep 에서 깨어나는 방법

1.     약속된 시간(타임아웃)

2.     Latch wait list에서 자신의 순서가 되어 다른 프로세스가 깨워주는 방법 (latch wait posting)

u  주로 sleep 상태에서 프로세스는 latch:xxx / latch free 이벤트를 대기

u  매번 슬립 시간이 두배로 증가함으로써 빠른 시간내에 래치 획득을 재시도하는 과정에서 지나친 스핀으로 인해 CPU를 과다하게 사용하는 것을 방지


 

No-wait 모드의 래치 획득

-       대부분의 latch 획득은 willing-to-wait 모드를 사용하지만 특수한 경우 no-wait 모드 사용

-       가장 최근에 획득한 래치보다 더 낮거나 같은 레벨의 래치를 획득하고자 할 때

-       데드락을 피하기 위함

-       No-wait 모드의 래치 획득에 실패할 경우 획득하고자 하는 래치보다 높은 레벨의 래치는 모두 해제하고 올바른 순서로 다시 획득 시도

Ex) 1,2,4 레벨의 레치를 획득 후 3레벨 래치 획득 시도 시 no-wait 시도 / 실패 시 1,2 레벨을 남기고 4 레벨 래치 포기 후 3레벨 순서로 획득

래치 cleanup

-       래치를 획득한 후 공유 메모리 영역을 변경하고자 하는 프로세스는 변경 전에 래치복구 영역에(latch recovery area) 자신의 목적에 대한 정보를 기록
이 후, 갑작스럽게 프로세스가 래치를 보유한 채로 종료되면 PMON에서 cleanup function을 호출하여 래치 복구영역에 기록된 정보를 이용하여 복구

 

래치 관련 Dynamic Views (V$LATCH)

-       v$latch_parent : 독립 래치에 대한 통계값을 제공

-       v$latch_children : 모든 개별 자식 래치들에 대한 통계값을 제공

컬럼

설명

GETS

Willing-to-wait 모드에서 슬립하기 전의 래치 요청회수

MISSES

Willing-to-wait 모드에서의 슬립하기 전의 래치 획득 실패 회수

SPIN_GETS

Willing-to-wait 모드에서 슬립하기 전의 스핀단계에서의 래치 획득 성공 회수

SLEEPS

Willing-to-wait 모드에서의 슬립 회수

IMMEDIATE_GETS

No-wait 모드에서 래치 획득 성공 회수

IMMEDIATE_MISSES

No-wait 모드에서 래치 획득 실패 회수

SLEEP1 ~ SLEEP4

1~3 회의 슬립회수와 4회 이상의 슬립 회수. 오라클 10gR2부터는 사용되지 않으며 V$EVENT_HISTOGRAM 뷰로 대체

WAITERS_WOKEN

Latch wait posting 을 사용할 경우 세션이 깨어난 회수. 오라클 10gR2 부터는 사용되지 않는다. Latch wait list 래치가 없어진 것과 같은 맥락으로 latch wait posting 알고리즘이 완전히 바뀌었음을 의미

WAIT_TIME

래치를 획득하기 위해 대기한 시간(microsecond) 단위

 

-       GETS MISSES 비율을 이용하여 경합이 있는지를 판단

-       Willing-to-wait 모드일 경우 MISSES / GETS , No-wait 모드일 경우에는 IMMEDIATE_MISSES / (IMMEDIATE_GETS + IMMEDIATE_MISSES) 값이 1% 이상이면 래치 경합이 발생한 것으로 판단

-       Wait_time 을 이용해 대기시간이 CPU 시간에 비해 어느 정도 높은 값을 보일 경우 래치 경합이 발생한 것으로 판단

 

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

-       Latch: cache buffers chains : Buffer cache에서 특정 블록을 탐색하고자 하는 프로세스는 cache buffers chain Latch 를 반드시 필요 이 과정에서 경합이 발생 시 발생 이벤트

-       Latch: cache buffers lru chain : Buffer cache에서 free buffer dirty buffer를 탐색하고자 할 때 경합 발생시 발생되는 이벤트

-       Latch: shared pool : Shared pool Heep 영역에 chunk를 할당 받고자 할 때 경합 발생 시

-       Latch: library cache : Library cache 영역을 탐색하고 할 때 경합 발생 시 이벤트

-       Latch: redo copy : DML에 의한 변동사항을 Redo Buffer에 기록하고자 할 때 작업의 전 과정 동안 redo copy latch 획득 필요 이 때 경합 시 발생

Latch Free 대기 이벤트의 경우 P2의 값이 latch# 이므로 이 값을 V$LATCHNAME.LATCH# 과 조인하면 래치이름을 얻을 수 있음


 

(Lock)

락의 분류

1.     락에 대한 정확한 분류가 존재하지 않음

2.     Enqueue Lock과 일반 Lock과 정확한 구분이 존재하지 않음

-       DML Lock

n  Row Locks (TX)

n  Table Lock (TM)

-       DDL Lock

-       Latches and Internal Locks

n  Latches

n  Intercal locks

u  Dictionary Cache locks

u  File and Log Management Locks

u  Tablespace and Rollback Segment locks

Steve Adams Lock 분류

-       Row cache Enqueues

-       Library cache locks and Pins

-       DML Locks

-       Buffer Locks

-       Sort Locks

 

Enqueue Lock : Enqueue 구조로 관리되는 Lock (10g 부터는 Wait Event로 등록 (v$event_name)

Row cache lock : shared pool Row Cache 영역을 보호하기 위해 사용 ( Row cache 메모리 영역 자체에 보유 프로세스 목록 (Owner List) 와 대기프로세스 목록(Waiter List) 를 관리) -> Row cache Lock, Library cache Lock, Library cache pin, Buffer Lock 등이 있음


 

-       Enqueue Lock

n  User Type lock : TX, TM, UL

n  System Type Lock : CF, US, CI, TC, JS, …

-       일반 Lock

n  Row cache Lock

n  Library cache Lock, Library cache pin

n  Buffer lock

 

Lock 이 보호하는 Resource

-       Latch SGA 보호 / Lock Database 전체를 보호 (Table, Transaction, undo segment, tablespace, Job

-       TM Lock Table resource 보호 (ID1=object id)

-       TX Lock Transaction Resource 보호 (ID1=USN << 16|SLOT, ID2=Sequence)

-       US Lock Undo Segment Resource 보호 (ID1=USN)

-       HW Lock (ID1=Tablespace#, iD2=DBA of Undo Segment Header)

-       Enqueue LockV$LOCKTYPE, ID1, ID2 값이 resource 구분자 역할

 

V$SESSION_WAIT

-       대기현상이 잘생하는지 관찰 가능

-       Buffer lock 경합의 경우 Buffer busy waits Read by other session 이벤트에 대한 대기현상 발생

-       Row cache lock 경합은 row cache lock Event로 확인 가능

-       Library cache lock library cache pin 에서의 경합은 library cache lock Evnet, library cache pin Event 로 관찰 가능

 


 

Lock 동작 매커니즘

1.     Lock 모드

Mode

설명

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)

 

-       Table 변경의 경우 Exclusive Mode로 획득 해야 함

-       DML 의 경우 TM LockSub Exclusive 모드로 획득

-       Sub-Exclusive의 경우 상호 호환성이 있기 때문에, 동시에 여러프로세스가 하나의 테이블에 대해 DML 작업을 수행하는 것이 허용

-       Lock Mode 호환성

 

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

 

Ex1) Procedure 실행하는 process Library cache pinShared mode 로 획득 해야 함.

Ex2) Procedure compile 의 경우, library cache pinExclusive mode로 획득해야 함(호환성이 없기에 library cache pin에 의한 경합이 발생)

 

2.     Lock 획득

-       Enqueue Lock 획득에 실패한 프로세스는 Enqueue resource의 대기목록(Waiter list)에 등록

(3초 마다(timeout) 스스로 깨어나서 데드락 발생 여부 확인 후 sleep 또는 락을 보유한 프로세스가 락의 사용이 끝난 후 대기 모드 프로세스를 깨워 줌)

-       enq: XX – YYYYY 이벤트를 대기

TX Lock 경합

n  enq: TX – row lock contention

n  enq: TX – allocate ITL entry

n  enq: TX – index contention

n  enq: TX – contention

이벤트가 별도로 정의

-       Row cache lock과 같은 일반 lock Enqueue Lock 과 기본적으로 같은 방식으로 동작

-       Buffer lock은 타임아웃이 1

-       역속적으로 buffer lock 획득하기 위해 대기하는 경우 3초 타임아웃

-       Row cache lock 60초까지 대기

-       Library cache lock library cache pin 3초를 대기

-       PMON 프로세스는 타임아웃이 1

-       데드락의 경우 원천적으로 Latchlevel 매커니즘에 의해 방지하지만 lock 의 경우 데드락의 가능성이 항상 존재하며,
데드락 판정이 나면 데드락을 발견한 프로세스의 락 요청은 취소되며, 전체 Transaction 이 아닌 현재 SQLrollback 된다

 

Lock 관련 Dynamic Views

-       V$LOCK 에서 Enqueue Lock 관련 정보를 확인 가능

SID

Lock 을 보유중이거나 요청 중인 Session ID

LMODE > 0 이면 Lock을 보유중인 Session 이며, Request > 0 이면 Lock 요청중인 session

Type

Enqueue Lock Resoure Type (ex – TX, TM, UL, US, CI, TC, …etc)

ID1

Resource ID 1

ID2

Resource ID 2 <TYPE-ID1-ID2>Lock이 보호하는 Resource 구분자

LMODE

Lock 을 보유하고 있는 경우의 Mode (1~6 -> Lock 모드 참조)

REQUEST

Lock 을 요청중인 경우의 Mode (1~6 -> Lock 모드 참조)

CTIME

현재의 lock mode가 허용된 시간(second) Lock을 보유하거나 요청한 이후부터의 시간

Block

현재의 Lock이 다른 Lock을 블로킹하고 있는지의 여부.
1:
다른 Lock을 블로킹 중
0 :
다른 Lock을 블로킹 안하고 있음

 

V$LOCK_OBJECT

-       현재 시스템의 모든 Transaction에 의해 획득 중인 TM Lock에 대한 정보를 제공

-       OBJECT_ID를 이용하여 object를 직접 조회할 수 있음

-       Lock 이 걸린 테이블을 조회할 때 유용

V$ENQUEUE_LOCK

-       V$LOCK과 동일하지만, 실제 Enqueue 현상-Blocking 이 발생한 경우 Waiting session 에 대한 정보만 조회

-       어떠한 session lock을 대기하고 있는지 정보만 확인 가능

 

Library cache lock

-       DBA_DDL_LOCKS, DBA_KGLLOCK, X$KGLLK를 통해 관찰이 가능

Library cache pin

-       DBA_KGLLOCK, X$KGLPN 통해서 관찰이 가능

-       122793.1 메타링크 참조

1.     System Trace 를 이용한 분석

$sqlplus '/ as sysdba'

oradebug setmypid

oradebug unlimit

oradebug dump systemstate 266

 

행 걸린 SID 를 이용하여 PID 검색

select pid from v$process where addr=

(select paddr from v$session where sid= sid번호;

 

TRACE 파일에서 아래 PID로 검색하여 wait event 확인('waiting for' 를 검색)

PROCESS 위에서 확인한 PID

 

2.     X$KGLLK 테이블을 조사

select sid,saddr from v$session where event= 'library cache lock';

 

select kgllkhdl Handle,kgllkreq Request, kglnaobj Object

from x$kgllk where kgllkses = '위에서 찾은 saddr정보'

and kgllkreq > 0

--직접 만든 join

select a.kgllkhdl Handle,a.kgllkreq Request, a.kglnaobj Object

from x$kgllk a, v$session b

where b.event='library cache lock'

and b.saddr=a.kgllkses

and a.kgllkreq > 0;

 

또는

select sid,saddr from v$session where event= 'library cache lock';

 

select kgllkses saddr,kgllkhdl handle,kgllkmod mod,kglnaobj object

from x$kgllk lock_a

where kgllkmod > 0

and exists (select lock_b.kgllkhdl from x$kgllk lock_b

where kgllkses = '위에서 찾은 saddr' /* blocked session */

and lock_a.kgllkhdl = lock_b.kgllkhdl

and kgllkreq > 0);

 

메타링크 원문


공통 상황들 

  • 테이블이 진행중인 변경(ALTER TABLE)에 의해 사용중이라면 이 테이블에 DML작업은 행이 걸리게 됩니다. 테이블의 크기나 변경이 어떤 작업(예를 들어 (수천 건의 레코드를 가지고 있는 테이블에 ALTER TABLE x MODIFY (col1 CHAR(200))) )이냐에 따라 아주 오래 락이 걸리기도 합니다.

    이런 경우, v$lock은 이 테이블 오브젝트에 DML 인큐 락(ID1이 테이블의 OBJECT_ID LMODE=6, TYPE=TM)을 가지고 'ALTER TABLE' 을 수행하고 있는 세션을 보여줄 것입니다. 이 기다리고 있는 세션은 v$lock에서 보이지 않는데 동시 접속 세션들이 많은 환경에서는 V$LOCK 정보를 이용하여 작업을 방해하고 있는 문제의 세션을 확인하기에 부족할 것입니다.
  • 어떤 사용자가 패키지에서 정의하고 있는  프로시져나 펑션을 수행중이라면 이 패키지 컴파일은 라이브러리 캐시 락 과 라이브러리 캐시 핀을 기다리게 될 것이다.

방법 1: Systemstate 분석

Systemstate 이벤트는 모든 오라클 프로세스들의 상세한 정보를 담고 있는 트레이스 파일을 생성해 줍니다. 이 정보에는 특정 프로세스에 의해 사용중이거나 요청중인 모든 자원들을 포함하고 있습니다.

어떤 작업이 행 상태에 있는 동안 새로운 세션을 열고 다음의 명령을 발행합니다:
Oracle 9.2.0.1
또는 그 이후 :

 

$sqlplus '/ as sysdba'
oradebug setmypid
oradebug unlimit
oradebug dump systemstate 266


더 오래 전 버젼은 상위 버젼에서도 수행 가능한 다음의 구문을 이용할 수 있습니다. 이벤트 level 266 9.2.0.6 이전에서는 사용할 수 없습니다.

alter session set max_dump_file_size=unlimited;
alter session set events 'immediate trace name systemstate level 10'



오라클은 USER_DUMP_DEST 디렉토리에 systemstate 트레이스 파일을 생성합니다.

행 상태에 있는 세션의 PID를 얻기 위해 :

select pid from v$process where addr=
(select paddr from v$session where sid= <sid_of_hanging_session> );

Systemstate 덤프는 각각의 프로세스별로 구분되는 정보를 담고 있습니다.
트레이스 화일을 열고 "PROCESS <위에서 확인한 PID>"를 찾습니다.
이 프로세스 부분에서 'waitinf for' 를 검색하여 지연 이벤트가 무엇인지 확인합니다.


 
PROCESS 20: 
---------------------------------------- 
SO: 0x7d2bd820, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=20, calls cur/top: 0x7d3d62d0/0x7d3d85dc, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6 
(latch info) wait_event=0 bits=0 
Process Group: DEFAULT, pseudo proc: 0x7d2ed5dc 
O/S info: user: oracle, term: pts/7, ospid: 19759 
OSD pid info: Unix process pid: 19759, image: goblin.forgotten.realms (TNS V1-V3) 

<cut> 

(session) sid: 141 trans: (nil), creator: 0x7d2bd820, flag: (41) USR/- BSY/-/-/-/-/- 
DID: 0001-0014-00000668, short-term DID: 0000-0000-00000000 
txn branch: (nil) 
oct: 6, prv: 0, sql: 0x62d01c34, psql: 0x7c20f24c, user: 542/SCOTT 
service name: SYS$USERS 
O/S info: user: oracle, term: pts/7, ospid: 19758, machine: goblin.forgotten.realms 
program: sqlplus@goblin.forgotten.realms (TNS V1-V3) 
application name: SQL*Plus, hash value=3669949024 
waiting for 'library cache lock' blocking sess=0x(nil) seq=36 wait_time=0 seconds since wait started=11 
handle address=62d064dc, lock address=79f88a68, 100*mode+namespace=c9 

  • U락이 잡힌 오브젝트의 정보를 찾기 위해 핸들 주소를 사용합니다:

 

SO: 0x79f88a68, type: 53, owner: 0x7d3d62d0, flag: INIT/-/-/0x00
LIBRARY OBJECT LOCK: lock=79f88a68 handle=62d064dc request=S
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000
htl=0x79f88ab4[0x79e71e60,0x79e71e60] htb=0x79e71e60 ssga=0x79e716fc
user=7d3a13b8 session=7d3a13b8 count=0 flags=[0000] savepoint=0xce
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0
name=SCOTT.EMPLOYEES

 

라이브러리 오브젝트 락이 공유 모드(request=S)에서 요청되었으며 그 이름이 SCOTT.EMPLOYEE임을 알 수 있습니다.

  • 같은 트레이스 파일에서 이 'handle address' 주소로 검색하여 자원에 락을 잡고 있는 프로세스가 무엇인지 찾습니다. 

PROCESS 18: 
---------------------------------------- 
SO: 0x7d2bcca8, type: 2, owner: (nil), flag: INIT/-/-/0x00 
(process) Oracle pid=18, calls cur/top: 0x79f3ab84/0x7d3d5fc8, flag: (0) - 
int error: 0, call error: 0, sess error: 0, txn error 0 
(post info) last post received: 109 0 4 
last post received-location: kslpsr 
last process to post me: 7d2b8d94 1 6 
last post sent: 0 0 24 
last post sent-location: ksasnd 
last process posted by me: 7d2b8d94 1 6 

<cut> 

SO: 0x75fe8f7c, type: 53, owner: 0x7b751914, flag: INIT/-/-/0x00 
LIBRARY OBJECT LOCK: lock=75fe8f7c handle=62d064dc mode=X 
call pin=(nil) session pin=(nil) hpc=0000 hlc=0000 
htl=0x75fe8fc8[0x79f81790,0x79fc3ef8] htb=0x79f81790 ssga=0x79f8102c 
user=7d3988d0 session=7d3988d0 count=1 flags=[0000] savepoint=0x146e 
LIBRARY OBJECT HANDLE: handle=62d064dc mtx=0x62d06590(0) cdp=0 
name=SCOTT.EMPLOYEES

 

위 결과에서 우리는 Process 18(pid)가 우리가 사용하고자 하는 오브젝트에 배타 락(mode=X)을 걸고 있는 것을 볼 수 있습니다. V$PROCESS V$SESSION을 이용하여 이 프로세스의 sid, 사용자, 터미널, 프로그램, 등을 조회해 볼 수 있습니다.

이 세션이 실행했던 실제 문장도 이 트레이스 화일에서 확인 할 수 있습니다(문장들과 다른 라이브러리 오브젝트들은 "name=" 다음에 위치합니다).

방법 2: X$KGLLK 테이블에서 조사

X$KGLLK 테이블(SYS/INTERNAL로 조회 가능)은 모든 세션들이 잡고 있거나 요청중인 모든 라이브러리 케시 오브젝트들 담고 있으며 비록 의미를 알기 어려운 열이름들이 사용되지만 V$LOCK 뷰보다 더욱 완벽한 정보를 제공합니다.

여러분은 V$SESSION에 있는 세션 주소(SADDR) 을 찾아 보고 아래의 조회를 해 봄으로써 대기중인 세션에 의해 요청된 락들을 조사할 수 있습니다:

select sid,saddr from v$session where event= 'library cache lock';

SID SADDR
---------- --------
16 572ed244


select kgllkhdl Handle,kgllkreq Request, kglnaobj Object
from x$kgllk where kgllkses = '572ed244'
and kgllkreq > 0;

HANDLE   REQUEST   OBJECT
-------- ---------- ------------------------------------------------------------
62d064dc          2 EMPLOYEES

 

이 결과는 라이브러리 캐시 락을 요청하고 있는 세션(KGLLKREQ > 0) 과 함께 락을 잡고자 하는 오브젝트의 이름중 첫 80자리를 KGLNAOBJ로 보여주고 있습니다. KGLLKHDL 의 값은 앞에서 봤던 방법 1 Systemstate 분석절차에서의 오브젝트에 대한 '핸들 주소' 에 해당됩니다.

만일 이 KGLLKHDL X$KGLLK 의 다른 세션의 핸들과 일치한다면 블로킹 세션의 주소를 알수가 있게 됩니다. 이 락을 작고 있는 세션은 락을 잡고 있기 때문에 KGLLKMOD > 0 상태를 가지고 있을 것입니다.

 

select kgllkses saddr,kgllkhdl handle,kgllkmod mod,kglnaobj object
from x$kgllk lock_a
where kgllkmod > 0
and exists (select lock_b.kgllkhdl from x$kgllk lock_b
where kgllkses = '572ed244' /* blocked session */
and lock_a.kgllkhdl = lock_b.kgllkhdl
and kgllkreq > 0);

SADDR     HANDLE   MOD
--------  -------- ----------
OBJECT
------------------------------------------------------------
572eac94  62d064dc          3
EMPLOYEES



조금 더 살펴보면, v$session 에서 KGLLKSES 과 일치하는 SADDR 를 찾아 블러킹 세션에 대한 추가적인 정보를 확인할 수 있습니다:

select sid,username,terminal,program from v$session where saddr = '572eac94'

SID        USERNAME                  TERMINAL
---------- ------------------------------ ------------------------------
PROGRAM
------------------------------------------------
12          SCOTT                          pts/20
sqlplus@goblin.forgotten.realms (TNS V1-V3)


같은 방법으로, 모든 대기 세션들을 찾을 수 있습니다

select sid,username,terminal,program from v$session
where saddr in 
(select kgllkses from x$kgllk lock_a 
 where kgllkreq > 0
 and exists (select lock_b.kgllkhdl from x$kgllk lock_b
             where kgllkses = '572eac94' /* blocking session */
             and lock_a.kgllkhdl = lock_b.kgllkhdl
             and kgllkreq = 0)
);

SID        USERNAME                       TERMINAL
---------- ------------------------------ ------------------------------
PROGRAM
------------------------------------------------
13         SCOTT                           pts/22
sqlplus@goblin.forgotten.realms (TNS V1-V3)

16         SCOTT                           pts/7
sqlplus@goblin.forgotten.realms (TNS V1-V3)

 

 

일반적인 Lock 관련 대기 이벤트

TX Lock 에 의한 대기 현상

Row cache lock

Row cache lock에 의한 경합

Buffer busy waits, read by other session

Buffer lock에 의하 경합

Library cache lock

Library cache lock에 의한 경합

Library cache pin

Library cache pin 에 의한 경합

DFS Lock handle

Global lock인 경우에 관찰

 

           V$session_wait , v$session 을 이용하여 lock 에 대한 경합을 확인 가능

 


반응형

Table 단위로 이관 요청이 있어서 쉽게 진행을 하였다.


PUMP 를 애용하는 편이라..(Enterprise 가 아니면 pump를 이용 못하거나, 주로 export를 많이 이용하라는데..쩝..)


expdp system/oracle directory=dp dumpfile=user_151120.dmp logfile=user_log.log tables=user.table1, user.tabl2....


이렇게 진행 하였다.


ftp 로 파일을 옮긴 후 IMPDP 진행


요청 받은 table 들은 truncate 로 삭제 진행

impdp system/oracle directory=dp dumpfile=user_151120.dmp logfile=user_log_imp.log content=data_only


어엇!!!에러가 발생했다.

ORA-31693: Table data object "유저명"."테이블명" failed to load/unload and is being skipped due to error:

ORA-29913: error in executing ODCIEXTTABLEOPEN callout

ORA-29400: data cartridge error

ORA-39786: Number of columns does not match between export and import database



이유

The errors occur when the ACCESS_METHOD is EXTERNAL_TABLE. This method is chosen if at least one of these conditions is met:


There is an active trigger

The table is partitioned

FGAC (Fine Grained Accesses Control) in insert mode

Referential integrity constraint exists

Unique index exists

Enabled constraint is present on pre-existing table

If any of these conditions apply, then you need to do import using DIRECT_PATH access method to solve the problem.


흠..뭐가 테이블끼리 맞지 않는 부분이 있는 듯 하다


해결방안


Follow either of the below workarounds to solve the issue:


o  Either drop the constraints/unique indexes on table before impdp is started and add access_method=direct_path to command line


- OR -


o  Rename the table before impdp, do the import and transfer the data per INSERT/SELECT to renamed table. Finally drop the imported table and rename table to old name. 


In 10g, DataPump chooses external tables for the access method to import data into a table with an unique index. On the other hand, in 11g the DataPump chooses the direct path access method even in this case. 


This issue specified in the Bug 4383811 Which has been closed as is not feasible to fix in 10g.

The ORA-39786 error is introduced (in 10.2.0.3.0) to avoid an ORA-600 error when importing data into the pre-existing table using the external tables access method.


결국은 기존 table Drop 후에 진행 하였으며, 정상적으로 해결 하였다.


기존 Table에 Trigger 가 있었으며, constraint 와 unique 를 삭제하고 재 진행할꺼면, 해당 테이블 통으로 Drop 하는 것이 편할 듯 싶었다.

버그인 부분도 있는 듯 하다.

 



반응형

아래와 같이 튜닝을 하려고 포인트를 Merge join 에 맞춰서 group by 시 해당 부분을 튜닝하려다가 

찾게 된 자료를 공유해 본다

내 자료는 아래와 같다.

서브 쿼리로 쪼개서 그 중에 하나이다.


공유 자료다.

1억건 정도의 데이터를 가진 2~3개의 테이블을 조인하여 자료를 이행하고자 하면 심각한 수행속도의 저하에 부딪히게 된다.

 

1. Join Method 의 선택 

 

대용량의 데이터라면 당연히 Hash Join 을 이용해야 한다.

해쉬조인은 해슁함수 기법을 활용하여 조인을 수행하는 방식으로 Nested Loop 조인이 가진 랜덤 액세스의 단점과 Sort Merge 조인이 가진 정렬의 부담을 해결할 수 있는 대안이다.

 

랜덤의 부담은 최악의 경우 하나의 로우를 액세스하기 위해 한 블록씩 액세스를 해야 하고, 그 블록이 아직 디스크에 위치하고 있을 수도 있다는 점이다. 정렬의 부담은 정렬처리 그 자체의 부담이라기 보다는 메모리 내에 지정한 정렬영역보다 정렬할 크기가 지나치게 큰 경우에 발생하는 기하급수적인 부담을 말한다.

 

해쉬조인의 가장 큰 장점은 조인의 연결고리의 인덱스 존재유무에 영향을 받지 않는다는 점이다.

따라서 인라인뷰를 이용한 중간집합을 만들어 가면서 집합의 연산을 통해 결과 집합을 생성해 가다보면 중간에 생성되는 집합들은 일종의 임시 테이블이라고 할 수 있으므로 당연히 인덱스를 가질 수 없다. 이러한 처리에서 해쉬조인의 가치는 크게 부각될 수 밖에 없다.

 

 

2. Hash 조인의 튜닝 포인트

 

1) Build Table 과 Probe Table 의 선택

 

해쉬 조인을 위해 먼저 액세스하여 필요한 준비를 해두는 처리를 빌드입력(Build Input) 이라 하며, 나중에 액세스하면서 조인을 수행하는 처리를 검증 혹은 검색입력(Probe Input)이라고 한다.

 

결론부터 언급하면 적은 처리 대상 집합을 가지는 Table 이 Build Table 로 선정되어야 한다.

 

처리대상 집합이 적다는 것은 테이블 사이즈가 작다는 것을 의미하지는 않는다. 테이블이 아무리 크더라도 인덱스 스캔을 통해 테이블의 3~5% 미만을 액세스한다면 이 경우는 처리 대상 집합이 적은 것이다.

 

빌드입력이 해쉬영역에 모두 위치할 수 있는 경우는 인_메모리(In_memory) 해쉬조인을 수행하게 되고, 그렇지 못한 경우에는 유예 해쉬조인을 수행하게 된다.

 

유예 해쉬조인이 수행되는 경우 해쉬 테이블은 Temp 테이블스페이스에 생성된다. Temp 테이블스페이스에 있는 해쉬 테이블이 필요시 해당 부분에 대해서 Block 단위로 액세스하게 된다.

 

참고) 해쉬조인으로 유도하기 위해서는 USE_HASH(B A) 힌트를 사용한다. 여기서 테이블 B 는 빌드 테이블이며 테이블 A 는 검증테이블을 의미한다.

 

2) Temp Tablespace 를 이용한 성능 향상

 

일반적으로 해쉬영역의 크기를 크게 할수록 Temp 테이블스페이스를 적게 사용하지만 무한정 해쉬영역을 확장할 수 없기 때문에 초대용량 데이터를 이행할 때는 해쉬 테이블이 Temp 테이블스페이스에 생성된다.

 

PGA 의 해쉬 테이블과 Temp 테이블스페이스는 Build 테이블의 처리 대상 집합의 크기에 따라 계속적인 통신을 하게 된다. 아래는 Temp 테이블스페이스의 사용을 확인하는 SQL이다.

 

SQL> SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

         FROM V$TEMPSEG_USAGE;

 

SEGTYPE : 해쉬조인을 수행할 경우 HASH 라고 표시된다.

                 SORT 라고 표현되면 SQL에서 Order by, Group by 등에 의해 Sort 를 수행하거나

                 인덱스를 생성하는 부분이다.

EXTENTS : 할당된 익스텐트의 갯수이다.

 

SQL> SELECT A.USERNAME

                     ,A.TABLESPACE

                     ,A.CONTENTS

                     ,A.SEGTYPE

                     ,A.EXTENTS                         AS USED_EXTENTS

                     ,TO_CHAR(ROUND(A.EXTENTS / B.TOTAL_EXTENTS * 100,2),'999.00') || '%'

                                                                AS USED_PCT

                    ,B.FREE_EXTENTS                 AS FREE_EXTENTS

                 ,TO_CHAR(ROUND(B.FREE_EXTENTS / B.TOTAL_EXTENTS * 100,2),'999.00') || '%'

                                                                AS FREE_PCT

                   ,B.TOTAL_EXTENTS

        FROM (SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

                   FROM V$TEMPSEG_USAGE) A

                 ,(SELECT TABLESPACE_NAME, EXTENT_SIZE, TOTAL_EXTENTS

                               ,TOTAL_BLOCKS, USED_EXTENTS, FREE_EXTENTS

                   FROM V$SORT_SEGMENT) B

        WHERE A.TABLESPACE = B.TABLESPACE_NAME

        ;

 

3) Parallel Processing 을 이용한 성능 향상

 

해쉬조인 만을 이용하는 것보다는 Parallel Processing 을 이용한 해쉬 조인은 대용량 데이터를 처리하기 위한 최적의 솔루션을 제공하고 있다.

 

/*+ USE_HASH(B A) PARALLEL(A 8) PARALLEL(B 8) */

 

4) Parameter 조정을 통한 성능 향상

 

오라클 9i 이상

 

SQL> alter system set pga_aggregate_target = 10737418240;

SQL> alter session set workarea_size_policy = auto;

SQL> alter session set hash_multiblock_io_count = 256;

 

오라클 9i 부터는 자동실행 메모리 기능을 제공하므로 PGA 공간의 크기를 각 세션별로 지정하지 않고 전체 세션이 사용하는 총 크기를 지정하기 때문에 한 세션이 PGA 크기를 전부 독차지 할 수도 있다.

 

그러나 자동실행 메모리 기능을 실제 사용해보면 오라클 9i 는 제대로 동작하지 않을 때가 많다. 즉, pga_aggregate_target 을 크게 잡아주어도 해쉬영역으로 메모리를 사용하지 못하고 Temp 테이블스페이스를 사용한다. 이는 자동실행 메모리 기능이 9i 에서 새로 추가되었기 때문에 기능이 완벽하지 못하다고 사료된다. 오라클 10g에서는 제대로 동작한다.

 

db_file_multiblock_read_count : Table Full Scan 시 해당 파라미터를 증가시킴으로써 한 번 디스크 IO에 더 많은 블록을 액세스할 수 있으므로 디스크 IO 횟수를 줄일 수 있다.

이 파라미터는 세션 레벨에서 변경 가능하다.

 

오라클 9i 이전

 

SQL> alter session set workarea_size_policy = manual;

SQL> alter session set sort_area_retained_size = 20480000;

SQL> alter session set sort_area_size = 20480000;

SQL> alter session set hash_area_size = 20480000;

SQL> alter session set hash_multiblock_io_count = 256;

SQL> alter session set db_file_multiblock_read_count = 256;

 

Hash Area Size

 

해쉬영역(Hash Area)이란 해쉬 조인을 수행하기 위해 메모리(PGA) 내에 만들어진 영역을 말한다. 이 해쉬영역이 부족하면 디스크(Temp Tablespace)를 사용하게 되어 수행속도에 지대한 영향을 미치게 된다.

 

해쉬영역은 세션별로 지정할 수 있으며 최대 PGA의 크기만큼 설정할 수 있다. 아래는 해쉬영역의 크기를 1G 로 설정한다.

 

SQL> alter session set hash_area_size = 1073741824;

 

 

3. Hash 조인으로 유도

 

1) 힌트(Hint) 사용

 

/*+ ORDERED USE_HASH(A B C) PARALLEL(A 8) PARALLEL(B 8) */

 

USE_HASH 힌트를 사용하여도 옵타마이져가 원하는 실행계획을 만들어 내지 않으면 ORDERED 힌트를 사용하여 실행계획을 고정시킬 필요가 있다. ORDERED 힌트는 쿼리 내 FROM 절의 순서대로 조인을 수행한다.

 

 

4. Hash 조인의 모니터링

 

1) V$PROCESS

 

SELECT ADDR, PID, PGA_USED_MEM

FROM V$PROCESS

;

 

해쉬 조인이 사용하는 메모리 용량을 모니터링 할 수 있다.

 

2) V$SESSION_LONGOPS

 

SELECT SID, START_TIME, TIME_REMAINING, ELAPSED_SECONDS, MESSAGE

FROM V$SESSION_LONGOPS

WHERE SID = XXX

;

 

V$SESSION_LONGOPS 는 6초 이상 수행되는 OPERATION 의 진행상황을 모니터링 할 수 있는 동적성능 뷰이다.

 

3) V$TEMPSEG_USAGE

 

SELECT USERNAME, TABLESPACE, CONTENTS, SEGTYPE, EXTENTS

FROM V$TEMPSEG_USAGE

;

 

해쉬조인이 사용하는 Temp 테이블스페이스의 사용량을 모니터링할 수 있다.


원본 출처 : http://blog.daum.net/servant2342/5417565

반응형

'Oracle > DBA' 카테고리의 다른 글

[ORACLE] ASM 에 Datafile 추가  (1) 2015.11.25
[Oracle] OWI Latch & Lock 정리  (0) 2015.11.24
[Oracle] Merge 구문 1  (0) 2015.11.12
[펌] [ORACLE] SYS_CONTEXT 및 USERENV 정리  (0) 2015.09.03
특정 컬럼만 Masking  (0) 2015.09.03

+ Recent posts