목차

Oracle Transaction Wait Event

트랜잭션 작업순서

사용자 DML(트랜잭션)수행 작업순서
순서 작업내용 실패시 동작 이벤트
1 해당 트랜잭션에 대해
Undo Segment를 할당한다.
Online Undo Segment 3회 획득시도 (실패시)
→ Offline Undo Segment 를 Online 화 시도 (실패시)
→ 새로운 Undo Segment 생성 (실패시)
→ 8i 에서 사용하던 Rollback Segment 알고리즘 사용
: 이미 다른 트랜잭션에 의해 사용 중인 Undo Segment 중
가장 사용량이 적은 것을 사용
enq: US - contention 이벤트

: 서버 프로세스가 언두 세그먼트를 획득하는 시점에
적당한 온라인 상태의 언두 세그먼트가 없을때
온라인 상태의 언두 세그먼트가 확보될때까지
대기하는 이벤트
2 언두 세그먼트를 할당받으면,
언두 세그먼트 헤더에
transaction table slot 을 생성한다.
3 트랜잭션 테이블을 생성하고나면
TXID(Transaction ID)를 생성하고,
핸재 트랜잭션에 할당한다.
트랜잭션은 반드시 언두 영역에
할당받은 다음 ID를 부여 받는다.
4 트랜잭션의 대상이 되는 블록들을
Buffer Cache로 적재하고
블록 헤더의 ITL(Interested Transaction List)에
Transaction Entry를 등록한다.
enq: TX - allocate ITL entry 이벤트

만일 ITL에 Entry를 등록할 공간이 없다면,
공간이 확보될 때까지 대기하는 이벤트
5 변경할 블록들의 변경 정보를
PGA에 체인지 벡터라는 이름으로 저장된다.
프로세스는 PGA에 체인지 벡터들을
리두 레코드(리두 엔트리)라는 이름으로
Redo Buffer로 복사한다.
latch: redo copy
latch: redo allocation
latch: redo writing

: 리두 버퍼에 변경 내용을 복사하는 과정에서
해당 래치를 획득하기 위해 대기하는 이벤트
6 이전 이미지(Before Image)에 대한 정보를
언두 블록에 기록하고, 데이터 블록을 변경한다.
변경된 데이터 블록은 Dirty 상태가 된다.
또, 변경된 데이터 블록에 대한
CR 블록이 Buffer Cache에 생성된다.
enq: TX - row lock contention 이벤트

: 변경하고자 하는 로우가
현재 다른 트랜잭션에 의해 변경 중이라면
해당 트랜잭션이 종료되기를 기다리는 이벤트
7 커밋이 수행되면 트랜잭션에 SCN을 할당하고,
커밋정보는 리두 버퍼에 저장된다.
8 Undo Segment 헤더의
트랜잭션 테이블에 커밋이 이루어졌음을 저장하고,
락을 포함한 모든 리소스에 대한 점유를 해제한다.
9 Redo Buffer의 내용이 리두 로그 파일에 기록된다.
변경된 블록들은
이후 DBWR에 의해 데이터 파일로 기록된다.

Row level lock

  1. 명시적(물리적)으로 존재하는 락이 아닌 논리적인 락
  2. 로우 변경 확인은 해당 로우를 직접 방문해보아야 알 수 있음
  3. 로우의 변경여부 + 로우를 변경한 트랜잭션정보(ITL) + 언두 영역의 트랜잭션 테이블 슬롯 + TX 락 의 정보들이 조합된 일종의 논리적인 락
  4. 로우레벨락은 TX락을 이용해 구현되지만 TX락 자체가 로우레벨락은 아니며,
    다양한 정보들이 조합되어 로우레벨락이 구현된다.

delayed block cleanout

메카니즘

  1. delayed block cleanout 메카니즘에 대한 설명이다.
  2. 오라클은 커밋이 이루어졌을 때, 트랜잭션에 의해 변경된 모든 데이터 블록의 ITL에 대해 일일이 커밋 처리를 하지 않는다.
  3. 변경된 블록 중 현재 버퍼 캐시에 올라와 있는 것들 중 일부만을 커밋처리하며,
    나머지 블록들에 대해서는 트랜잭션에 할당된 언두 세그먼트 헤더의 트랜잭션 테이블 슬롯에만 커밋처리를 한다.
    이 데이타 블록들은 나중에 다른 세션에 의해 스캔될 때, 실제로 Cleanout 처리된다.

Fast commit

  1. 커밋시점에 모든 블록에 대해 cleanout을 수행하지 않는다는 것을 의미한다.
  2. 오라클은 성능상의 문제로 변경된 데이터 블록들 중 버퍼 캐시에 올라와 있는 일부 블록들에 대해서만 cleanout을 수행한다.
  3. Fast commit 이 발생하는 경우, 변경되는 정보량을 최소화하기 위해서
    ITL 정보에서 Flag와 SCN 정보만 변경되고 lock byte정보는 변경되지 않는다.
    lock byte 정보는 트랜잭션에 의해 변경된 모든 로우에 저장되므로 변경해야할 데이터의 양이 많기 때문이다.
  4. Fast commit 기법은 변경된 일부 데이터 블록들의 헤더에 대해서만 변경 작업을 수행하기 때문에 리두데이터가 생성되지 않고, 커밋마크(Commit Mark)만이 리두에 저장된다.
  5. 수백만건의 데이터를 변경한 후에 커밋을 수행하는 경우에도 매우 빠른 속도로 커밋 처리가 되는 것은 이런 기법 때문이다.

트랜잭션 대기 이벤트

내용 트랜잭션 대기 이벤트
인덱스가 없는 Foreign Key enq:TM - contention
부적절한 DDL로 인한 TM락 경합 enq:TM - contention
Lock table .. (의도적인 TM락) enq:TM - contention
Direct/Parallel Load 작업 enq:TM - contention
여러 세션이 동일 로우를 변경하는 경우 enq:TX - row lock contention, mode=6
여러 세센이 Unique Key 충돌을 일으키는 경우 enq:TX - row lock contention, mode4
ITL Entry 부족 enq:TX - allocate ITL entry, mode=4
여러 세션이 Bitmap Index 충돌을 일어키는 경우 enq:TX - row lock contention, mode=4
Index leaf node에서 Split이 발생하는 경우 enq:TX - index contention, mode=4
기타(enq: Tx - contention) enq:TX - contention
사용자 정의 락, DBMS_LOCK enq:UL - contention, PL/SQL lock Timer
DML 락 TM 락과 일치
일반적인 DML 문은 테이블에 대해 TM락을 Sub-Exclusive(SX)모드로 획득
DDL 락 library cache lock과 일치

enq:TM - contention

인덱스가 없는 Foreign Key

  1. 9i 이전 인덱스가 없는 foreign key 컬럼이 TM 락 경합의 주된 원인이었다.
  2. 9i 이전 버젼들은
    자식 테이블의 foreign key 컬럼에 인덱스가 없는 상태에서 부모 테이블의 key가 변경되면,
    자식 테이블에 대해 Shared 모드나 Shared-Sub-Exclusive 모드로 TM 락을 획득해야 한다.
  3. 획득된 TM 락은 부모 key를 변경한 트랜잭션이 종료될때까지 유지되기 때문에 이로 인한 경합이 심각한 성능저하 현상을 일으켰다.

부적절한 DDL로 인한 TM락 경합

  1. DDL이 수행중인 테이블에 대해서 DML을 수행하는 경우에는 TM 락 경합이 발생할 수 있다.
    세션1> update , 세션2> alter table
  2. 데이타량이 많은 테이블에 대한 부적절한 DDL을 수행하면, 해당 테이블을 접근하는 모든 DML 세션이 대기상태에 빠지게 되고, 장애상황으로까지 발전할 수 있다.

Lock table ..

  1. lock table .. 문을 이용한 의도적인 TM 락 획득을 통한 경합 방법

Direct/Parallel Load 작업

  1. Direct load 작업은 SGA를 경유하지 않고 데이터파일을 직접쓰기를 수행하므로 작업이 수행되는 동안 테이블에 어떠한 변화도 허용해서는 안된다.
    그러므로 TM락을 Exclusive하게 획득함으로써 테이블에 대한 어떠한 변경도 허용하지 않는다.
  2. SQL*Loader를 parallel 모드로 수행하는 경우에는 테이블에 대해 TM락을 Shared모드로 획득한다.

enq:TX - 시리즈

  1. TX락은 트랜잭션을 보호하는 것이므로, 트랜잭션이 종료될때(commit or rollback) 해제된다.
  2. 여기서는 3가지 종류를 이야기 한다.
    1. enq:TX - row lock contention
    2. enq:TX - allocate ITL Entry
    3. enq:TX - index contention
여러 세션이 동일 로우를 변경하는 경우 enq:TX - row lock contention
여러 세센이 Unique Key 충돌을 일으키는 경우 enq:TX - row lock contention
ITL Entry 부족 enq:TX - allocate ITL Entry
여러 세션이 Bitmap Index 충돌을 일어키는 경우 enq:TX - row lock contention
인덱스 리프 노드에서 Split이 발생하는 경우 enq:TX - index contention
기타 enq: Tx - contention

여러 세션이 동일 로우를 변경하는 경우

  1. 동일 row 변경은 TX 락 경합이 발생하는 가장 보편적인 경우이다.
  2. row level lock 구성 : [로우 자체의 변경사실 + ITL + 트랜잭션 테이블 슬롯 + TX락]
  3. enq:TX - row lock contention 이벤트
    • 프로세스가 특정 로우를 변경하기 위해 해당 로우를 방문했을 때,
      현재 로우가 변경된 상태라면 ITL로부터 해당 로우를 변경한 트랙잭션을 확인하고
      자기 자신을 TX Enqueue 목록에 추가하고 대기하는 이벤트

여러 세센이 Unique Key 충돌을 일으키는 경우

  1. Unique Key, Primary Key 충돌시에도 TX 락 경합이 발생한다.
  2. enq:TX - row lock contention
    1. 프로세스 A가 Insert를 수행한 후,
      프로세스 B가 Unique Key 충돌이 발생하게끔 insert를 수행하면
      프로세스 B는 프로세스 A의 트랜잭션에 대해 TX 락을 Shared Mode로 획득하기 위해서 대기한다.
    2. 프로세스 B는 프로세스 A가 commit 또는 rollback 할때까지 대기한다.
    3. 프로세스 A가 commit 이 이루어지면 ORA-0001 에러 상황이 되며,
      rollback 이 이루어지면 프로세스 B의 Insert는 성공적으로 이루어지게 된다.

ITL Entry 부족

  1. 모든 트랜잭션은 블록을 변경시키기 전에 블록 헤더의 ITL에 엔트리를 등록해야 한다.
  2. enq:TX - allocate ITL entry
    1. ITL 이 MAXTRANS를 초과하거나 블록 내의 여유공간이 부족해서 엔트리를 등록하는 것이 불가능한 경우,
      프로세스는 이미 ITL에 엔트리를 등록한 프레세스의 트랜잭션에 대해 TX 락을 Shared mode로 획득하기 위해 대기하는 이벤트
  3. 10g 부터는 MAXTRANS 값이 255로 고정되어 있다.

여러 세션이 Bitmap Index 충돌을 일어키는 경우

  1. 하나의 리프 노드가 넓은 범위의 ROWID를 관리한다.
  2. enq:TX - row lock contention
    1. 테이블의 로우가 변경될때마다 비트맵 인덱스에 해당하는 컬럼값에 대해 로우가 속한 리프 노드의 비트맵을 매번 새로 계산해주어야 한다.
      따라서 동시에 두 세션이 같은 리프 노드의 비트맵 연산을 수행할 경우, 순서를 보장하기 위해서 TX 락을 획득한다.
    2. 특정 세션이 TX 락을 Exclusive 하게 획득한 후, 비트맵 연산을 수행하고 아직 커밋을 하지 않았다면,
      다른 세션들은 선행한 트랜잭션에 대해 TX 락을 Shared mode로 확보하기 위해 대기함으로써 비트맵 연산이 끝나기를 기다리게 된다. 즉, 하나의 리프 노드가 넒은 범위의 ROWID를 관리하기 때문에 TX 락 경합이 광범위하게 나타날 수 있다.

인덱스 리프 노드에서 Split이 발생하는 경우

  1. 비트리 인덱스는 데이터를 추가하는 과정에서 리프 노드가 꽉차면 Split을 함으로써 Balance를 맞춘다.
  2. enq:TX - index contention
    1. 보통의 상황에서는 잘 볼생하지 않는다.
    2. 동시에 여러 세션에서 인덱스가 생성되어 있는 테이블에 대해서 많은 양의 DML을 수행하는 경우에 주로 발생한다.
    3. 시퀀스 등을 사용해서 값을 생성하는 컬럼에 대해 인덱스가 생성되는 경우
    4. 인덱스가 생성되어 있지 않은 테이블을 변경하는 경우
    5. 테이블에 LOB컬럼이 있을때 동시에 여러세션이 LOB테이블을 변경하는 경우

기타(enq: Tx - contention)

  1. enq:TX - contention
    1. Distributed Transaction(분산 트랜잭션) 환경에서 Prepared Transaction에 의해 락이 획득된 로우를 읽는 경우
      트랜잭션이 종료(commit,rollback,in-doubt)될때까지 TX락을 Shared Mode로 획득하기 위해서 대기한다.
    2. FLM을 세그멘트 공간관리기법으로 사용하는 경우,
      TFL(Transaction FreeList)을 확보하려는 프로세스는 TFL을 확보하지 못할 경우
      이미 TFL을 확보한 Transaction의 TX락을 Shared Mode로 확보하기 위해서 대기한다.
    3. 언두 세그먼트 헤더의 트랜잭션 테이블에서 새로운 슬롯을 할당받고자 하는 경우
      TX락을 Exclusive 하게 획득한다.
  2. 이들 경우는 겨의 보고되지 않고 있으며, 성능상 이슈도 없는 것으로 보인다.

동시에 많은 수의 트랜잭션이 발생할 경우 enq:TX - contention 이벤트 대기현상 문제가 생길 수 있다.

enq:UL - contention, PL/SQL lock Timer

  1. 사용자 정의 락(US, User-defined Lock)
  2. dbms_lock.request(1)
  3. dmbs_lock.sleep(1)