Transaction

EXEM Knowledge Base

Jump to: navigation, 찾기

오라클 트랜잭션(Transaction)을 완벽하게 이해한다는 것은 오라클을 완벽하게 이해한다는 것과 같은 의미를 지닌다. 트랜잭션을 이해하려면 오라클이 제공하는 제어기능과 내부 구조, 알고리즘에 대한 이해가 필요하기 때문이다. 더구나, RAC와 같은 멀티노드 환경에서는 여러 노드간의 트랜잭션 동기화까지 필요하기 때문에, 그 복잡도는 상상을 초월한다. 사용자가 DML을 수행하게 되면(즉 트랜잭션을 수행하게 되면) 오라클은 내부적으로 다음과 같은 순서로 작업을 진행한다.

1. 해당 트랜잭션에 대해 언두 세그먼트(Undo segment)를 할당한다. 이 경우 현재 온라인상태인 언두 세그먼트 중 하나를 우선적으로 사용한다. 언두 세그먼트의 선택은 랜덤하게 이루어지며, 다른 트랜잭션이 사용중이라면 3번까지 재시도한다. 이 과정이 실패하면 오프라인 상태의 언두 세그먼트를 온라인화해서 사용한다. 만일 이 과정까지 실패하면, 새로운 언두 세그먼트를 생성한다. 이 과정을 통해서도 언두 세그먼트를 할당받지 못하면 오라클 8i에서 사용하던 롤백 세그먼트(Rollback Segment) 알고리즘을 사용한다. 즉, 이미 다른 트랜잭션에 의해 사용중인 언두 세그먼트 중 가장 사용량이 적은 것을 사용한다. 서버 프로세스가 언두 세그먼트를 획득하는 시점에 적당한 온라인 상태의 언두 세그먼트가 없으면 온라인 상태의 언두 세그먼트가 확보될 때까지 enq: US - contention 이벤트를 대기한다.

2. 언두 세그먼트를 할당받으면, 언두 세그먼트 헤더에 트랜잭션 테이블 슬롯(transaction table slot)을 생성한다.

3. 트랜잭션 테이블을 생성하고 나면 TXID(Transaction ID)를 생성하고, 현재 트랜잭션에 할당한다. TXID는 V$TRANSACTION 뷰의 XIDUSN, XIDSLOT, XIDSQN으로 표현되는데, 이 값은 트랜잭션에 할당된 언두 영역의 언두 세그먼트 헤더에 존재하는 트랜잭션 테이블의 정확한 위치를 가리킨다. 트랜잭션은 반드시 언두 영역을 할당받은 다음에 ID를 부여받는 것에 유의하자.

4. 트랜잭션의 대상이 되는 블록들을 버퍼 캐시로 적재하고 블록 헤더의 ITL(Interested Transaction List)에 트랜잭션 엔트리(Transaction Entry)를 등록한다. 만일 ITL에 엔트리를 등록할 공간이 없다면, 공간이 확보될 때까지 enq: TX - allocate ITL entry 이벤트를 대기한다.

5. 변경할 블록들의 변경 정보는 PGA에 체인지 벡터라는 이름으로 저장된다. 보통 하나의 로우가 변경되는 경우 각각 언두 헤더 블록(체인지 벡터#1), 언두 블록(체인지 벡터#2), 데이터 블록(체인지 벡터#3)에 해당하는 체인지 벡터들이 생긴다. 프로세스는 PGA의 체인지 벡터들을 리두 레코드(또는 리두 엔트리)라는 이름으로 리두 버퍼(Redo Buffer)로 복사한다. 리두 버퍼에 변경 내용을 복사하는 과정에서 redo copy 래치, redo allocation 래치, redo writing 래치를 획득해야 한다. 이 과정에서 래치 경합이 발생하면 각각 latch: redo copy, latch: redo allocation, latch: redo writing 이벤트를 대기한다.

6. 이전 이미지(Before Image)에 대한 정보를 언두 블록에 기록하고, 데이터 블록을 변경한다. 변경된 데이터 블록은 더티(Dirty) 상태가 된다. 또한 변경된 데이터 블록에 대한 CR 블록이 버퍼 캐시에 생성된다. 만일 변경하고자 하는 로우가 현재 다른 트랜잭션에 의해 변경 중(즉 변경 후 아직 트랜잭션이 종료되지 않은 상태)이라면 해당 트랜잭션이 종료되기를 기다려야 하며 enq: TX - row lock contention 이벤트를 대기한다.

7. 커밋이 수행되면, 트랜잭션에 SCN을 할당한다. 커밋 정보는 리두 버퍼에 저장된다.

8. 언두 세그먼트 헤더의 트랜잭션 테이블에 커밋이 이루어졌음을 저장하고, 락을 포함한 모든 리소스에 대한 점유를 해제한다.

9. 리두 버퍼의 내용이 리두 로그 파일에 기록된다. 변경된 블록들은 이후 DBWR 프로세스에 의해 데이터 파일로 기록된다. 트랜잭션과 관련된 리소스들을 그림으로 표현하면 아래 그림과 같다. 그림:트렉젝션 리소스.jpg