Contents

트랜잭션이 Undo에 접속하는 방법

!이미지 002.jpg!

  • 해당 트랜잭션에 대해 언두 세그먼트( Undo Segment )를 할당한다. (서버 프로세스가 언두 세그먼트를 획득하는 시점에 적당한 온라인 상태의
    언두 세그먼트가 없으면 온라인 상태의 언두가 확보될 때까지 enq: Us - contention )
    • 현재 온라인 상태인 언두 세그먼트 중 하나를 우선적으로 사용한다 ( 랜덤 ) \-> 언두 세그먼트 할당
    • 다른 트랜잭션이 사용중이라면 3번까지 재시도한다.
    • 3번까지 재시도 실패시 오프라인 상태의 언두 세그먼트를 온라인화해서 사용한다.
    • 온라인화 실패시 새로운 언두 세그먼트를 생성한다.
    • 언두 세그먼트 생성 실패시 8i에서 사용하던 롤백 세그먼트 알고리즘을 사용한다. ( 다른 트랜잭션에 의해 사용중인 언두 세그먼트 중 가장
      사용량이 적은 것을 사용한다. )
  • 언두 세그먼트를 할당받으면, 언두 세그먼트 헤더에 트랜잭션 테이블 슬롯( Transaction Table Slot )을 생성한다.
  • 트랜잭션 테이블을 생성하고 나면 TXID( Transaction ID )를 생성하고, 현재 트랜잭션에 할당한다.
    • TXID는 v$TRANSACTION 뷰의 XIDUSN, XIDSLOT, XIDSQN으로 표현하는데, 이값은 트랜잭션에 할당된 언두 영역의 언두 세그먼트 헤더에
      존재하는 트랜잭션 테이블의 정확한 위치를 가르킨다.
    • 트랜잭션은 반드시 언두 영역을 할당받은 다음에 ID를 부여받는 것에 유의하자.
  • 트랜잭션의 대상이 되는 블록들은 버퍼캐시로 적재하고 블록 헤더의 ITL( Interested Transaction List )에 트랜잭션엔트리
    ( Transaction Entry )를 등록한다.
    • 만일 ITL에 엔트리를 등록할 공간이 없다면, 공간이 확보될 때까지 enq: TX - allocate ITL entry 이벤트를 대기한다.
  • 변경할 블록들의 변경 정보는 PGA에 체인지 벡터라는 이름으로 저장된다.
    • 보통 하나의 로우가 변경되는 경우 각각 언두 헤더 블록( 체인지 벡터#1 ), 언두 블록( 체인지 벡터#2 ), 데이터 블록( 체인지 벡터#3 )에 해당하는 체인지 벡터들이 생긴다.
      프로세스는 PGA의 체인지 벡터들을 리두 레코드( 또는 리두 엔트리 ) 라는 이름으로 리두 버퍼( Redo Buffer )로 복사한다.
      리두 버퍼에 변경 내용을 복사하는 과정에서 redo copy 래치, redo allocation 래치, redo writing 래치를 획득해야 한다.
      이 과정에서 래치 경합이 발생하면 각각 latch:redo copy, latch: redo allocation, latch: redo writing 이벤트를 대기한다.
  • 이전 이미지( Before Image )에 대한 정보를 언두 블록에 기록하고, 데이터 블록을 변경한다. 변경된 데이터 블록은 더티( Dirty ) 상태가 된다.
    또한 변경된 데이터 블록에 대한 CR 블록이 버퍼 캐시에 생성된다. 만일 변경하고자 하는 로우가 현재 다른 트랜잭션에 의해 변경 중 ( 즉 변경 후 아직 트랜잭션이 종료되지 않은 상태 )이라면
    해당 트랜잭션이 종료되기를 기다려야 하며 enq: TX\- row lock contention 이벤트를 대기한다.
  • 커밋이 수행되면, 트랜잭션에 SCN을 할당한다. 커밋 정보는 리두 버퍼에 저장된다.
  • 언두 세그먼트 헤더의 트랜잭션 테이블에 커밋이 이루어졌음을 저장하고, 락을 포함한 모든 리소스에 대한 점유을 해제한다.
  • 리두 버퍼의 내용이 리두 로그 파일에 기록된다. 변경된 블록들은 이후 DBWR 프로세스에 의해 데이터 파일로 기록된다.
  • 변경할 블록들의 변경 정보는 PGA에 체인지 벡터라는 이름으로 저장된다.
    • 보통 하나의 로우가 변경되는 경우 각각 언두 헤더 블록( 체인지 벡터#1 ), 언두 블록( 체인지 벡터#2 ), 데이터 블록( 체인지 벡터#3 )에 해당하는 체인지 벡터들이 생긴다.
      프로세스는 PGA의 체인지 벡터들을 리두 레코드( 또는 리두 엔트리 ) 라는 이름으로 리두 버퍼( Redo Buffer )로 복사한다.
      리두 버퍼에 변경 내용을 복사하는 과정에서 redo copy 래치, redo allocation 래치, redo writing 래치를 획득해야 한다.
      이 과정에서 래치 경합이 발생하면 각각 latch:redo copy, latch: redo allocation, latch: redo writing 이벤트를 대기한다.
  • 이전 이미지( Before Image )에 대한 정보를 언두 블록에 기록하고, 데이터 블록을 변경한다. 변경된 데이터 블록은 더티( Dirty ) 상태가 된다.
    또한 변경된 데이터 블록에 대한 CR 블록이 버퍼 캐시에 생성된다. 만일 변경하고자 하는 로우가 현재 다른 트랜잭션에 의해 변경 중 ( 즉 변경 후 아직 트랜잭션이 종료되지 않은 상태 )이라면
    해당 트랜잭션이 종료되기를 기다려야 하며 enq: TX\- row lock contention 이벤트를 대기한다.
  • 커밋이 수행되면, 트랜잭션에 SCN을 할당한다. 커밋 정보는 리두 버퍼에 저장된다.
  • 언두 세그먼트 헤더의 트랜잭션 테이블에 커밋이 이루어졌음을 저장하고, 락을 포함한 모든 리소스에 대한 점유을 해제한다.
  • 리두 버퍼의 내용이 리두 로그 파일에 기록된다. 변경된 블록들은 이후 DBWR 프로세스에 의해 데이터 파일로 기록된다.

참조 - http://wiki.ex-em.com/index.php/Transaction

블록 클린아웃

  • 트랜잭션에 의해 설정된 로우 Lock 을 해제하고 헤더에 Commit 정보를 기록하는 Operation.
  • 대량의 갱신 작업후 트랜잭션 테이블에만 Commit 정보를 기록.
  • Delayed 클린아웃, 커밋 클린아웃(=Fast 클린아웃) 두가지 매커니즘으로 동작.

Delayed 클린아웃

!이미지 004.jpg!

  • 트랜잭션이 갱신한 블록 개수가 버퍼 캐시 블록 개수위 1/10 을 초과할때 사용
  • Commit 후 해당 블록을 액세스 하는 첫 번째 쿼리에 의해 클린아웃
    • ITL 슬로ㅅ에 커밋 정보 저장
    • 레코드에 기록된 Lock Byte 해제
    • Online Redo에 Logging
  • 다른 트랜잭션이 발생시킨 변경 사항이 ITL에 기록되지 않았다면 클린아웃 시도

커밋 클린아웃(=Fast 클린아웃)

!이미지 006.jpg!

  • 트랜잭션이 갱신한 블록 개수가 버퍼 캐시 블록 개수의 1/10을 초과하지 않을 경우 커밋 시점에 곧바로 블록 클린 아웃
  • OPS (Oracle Parallel Server) 환경에서 과도한 Ping 을 방지하기 위해 개발
    • 과거 OPS 환경에서는 일단 Dirty 블록을 디스크에 기록 하여 그것을 디스크에서 읽어가는 방식을 사용
      !이미지 005.jpg!
  • Lock Byte를 해제하지 않는 불완전한 클린아웃. 해당 불록을 갱신하는 다음 트랜잭션에 의해 완전 클린아웃 된다.

ITL과 블록 클린아웃

!이미지 61.jpg!

  • 0x01: - Fast 클린아웃
    • Lck=1 (로우 헤더에 Lock Byte가 해제되지 않음)
    • Scn/Fsc : FSC (Fast 클린아웃상태)
    • Flag: U
  • 0x02: - Dlayed 블록 클린아웃에 의해 클린아웃된 경우
    • Flag: C
    • Scn/Fsc: Scn 정확한 커밋 시점 정보
  • 0x03: - 추정된 SCN Commit Flag 가 C-U\-
    • Flag: C-U\-
    • Scn/Fsc: scn

참고 - http://blog.naver.com/dndwlstm/30128332110