h5. 배열내의 중요한 칼럼{code:sql} Name Null? Type -- KSQRSIDT VARCHAR2(2) KSQRSIDl NUMBER KSQRSID2 NUMBER {code} * ('PS',1,1)는 인스턴스 1번에서 수행되는 병렬 수행 슬레이브 P004를 의미 * ('TM',80942,0)은 object_id가 80942인 테이블을 의미 * ('TX';,65543,11546)은 트랜잭션이 사용하는 언두세그먼트는 1번(trunc(65543/65536)), 슬롯은 7번(mod(65543,65536))이며 해당슬롯은 11546번 재사용된 것을 의미 |
{code:sql} select sid, type, id1, id2, lmode, request, ctime, block from v$lock where type = 'TM' and idl = 8272 ; |
SID TY IDl ID2 LMODE REQUEST CTlME BLOCK
(자식테이블의 foreign key 칼럼에는 인덱스가 존재하지 않는다.)
1. 세션37 : 부모 테이블의 레코드 1과 관련된 자식 테이블의 레코드를 삭제한다.
2. 세션36 : 부모 테이블의 레코드 2와 관련된 자식 테이블의 레코드를 삭제한다.
3. 세션39 : exclusive모드로 자식 테이블에 락을 시도한다.(그리고 대기를 시작한다.)
4. 세션37 : 부모 테이블의 레코드 1을 삭제하려고 시도한다.(그리고 FK인덱스의 부재로인해 대기를 시작한다.)
5. 세션35 : 부모테이블의 레코드 3과 관련된 자식테이블의 레코드를 삭제한다(그리고 대기를 시작한다.)
{panel:title=그림4-4 v$lock 뷰의 몇 개의 로우에 대한 그림|borderStyle=dashed|bgColor=#FFFFFF|titleBGColor=#F0F0F0}!4.jpg|vspace=4!{panel}
※ 오브젝트에 락을 설정하기 위해서는 waiters 또는 converters 리스트에 대기세션이 존재하지 않아야하고,
owners리스트 내의 세션들이 획득한 락 모드와 호환성이 있어야 한다.
* SID 35는 waiters리스트의 맨 뒤에 위치한다. 이미 SID 39가 존재하기 때문이다.
* SID 39역시 대기중이다. SID 37이 converters 리스트에 존재하기 때문이다.
* SID 37은 converters리스트에서 대기한다. SID 37은 락모들르 3에서 5로 변환하기를 원하지만 SID 36이 owner리스트에서
모드 3으로 락을 획득한 상태이기 때문이다(모드 3으로 락을 획득한 세션이있다면, 모드 5로 락을 소유할 수 없다.)|
|* 프로세스가 커밋(또는 롤백)을 수행하면, 리스트는 다음과 같이 재배치 된다.
1. SID 36이 커밋을 수행하면,owners리스트는 빈상태가 된다. 이로인해 SID 37은 converters 리스트에서 owners 리스트로 이동하고,
모드 5로 락을 획득하고 ctime을 다시 0으로 설정한다. SID 39와 35는 여전히 waiters리스트에 위치한다.
2. 그 후에 SID 37이 커밋을 수행하면, owners 리스트는 다시 빈 상태가 된다. 이로인해 SID 39는 owners 리스트로 이동하고,
모드 6으로 락을 획득하고, ctime을 0으로 설정한다. SID 35는 waiters 리스트의 가장 앞에 위치하게 되지만
owners 리스트로는 이동 할 수 없다. 이미 SID 39가 테이블에 대한 exclusive(모드6)락을 획득했기 때문이다.
3. 그 이후에 SID 39가 커밋을 수행하면, owners 리스트는 다시 빈 상태가 된다. 이로인해 SID 35는 owners리스트로 이동하고
모드 3으로 락을 획득하고 ctime을 0으로 설정한다.|
|※ 락을 획득하기 위해 대기중이라면, ctime칼럼은 대기시간을의미, 락을 획득하고있다면, 락을 소유한 시간을 의미
※ 아주 복잡한 락 패턴으로인해 상세한 정보를 필요로한다면, enqueue 트레이스로 확인을 하면된다.
alter session set event 'immediate trace name enqueues level 3'|
h4. 3)데드락
|{code:sql}
데드락 발생시, 트레이스 파일에서 처음으로 확인해야 할 부분은 deadlock graph이다
Dead10ck graph: ---------B1ocker(s) -------- ---------Waiter(s) --------
Resource Name process session ho1ds waits process session ho1ds waits
TX- 00030026-000040d6 13 38 x 12 50 x
TX- 00060002-00004113 12 50 x 13 38 x
세션 38은 TX락(언두세그먼트3번,슬롯38(0x26),시퀀스16,598)을 모두 6으로 획득,세션 50번은 대기중,
세션 50은 TX락(언두세그먼트6번,슬롯 2,시퀀스 16,659)을 획득, 세션 38은 대기중 |
모드 | 이름(들) | 해당모드와 관련된 오퍼레이션 |
---|---|---|
1 | Null Lock(NL) | 테이블과는 관련이 없다. 병렬 DML을 수행하는동안 PX슬레이브에 의해 소유된다. 반면에 QC는 exclusive락을 소유한다. |
2 | Sub Share(SS) Row Share (RS) | select for update(9.2.0.5까지) Lock table in row share mode FK가 생성된 테이블에 DML발생 시 부모 테이블에 해당 모드 락 설정(9.2.0.1부터) |
3 | Sub Exclusive(SX) Row Exclusive(RX) | DML(9.2.0.5부터는 select for update포함) Lock table in row exclusive mode FK가 생성된 테이블에 DML발생시 부모 테이블에 해당 모드 락 설정(11.1부터) |
4 | share(S) | Lock table in share mode 병렬DML수행시에 PX 슬레이브 세션에서 보여질 수 있다. Foreign key락킹(인덱스가 존재하지 않는)문제의 일반적인 증상) |
5 | Share Sub Exclusive(SSX) Share Row Exclusive(SRX) | Lock table in share row exclusive mode Foreign key 락킹의 일반적이지 않은 증상이며, delete cascade옵션을 사용할 때 보여진다 |
6 | Exclusive(X) | Lock table in exclusive mode |
※ 테이블 락과 관련해서, 모드4 또는 모드5의 락 대기가 발생한다면 foreign key 제약조건에 인덱스를 생성해야 한다.
{panel:title=그림4-5 Enqueue와 enqueue resource | borderStyle=dashed | bgColor=#FFFFFF | titleBGColor=#F0F0F0}!3.jpg | vspace=4!{panel} h5. # 락 획득 절차 * 해시값을 생성하기 위해 리소스 식별자(type,id1,id2)를 사용한다. 해시테이블의 크기는 2*sessions+35 정도이므로, '소수' 또는 "2의 지수승"의 일반적인 형식을 사용하지 않는다. * 해시버킷은 enqueue hash chains 래치에 의해 보호된다. 래치의 수는 CPU의 수와 일치하며, 해시버킷은 래치를 통해 "라운드-로빈"방식으로 공유된다. * 락을 설정하려는 리소스에 해당되는 x$ksqrs구조의 한 로우가 이미 해시 체인에 링크되었는지를 확인하려면, 래치를 획득한 후 버킷을 검색(체인을 따라가면서검색)하면된다. * enqueue 리소스를 사용할 준비가 되었다면, 연관된 enqueue구조(x$ksqeq구조등)로부터 하나의 로우를 획득한다. 하지만 동시에 동일한 enqueue로우를 다른 세션이 획득하는 것을 방지하기 위해 관련된 enqueue래치를 획득해야만 한다. * 획득할 필요가 있는 래치는 세션이 사용하려는 enqueue의 유형에 따라 다르다. 예를들어, x$ksqeq구조로부터 로우를 획득하려면 enqueue 래치를 획득해야하고, x$ktadm 구조로부터 로우를 획득하려면 dml allocation 래치를 획득해야한다. 그리고 안전하게 enqueue 로우를 획득하자마자 래치를 릴리즈 해야한다. * enqueue리소스를 사용할 준비가 되지 않았다면(enqueue hash chains 래치를 획득한 채로)x$ksqrs구조로부터 하나의 로우를 획득하고, 세션이 사용하려는 리소스를 표현하도록 표시하고, 해시 체인에 연결한 후 해당 로우와 연결된 enqueue로우를 획득한다. * 이 모든것이 완료되면 enqueue hash chains래치를 릴리즈한다. |