2. 리두와 언두
복구와 읽기 일관성에 대한 거의 모든 것에 대한 대답 :
필자는 오라클의 가장 중요한 기술요소로 체인지 백터(Change vector)를 꼽는다.
체인지 백터는 리두와 언두의 핵심이며, 데이터 블록에 대한 변경을 설명하기 위한 메커니즘이다.
또한 사용자의 데이터를 안전하게 유지하고, 읽기와 쓰기간의 경합을 최소화하고, 인스턴스 복구, 미디어복구, 모든 Standby 아키텍쳐, flashback 메커니즘, change data capture(CDC) 및 스트림을 위한 기술요소로 가장 먼저 다루어야 할 기술요소이다.
오라클 데이터베이스의 특징 중 하나는 데이터를 두번 기록한다는 것이다.
데이터의 한본은 데이터파일 내에 존재한다.
데이터의 또다른 한본은 리두로그파일에 존재한다.
변경 전 | 변경 후 |
{code}tab 0, row 4, @0x1d3f tl: 117 fb: --H-FL-- lb: 0x0 cc: 4 col 0: 2 c1 0a col 1: 2 c1 06 col 2: 6 78 78 78 78 78 78 col 3: 100 30 30 30 30 30 30 30 30 30 30 30 ... {code} | {code}tab 0, row 4, @0x2a7 tl: 121 fb: --H-FL-- lb: 0x2 cc: 4 col 0: 2 c1 0a col 1: 2 c1 06 col 2: 10 59 59 59 59 59 59 59 59 59 59 col 3: 100 30 30 30 30 30 30 30 30 30 30 30 ... {code} |
세번 째 컬럼의 사이즈가 증가하여 블록의 프리블록으로 해당 로우의 위치가 이동함
ITL의 두번째 슬롯을 사용함
*-----------------------------
* Rec #0xf slt: 0x1a objn: 45810(0x0000b2f2) objd: 45810 tblspc: 12(0x0000000c)
* Layer: 11 (Row) opc: 1 rci 0x0e
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080009a.09d4.0d
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x02c0018a hdba: 0x02c00189
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0 ckix: 16
ncol: 4 nnew: 1 size: -4
col 2: [ 6] 78 78 78 78 78 78
언두 블록 내의 언두 레코드에 변경 이전의 데이터가 기록된다.
REDO RECORD - Thread:1 RBA: 0x00036f.00000005.008c LEN: 0x00f8 VLD: 0x01
SCN: 0x0000.03ee485a SUBSCN: 1 03/13/2011 17:43:01
CHANGE #1 TYP:0 CLS:36 AFN:2 DBA:0x0080009a SCN:0x0000.03ee485a SEQ: 4 OP:5.1
ktudb redo: siz: 92 spc: 6786 flg: 0x0022 seq: 0x09d4 rec: 0x0f
xid: 0x000a.01a.0000255b
ktubu redo: slt: 26 rci: 14 opc: 11.1 objn: 45810 objd: 45810 tsn: 12
Undo type: Regular undo Undo type: Last buffer split: No
Tablespace Undo: No
0x00000000
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080009a.09d4.0d
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x02c0018a hdba: 0x02c00189
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0 ckix: 16
ncol: 4 nnew: 1 size: -4
col 2: [ 6] 78 78 78 78 78 78
CHANGE #2 TYP:0 CLS: 1 AFN:11 DBA:0x02c0018a SCN:0x0000.03ee485a SEQ: 2 OP:11.5
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080009a.09d4.0f
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x02c0018a hdba: 0x02c00189
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 2 ckix: 16
ncol: 4 nnew: 1 size: 4
col 2: [10] 59 59 59 59 59 59 59 59 59 59
데이터에 대한 변경 사항(change vector)과 언두에 대한 변경사항(change vector)이 쌍(pair)을 이루어 리두 레코드로 기록된 것이 확인됨
언두와 리두를 위한 메커니즘은 ACID의 기본적인 요구사항을 구현하는데 충분할 뿐 아니라 성능과 복구 측면에서도 장점을 제공한다.
연속된 리두가 온라인 리두로구 파일에 기록되면, 일반적인 상황에서는 인스턴스에 의해서 다시 읽혀지지 않으므로 한 번 기록된 내용에 대해서 신경 쓸 필요가 없다. (Write and forget)
Point
오라클은 하나의 Redo allocation 래치를 exclusive모드로 획득하여야 로그 버퍼에 기록할 수있게 된다. 이는 다수의 프로세스가 로그버퍼 내의 동일한 공간에 동시에 기록하는 문제를 방지해 주지만 경합에 의한 리소스 소비와 대기 시간 증가를 일으킬 수 있다.
그러므로 리두를 가능한 빨리 온라인 리두로그로 저장하는 메커니즘이 필요.
10g에서는 private redo와 in-memory undo를 결합한 새로운 매커니즘이 소개됨.
private redo strand (x$kcrfstrand 구조) | in-memory undo pool (x$ktifp 구조) |
x$kcrfstrand구조내에는 private redo뿐만아니라 public 로그버퍼를 포함한다. Public로그버퍼의 개수는 cpu_count파라미터에 의해 결정된다. (추정 ceil(1+cpu_count) X$kcrfstrand구조내의 각 항목은 각각의 redo allocation래치에 의해 관리되며 각 public 로그 버퍼는 cpu 당 하나의 redo copy래치에 의해 추가적으로 관리된다. _log_parallelism_dynamic = true _log_private_parallelism=true | pool개수가 transactions파라미터에 의해 결정된다.( default transactions/10) 각 pool은 in memory undo latch에 의해 관리된다. _in_memory_undo=true _imu_pools |
<public redo/private redo 버퍼의 크기>
<9i vs 10g 수행비교>
1. 트랜잭션이 수행하는 동안 생성된 체인지 백터를 Private리두로그버퍼에 저장하고,
2. 트랜잭션이 완료되면, 해당 프로세스는 private리두로그버퍼를 public리두로그버퍼에 복사
3. 이후 기존의 로그버퍼 처리방식으로 수행되며, 트랜잭션 시 최소 1번의 public redo allocation 래치를 획득하게 된다는 것을 의미
SQL> select ktiffcat, ktiffflc from x$ktiff;
KTIFFCAT KTIFFFLC
-------------------------------------------- ---------
Undo pool overflow flushes 1
Stack cv flushes 49
Multi-block undo flushes 0
Max. chgs flushes 26
NTP flushes 0
Contention flushes 4
Redo pool overflow flushes 16
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 4569
Commit flushes 8850
Recursive txn flushes 10
Redo only CR flushes 1
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 143
Presumed commit violation 0
Securefile direct-write lob update flushes 0
19 rows selected.
모든 프로세스는 커밋 전 데이터를 확인하기 위하여 언제든지 언두 레코드를 액세스 할 수 있어야 한다
언두 레코드의 용도
읽기 일관성을 위해서 데이터블록의 복사본을 생성한 후 해당 복사본에 언두 레코드를 적용한다.
*-----------------------------
* Rec #0xf slt: 0x1a objn: 45810(0x0000b2f2) objd: 45810 tblspc: 12(0x0000000c)
* Layer: 11 (Row) opc: 1 rci 0x0e
Undo type: Regular undo Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------
KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080009a.09d4.0d
KDO Op code: URP row dependencies Disabled
xtype: XA bdba: 0x02c0018a hdba: 0x02c00189
itli: 2 ispac: 0 maxfr: 4863
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 0 ckix: 16
ncol: 4 nnew: 1 size: -4
col 2: [ 6] 78 78 78 78 78 78
Op : C는 동일 트랜젝션에 의해 이전에 변경된 것이 있다는 것을 의미한다.
rci 0x0e : 이전 언두 레코드 번호를 가르킨다.
언두의 중요한 용도는 변경에 대한 롤백이다.
록백 시에는 current블록을 확득한 후 current블록에 언두 레코드를 적용한다.
롤백은 트랜잭션의 이력에 대한 것으로 역순으로 트랜잭션에 대한 모든 언두 레코드를 검색할 필요가 있다.
이 때 이전 언두 레코드를 찾을 수 있는 Linked list 항목은 rci이며, 이전 언두레코드가 다른 블록에 있다면 rci 0x0, rdba: 언두블록주소로 표기된다.
롤백이 읽기 일관성과 차이나는 측면 :
롤백 시 추가적인 오버헤드 :