Change Vector
리두와 언두의 핵심, 데이터 블록 변경을 설명하기 위한 메커니즘
안전한 데이터 유지 유지, 읽기/쓰기 경합 최소화, 인스턴스 복구, 미디어 복구, Standby 아키텍처, Flashback 메커니즘, CDC 및 Streams 를 위한 기술요소
※ 필자가 오라클의 가장 중요한 기술요소로 손꼽음
데이터 및 데이터 블록
내부 메커니즘 설명시 "데이터"는 데이터, 인덱스, 메타데이터 및 언두 까지 포함함
블록번호 | 저장내용 | 변경레코드 |
---|---|---|
블록#1 | 1, 3, 5, 7, 9 | 5, 7, 9 |
블록#2 | 2, 4, 6, 8, 10 | 6, 8 |
create table t1
as
select
2 * rownum - 1 id,
rownum n1,
cast('xxxxxx' as varchar2(10)) v1,
rpad('0',100,'0') padding
from
all_objects
where
rownum <= 60
union all
select
2 * rownum id,
rownum n1,
cast('xxxxxx' as varchar2(10)) v1,
rpad('0',100,'0') padding
from
all_objects
where
rownum <= 60
;
update
/*+ index(t1 t1_i1) */
t1
set
v1 = 'YYYYYYYYYY'
where
id between 5 and 9
;
-- 업데이트 전
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 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
-- 업데이트 후
-- Row 길이가 길어져 블록의 프리 영역으로 이동 됨 (@0x1d3f → @0x2a7), 블록 내 레코드 순서 유지 (row 4 / 다섯 번째)
-- 커밋 전 이므로 lock byte 변경 됨(lb:0x0 → 0x2) : ITL 내 두번째 슬롯을 사용하는 트랜잭션에 의해 락이 설정 됨
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 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30
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 <<< Op code: URP(Update Row Piece)
xtype: XA bdba: 0x02c0018a hdba: 0x02c00189 <<< 변경한 블록의 주소 (bdba:), 오브젝트 세그먼트 헤더 블록 주소(hdba:)
itli: 2 ispac: 0 maxfr: 4863 <<< ITL 슬롯 정보
tabn: 0 slot: 4(0x4) flag: 0x2c lock: 2 ckix: 16 <<< 테이블/레코드 정보 (첫번째 테이블, 다섯번째 레코드) ※ Cluster 내 블록 특성 고려
ncol: 4 nnew: 1 size: 4 <<< 컬럼갯수 (ncol:), 변경컬럼수 (nnew:), 크기증감 (size:)
col 2: [10] 59 59 59 59 59 59 59 59 59 59 <<< 컬럼#2 의 변경 후 값
*-----------------------------
* 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 <<<
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
DBMS_UTILITY
SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILES(TO_NUMBER('0080009a', 'XXXXXXXX')) FILE_NO,
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(TO_NUMBER('0080009a', 'XXXXXXXX')) FILE_BLOCK
FROM DUAL;
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
Private redo & in-memory undo
Session | SQL | read committed | read only | serializable |
---|---|---|---|---|
1 | SELECT * FROM T1; | 1 rows selected | 1 rows selected | 1 rows selected |
2 | INSERT INTO T1 SELECT * FROM T1; | |||
2 | COMMIT; | |||
1 | SELECT * FROM T1; | 2 rows selected | 1 rows selected | 1 rows selected |
1 | INSERT INTO T2 SELECT * FROM T1; | 2 rows created | ORA-01456 | 1 rows created |
write and forget
리두 로그 파일에 기록된 내용은 일반 적인 상황에서 다시 읽혀지지 않으므로 신경 쓸 필요가 없다.
이러한 "write and forget" 접근 방식은 리두를 매우 단순하게 처리할 수 있도록 한다.
※ 버퍼 캐시 내 버퍼가 손상 되면 디스크의 블록과 리두 로그를 이용하여 복구 한다.
log_parallelism
9.2.0.8
=======
Latch Gets Misses Sp_Get Sleeps Im_Gets Im_Miss Holding Woken Time ms
----- ---- ------ ------ ------ ------- ------- ------- ----- -------
redo copy 0 0 0 0 51 0 0 0 .0
redo allocation 53 0 0 0 0 0 0 0 .0
redo writing 3 0 0 0 0 0 0 0 .0
undo global data 3 0 0 0 0 0 0 0 .0
cache buffers chains 267 0 0 0 1 0 0 0 .0
Name Value
---- -----
redo synch writes 1
redo entries 51
redo size 12,668
redo wastage 228
redo writes 1
redo blocks written 26
10.2.0.3
========
Latch Gets Misses Sp_Get Sleeps Im_Gets Im_Miss Holding Woken Time ms
----- ---- ------ ------ ------ ------- ------- ------- ----- -------
redo writing 3 0 0 0 0 0 0 0 .0
redo copy 0 0 0 0 1 0 0 0 .0 <<< 급감
redo allocation 5 0 0 0 1 0 0 0 .0 <<< 급감
undo global data 5 0 0 0 0 0 0 0 .0
In memory undo latch 53 0 0 0 1 0 0 0 .0 <<< 급증(신규)
cache buffers chains 379 0 0 0 0 0 0 0 .0
Name Value
---- -----
redo synch writes 1
redo synch time 1
redo entries 1 <<< 급감
redo size 12,048 <<< 감소
redo wastage 352
redo writes 1
redo blocks written 25
undo change vector size 4,632
IMU commits 1
IMU undo allocation size 43,052
SQL> select indx, first_buf_kcrfa, strand_size_kcrfa from x$kcrfstrand;
INDX FIRST_BUF_KCRFA STRAND_SIZE_KCRFA
---------- ---------------- -----------------
0 070000000021E000 3694592 <<< public
1 07000000005A4000 3694592 <<< public
2 070000005244A000 132096 <<< private
3 070000005246B000 132096
4 070000005248D000 132096
...
175 0700000051B53000 132096
176 0700000051B74000 132096
177 0700000051B95000 132096
178 rows selected.
INDX UNDO_SIZE UNDO_USAGE REDO_SIZE REDO_USAGE
----- --------- ----------- --------- ----------
0 64000 4352 62976 3920
-- 하나의 세션에 할당될 수 있는 메모리는 약 64KB, 사용은 약 4KB
최적화를 위한 중요한 원칙
동일한 경합 위치에서 끊임없이 충돌하는 것 보다는, 분리된 위치에서 약간 더 일하는 것이 전체 사용자를 위해 더 좋은 방법
SQL> select ktiffcat, ktiffflc from x$ktiff;
KTIFFCAT KTIFFFLC
---------------------------------------- ----------
Undo pool overflow flushes 632
Stack cv flushes 73642
Multi-block undo flushes 0
Max. chgs flushes 2197
NTP flushes 0
Contention flushes 1208
Redo pool overflow flushes 0
Logfile space flushes 0
Multiple persistent buffer flushes 0
Bind time flushes 0
Rollback flushes 25099
Commit flushes 292164
Recursive txn flushes 700
Redo only CR flushes 61
Ditributed txn flushes 0
Set txn use rbs flushes 0
Bitmap state change flushes 112760
Presumed commit violation 0
Securefile direct-write lob update flush 0
es
19 rows selected.
*-----------------------------
* Rec #0xf slt: 0x1a objn: 45810(0x0000b2f2) objd: 45810 tblspc: 12(0x0000000c) <<< 언두 블록 내의 0xf 에 기록
* 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 <<< op: C 동일한 트랜잭션에 의해 이전에 변경된 것이 존재
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
-- uba: 0x0080009a.09d4.0d 해당 블록의 이전 버전 재 생성시 사용 정보
-- 이전 버전 재생성 : "xxxxxx" 는 로우4, 컬럼2 로 다시 복사, 0x0080009a.09d4.0d 는 ITL 엔트리 2로 다시 복사
구분 | 읽기 읽관성 | 롤백 |
---|---|---|
특징 | 싱글 블록에 대한 모든 언두 레코드의 링크드 리스트 검색 | 트랜잭션의 이력, 정확한 순서로 트랜잭션에 대한 모든 언두 레코드의 링크드 리스트 검색 |
차이점 | 메모리 내 데이터 블록 복사본 생성 후 언두 레코드 적용, 사용 후 빠른 폐기 가능 | current 블록 획득 후 언두 레코드 적용 |
언두 레코드의 backward 순 적용
1. 하나의 로우를 두 번 변경 (A → B → C)
2. 두개의 언두 레코드 생성
3. 원복시 B → A 전에 C → B 먼저 적용 필요 (두 번째 언두 레코드를 먼저 적용)