[Oracle] 오라클 블록 클린아웃, Block Cleanout
오늘은 어디선가 들어본 적 있는 블록 클린아웃에 대해 알아보자.
우선 cleanout은 '청소'라는 뜻이므로 『블록 청소』 뭔가 dirty 상태의 블록을 free 상태로 바꿔주는 행위같다는 느낌적인 느낌이 든다.
블록 클린아웃 (Block Cleanout)
- 트랜잭션에 의해 설정된 로우 Lock을 해제하고 블록 헤더에 커밋 정보를 기록하는 오퍼레이션
- 보통은 트랜잭션 커밋 후 블록 클린아웃까지 완료해야 완전한 커밋이라고 할 수 있지만 대량 갱신 작업 후에는 시간 관계상 커밋 정보를 트랜잭션 테이블에만 기록하고 빠르게 커밋을 완료, 나중에 해당 블록이 처음 액세스되는 시점에 블록 클린아웃을 함
흠.. 커밋을 때리면 Redo Log Buffer의 정보를 Redo Log File에 기록한다 라고 알고 있는데 위 내용과 어떻게 연관성이 있는건지 차근차근 정리해보도록 하자.
※ Redo Buffer의 내용을 Redo Log File에 기록하는 시점
① 매 3초마다
② Redo Log Buffer의 1/3이 찼을 때
③ 사용자가 Commit or Rollback을 날렸을 때
→ 해당 Transaction과 관계된 모든 Redo 정보를 Log File에 저장하고 나서 Commit을 완료: Log Force at Commit
④ DBWR에 의해 신호를 받았을 때
→ Data Buffer Block을 Disk로 기록하기 전에 Redo Buffer Log를 먼저 기록: Write Ahead Log
TRANSACTION
① 사용자가 쿼리(DML)를 날린다.
② 해당 트랜잭션에 대해 Undo Segment를 할당한다.
※ Undo Segment
구조적으로 데이터를 저장하는 일반 테이블 세그먼트와 동일, 각 트랜잭션 별로 Undo 세그먼트 할당, 트랜잭션이 발생시킨 테이블과 인덱스에 대한 변경 사항을 Undo 레코드 단위로 Undo 세그먼트 블록에 기록
③ 할당받은 Undo Segment Header에 트랜잭션 테이블 슬롯을 생성한다.
④ 트랜잭션 테이블 생성 후 TXID(트랜잭션 ID)를 생성하고 해당 트랜잭션에 할당한다.
※ TXID
트랜잭션에 할당된 Undo Segment의 Header에 존재하는 트랜잭션 테이블의 정확한 위치를 가리킴
(흠.. 뭔가 RowID랑 비슷한 거 같다!)
⑤ 트랜잭션의 대상이 되는 블록들을 버퍼 캐시로 적재하고 블록 헤더의 ITL에 트랜잭션 엔트리를 기록한다.
⑥ 이전 정보를 Undo 블록에 기록하고 데이터 블록을 변경한다. 변경된 데이터 블록은 Dirty 상태가 되고 해당 블록에 대한 CR블록이 버퍼 캐시에 생성된다.
⑦ 사용자가 커밋을 때린다.
⑧ 트랜잭션에 SCN(System Commit Number:global)을 할당한다. 커밋 정보는 Redo Log Buffer에 저장된다.
⑨ Undo Segment Header의 트랜잭션 테이블에 커밋이 됐음을 저장한다.
⑩ Redo Log Buffer의 내용을 Redo Log File에 기록한다.
⑪ 블록 헤더의 ITL 슬롯에 커밋 정보를 저장한 후 Lock을 해제한다.
▶ ⑪이 수행되는 시점에 의해 Delayed 블록 클린아웃과 커밋 클린아웃으로 나뉜다.
Delayed 블록 클린아웃
- 트랜잭션이 갱신한 블록 개수가 총 버퍼 캐시 블록 개수의 1/10을 초과할 때 사용
- 커밋 이후 해당 블록을 액세스하는 첫 번째 쿼리에 의해 클린아웃
* 블록을 읽는 과정에서 Active 상태의 블록을 만났을 때
(다른 트랜잭션이 발생시킨 변경사항에 대한 커밋 정보가 ITL에 기록되기 전 일때)
① 블록 클린아웃을 시도
② ITL 슬롯에 기록된 트랜잭션 ID 확인
③ 확인한 ID를 이용해 Undo 세그먼트 헤더에 있는 트랜잭션 테이블 슬롯 탐색
④ 트랜잭션의 현재 상태가 커밋이라면 ITL 슬롯에 반영
⑤ 로우 Lock 정보 해제
커밋 클린아웃 (=Fast 블록 클린아웃)
- 트랜잭션이 갱신한 블록 개수가 버퍼 캐시 블록 개수의 1/10을 초과하지 않을 때 사용
① 커밋 시점에 ITL 슬롯에 커밋 정보 저장 → Lock Byte는 해제하지 않음 (로깅을 수행하지 않기 위해)
② 해당 블록을 갱신하기 위해 Current 모드로 읽는 시점에 Lock Byte 해제
③ Online Redo에 로깅 (Delayed Logging Block Cleanout) → Delayed Block Cleanout과 혼동하지 말자!
이해하기 쉽게 비유를 하자면 블록 클린 아웃은 설거지와 비슷하다.
밥 먹고 나서 바로 설거지를 하면 Fast 블록 클린 아웃,
놔뒀다가 다음 끼니 먹기 직전에 설거지를 하면 Delayed 블록 클린 아웃
ITL과 블록 클린아웃
Itl Xid Uba Flag Lck Scn/Fsc
0x0l 0x0004.00c.000035c3 0x008005a2.042f.lc --U- 1 fsc 0x0003.03536d7f
0x02 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.035368ge
0x03 0x0005.00d.000003c4 0x00801a0b.0ldl.ld C-U- 0 scn 0x0000.006770c0
1번 슬롯
- Fast 클린아웃한 상태 (Lck:1 / fsc / Flag:U)
- 쓰기 작업을 위해 블록 액세스 시 Lock Byte 해제 → 2번 슬롯과 같은 상태로 바뀜
3번 슬롯
- 완전히 클린아웃된 상태이이고 언제든 재사용도 가능하지만 추정된 커밋 상태 (Flag:C-U-)
추정된 커밋 상태가 뭔진 모르겠지만 일단 오늘은 여기까지..!