Commit record :
트랜잭션 커밋 시에 current SCN을 트랜잭션 테이블 슬롯에 기록하며, 해당 변경에 따른 리두 체인지 백터를 "Commit record"라고한다.
Fast commit :
커밋이 발생하면 헌두 헤더블록의 해당 트랜잭션 테이블 슬롯의 상태를 커밋된 것으로 변경, (Commit record 발생하여 rolling forward는 가능함)
Commit Cleanout :
세션이 데이터 블록을 변경할 때, 변경 블록에 대한 리스트를 메모리에 생성(최대 버퍼캐쉬의 1/10)하고 커밋 시 버퍼캐시내에 존재하는 블록들을 재방문하여 commit flag를 변경(U)하고 commit SCN을 설정한다.
Delayed block cleanout :
트랜잭션 커밋 시 트랜잭션 테이블 슬롯만을 변경한다면, 데이터블록을 정리하는 작업(lock byte 해제, fsc/scn 에 commit SCN설정, commit flag C--로 변경) 은 차후에 다른 세션에 의해 수행한다. (일의 분담을 통한 오버헤드 감소)
commit을 다루는 일반적인 logging 전략 :
SQL> drop table t1;
테이블이 삭제되었습니다.
SQL>
SQL> create table t1 (
2 id number,
3 small_no number(5,2),
4 small_vc varchar2(10),
5 padding varchar2(1000),
6 constraint t1_pk primary key (id)
7 )
8 pctfree 90
9 pctused 10
10 ;
테이블이 생성되었습니다.
SQL>
SQL> insert into t1
2 select
3 rownum,
4 1+ trunc(rownum/10),
5 lpad(rownum,10),
6 rpad('x',1000)
7 from
8 all_objects
9 where
10 rownum <= 500
11 ;
500 개의 행이 만들어졌습니다.
SQL> commit;
커밋이 완료되었습니다.
NAME DIFF
----------------------------------------- -------
IMU Redo allocation size 9436
bytes received via SQL*Net from client 574
commit cleanouts successfully completed 501
commit cleanouts 501
bytes sent via SQL*Net to client 369
redo size 140
IMU undo allocation size 52
user calls 3
SQL*Net roundtrips to/from client 2
enqueue releases 2
opened cursors cumulative 2
parse count (total) 2
non-idle wait count 2
execute count 1
db block gets 1
db block gets from cache 1
session cursor cache hits 1
user commits 1
session logical reads 1
redo synch writes 1
db block changes 1
calls to kcmgas 1
recursive calls 1
messages sent 1
redo entries 1
session uga memory 131024
Cleanout 항목은 500 이 나오지만 실제 읽었던 항목은 기록되지 않는다.
SQL> drop table t1;
테이블이 삭제되었습니다.
SQL>
SQL> create table t1 (
2 id number,
3 small_no number(5,2),
4 small_vc varchar2(10),
5 padding varchar2(1000),
6 constraint t1_pk primary key (id)
7 )
8 pctfree 90
9 pctused 10
10 ;
테이블이 생성되었습니다.
SQL>
SQL> insert into t1
2 select
3 rownum,
4 1+ trunc(rownum/10),
5 lpad(rownum,10),
6 rpad('x',1000)
7 from
8 all_objects
9 where
10 rownum <= 500
11 ;
500 개의 행이 만들어졌습니다.
SQL> alter system flush buffer_cache;
시스템이 변경되었습니다.
SQL> commit;
커밋이 완료되었습니다.
NAME DIFF
-------------------------------------- ----
IMU Redo allocation size 9436
bytes received via SQL*Net from client 574
bytes sent via SQL*Net to client 369
redo size 140
commit cleanout failures: block lost 101
commit cleanouts 101
IMU undo allocation size 52
non-idle wait count 4
user calls 3
opened cursors cumulative 2
SQL*Net roundtrips to/from client 2
parse count (total) 2
enqueue releases 2
session logical reads 1
execute count 1
db block gets 1
db block gets from cache 1
session cursor cache hits 1
user commits 1
redo entries 1
messages sent 1
redo synch writes 1
recursive calls 1
calls to kcmgas 1
db block changes 1
cleanout항목이 100번가량 처리되고 나머지 400블록은 포기한 것으로 추측됨, 이것을 오락클 런-타임 전략인 "통계적 추측" 유형이라고 함
update후 | checkpoint후 | commit후 |
---|---|---|
{code} OBJD COUNT(*) -- -- 267 2 58 2 18 2 68370 2 28 2 67130 2 424 3 75180 4 67127 4 4294967295 24 75179 546 {code} | {code} OBJD COUNT(*) -- -- 67251 1 5874 1 5873 1 67544 1 5841 1 67714 1 289 1 68370 1 67740 1 68371 1 5839 1 5870 1 67738 1 5834 1 5875 1 383 1 287 1 18 1 4294967295 14 {code} | {code} OBJD COUNT(*) -- -- 67251 1 5874 1 5873 1 459 1 457 1 67544 1 18 1 287 1 383 1 5841 1 67714 1 289 1 68370 1 67740 1 68371 1 456 6 4294967295 24 75179 500 {code} |
세션이 데이터 블록을 읽을 때 uncommit트랜잭션으로 추정되는 정보(ITL 및 Row lock)를 확인하게 되면 읽기 일관성 버전을 생성하여 "정확한 언두 세그먼트 및 테이블 슬롯으로 무슨일이 발생했었는지" 확인하게 된다.
언두 세그먼트가 존재하지 않을 경우 :
Sys.Undo$에서 관리하고 있는 최종 Scn Base#과 Wrap#을 이용하여 Commit SCN이 변경경되어 블록 클린아웃이 진행된다.
언두 세그먼트 슬롯이 재사용된 경우 :
트랜젝션 컨트롤 내의 Scn은 방금 재사용된 트랜잭션 테이블 슬롯의 commit SCN으로 변경된다. 즉 원하는 슬롯의 wrap#가 transaction id의 wrap#보다 크다면, 트랜잭션 컨트롤 내의 scn을 획득한다.
1. 새로운 트랜잭션이 시작될 때마다,
2. 트랜잭션 테이블의 기존 정보를 새로운 트랜잭션의 첫 번째 언두 레코드에 저장하고,
3. 트랜잭션 컨트롤 내의 포인터는 해당 레코드를 가리키며,
4. 해당 언두 레코드는 기존 포인터 값을 저장한다.
TRN CTL: : seq: OxOb02 chd: Ox0011 ctl: Ox001c inc : Oxoooooooo nfb: Ox0001
TRN TBL:
index state cflags wrap# uel scn dba
--------------------------------------------------------------
...
Ox11 9 OxOO Ox2d25 Ox001b OxOOOO.041c818a Ox00805805
...
Ox19 9 OxOO Ox2d24 Ox002e OxOOOO.041c8ld1 Ox00805cOb
...
Oxlb 9 OxOO Ox2d23 Ox0019 OxOOOO.041c81ce Ox00805c09
Oxlc 9 OxOO Ox2d24 Oxffff OxOOOO.041c907c Ox00805cOd
...
Ox27 9 OxOO Ox2d25 OxOOlc OxOOOO.041c9072 Ox00805cOd
...
Ox2e 9 OxOO Ox2dlf OxOOla OxOOOO.041c81d2 Ox00805806
-- 트랜잭션 컨트롤 영역에서 리스트의 헤드(chd)는 0x0011이고 꼬리(ctl)는 0x001c
-- 리스트의 헤드인 0x11(index 칼럼 값)의 uel칼럼 값은 0x001b를 가리키고
– 0x1b는 0x0019 ,0x19는 0x002e, 0x2e는 0x001a ... 0x27은 0x001c(리스트의꼬리인 ctl)
– 0x1c는 0xffff를 가리킴으로써 링크드 리스트는 끝내게 된다.
검증방향 :
chd항목과 ctl항목, uel항목의 관계확인
언두레코드의 첫번째 레코드와 위 항목간의 관계확인
-- 트래이스로 변경사항 추적
아래와 같은 시나리오로 진행
----------------------------------------
-- other session 17000 * update & commit
----------------------------------------
col owner format a10
col object_name format a10
select OWNER, OBJECT_NAME, OBJECT_ID, OBJECT_TYPE
from dba_objects
where object_name in ('T1', 'T_WOONG');
set serveroutput on
alter system switch logfile;
alter system switch logfile;
alter system dump undo header '_SYSSMU10_3176102001$';
alter system dump undo header '_SYSSMU1_1518548437$';
alter system dump undo header '_SYSSMU2_2082490410$';
alter system dump undo header '_SYSSMU3_991555123$';
alter system dump undo header '_SYSSMU4_2369290268$';
alter system dump undo header '_SYSSMU5_1018230376$';
alter system dump undo header '_SYSSMU6_1834113595$';
alter system dump undo header '_SYSSMU7_137577888$';
alter system dump undo header '_SYSSMU8_1557854099$';
alter system dump undo header '_SYSSMU9_1126410412$';
alter system dump datafile 6 block 171;
update t_woong
set v1 = 'AAAAA'
where id = 1;
select xidusn, xidslot, xidsqn
from v$transaction
where addr=(select taddr from v$session where sid= SYS_CONTEXT('USERENV', 'SID'));
alter system dump datafile 6 block 171;
execute dump_undo_block
execute dump_log
그러나 납득할 만한 결과를 얻지 못함
트랜잭션 테이블의 읽기 일관성 버전을 생성하는 단계
1. 메모리 내에 언두 세그먼트 헤더블록을 복제한다.
2. 트랜잭션 컨트롤을 마지막으로 변경한 트랜잭션의 첫 번째 언두 레코드를 찾기 위해서 트랜잭션 컨트롤 내의 uba를 사용한다.
3. 해당 언두 레코드는 언두를 적용해야 할 트랜잭션 테이블 슬롯과 해당 슬롯에 대한 commit SCN을 알려주므로, 해당 언두를 복제본에 적용한다.
4. 이 시점에 트랜잭션 테이블과 트랜잭션 컨트롤은 과거 시점으로 한 걸음 이동한 것
5. 충분히 작은 scn을 발견하지 못했다면 현재보다 이전 버전의 트랜잭션 테이블을 생성하며, 언두레코드를 모두 사용한 후에도 적절한 값을 찾지 못했다면 ora-01555에러가 발생한다.
ORA-01555
"Snapshot too old"로 알려진 에러번호이다. 이것은 이력을 무한대로 유지할 수 없기 때문에 발생한다.
특정 언두 세그먼트의 크기가 매우 커짐으로써 발생하는 언두 테이블스페이스의 비효율성 문제를 automatic undo management를 이용하여 자동적인 offline, online, shrink등을 자동으로 관리하게 하여 효율성을 높였다.
그리고 자동 언두관리에서 undo-retention파라미터를 이용하여 이력을 유지할 시간을 지정하여 이력을 유지할 시간을 지정할 수 있게 되었다.