ORA-01480: |
trailing null missing from STR bind value |
| Cause: | A bind variable of type 5 (null-terminated string) does not contain the terminating null in its buffer. |
| Action: | Terminate the string with a null character |
ORA-01480: |
trailing null missing from STR bind value |
| Cause: | A bind variable of type 5 (null-terminated string) does not contain the terminating null in its buffer. |
| Action: | Terminate the string with a null character |
참 골치 아픈 에러다 ...
Unable to connect to Oracle 은 여러가지의 의미를 가진다.
1. ORACLE 이 shutdown 되어 있는상태.
2. PL/SQL 구문검사시 해당 USER/PASSWD 가 일치하지 않는 경우.
3. LIstener 가 활성화 되지 않은 경우.
4. 기타 서버의 상태가 접속 가능 하지 않는 상황.
특히 PL/SQL 문장이 포함된 파일인 경우 위의 에러는 해당 USER 의 상태를 확인 하여야한다.
ID / USER 대소문자만 틀려도 위의 에러가 발생한다.
pcscfg.cfg 내에 있는 USERID=PROC5/PROC5
- PL/SQL 문법 검사시 사용된다.
자신의 코드 안에 있는 접속 USERID/PASSWD
- *.pc 를 c 로 변환하여, 실행파일을 수행시 해당 유저의 세션을 open 할때 사용한다.
- 실행파일을 수행하여 세션을 open 할때 유저정보가 틀리다면 위의 에러가 아닌 다른 에러를 출력한다.
ORA-01017 : invalid username/password: logon denied
PL/SQL 이 포함되지 않는 경우라면..
으로 변경한다.
SQL> conn proc/proc
ERROR:
ORA-28000: the account is locked
SQL> alter user proc account unlock;
User altered.
SQL> conn proc/proc
Connected.
.bash_profile 에 추가
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib
그래도 안되면 $ORACLE_HOME/lib 에 파일 이 있는지 확인후 없으면 링크
SYS 세션이 아닌 다른 세션에 Trace SQL 을 실행하면 ...
권한이 없다고 나온다.
alter session 권한을 주면 된다.
SQL> grant alter session to proc5;
Grant succeeded.
libstdc++.so.5 가 없어서 발생한 에러.
/usr/lib/ 에 libstdc++.so.5 링크를 만든다.
ln -s libstdc++.so.6.0 libstdc++.so.5
David L Mansfield 씀:
I have figured out why some people get this error. If you are installing under FC2, then the workaround fails. If you are running a pre-existing installation it works. Here's why:when the DBCA launches the oracle process to create the instance, it doesn't carry the environment variables (i.e. DISABLE_HUGETLBFS=1) to the child process (java bug?). So you cannot create a database. My workaround is:
As oracle user:
cd $ORACLE_HOME/bin
mv oracle oracle.bin
cat >oracle << "EOF"
#!/bin/bashexport DISABLE_HUGETLBFS=1
exec $ORACLE_HOME/bin/oracle.bin $@
EOFchmod +x oracle
I just this second finished the install and it works!
64비트 리눅스 에서 오라클을 설치할때 나는 오류이다.
해당 라이브러리를 설치.
위의 에러를 넘기고 다시 시스템 체킹시 오류가 발생한다면..
Problem Description
alert log 및 트레이스 화일에는 이와 같은 에러가 남게 된다.
ORA-00600: internal error code, arguments: 729, 560, space leak], [, ], [, ], [
Explanation
Heap dump의 내용과 어떤 경우에 이런 에러가 발생하는지에 대해 좀 더 자세히 알아보기로 한다.
Oracle이 process를 종료하면, 점유하였던 메모리와 release되는 memory를 비교하여
size가 정확히 일치하지 않으면 ora-600729 에러를 발생시키고, shutdown 시에 SGA 등을
모두 release하고 일부 메모리 영역이 여전히 남아있으면 ora-600730을 report하게 된다.
User가 oracle에 접속하면 user process가 생성이 되고, 각 user process마다 heap이 할당된다.
모든 프로세스들은 자신의 memory heap을 갖게 된다.
Heap을 구성하는 각 extent는 연속적인 chunk로 이루어져 있는데, 이러한 chunk들은 각각
다음과 같은 type들을 가질 수 있다.
1. FREE : free chunk는 heap manager가 다시 할당할 수 있는 비어있는 부분.
Free 영역은 할당된 chunk가 해제가 된 상태로 이것은 인접한 free chunk들과
merge한 다음에 Free list에 등록된다.
2. FREEABLE : freeable은 flush를 시켜서 다시 merge를 할 수 있는 후보.
SYS.X$KSMSP를 조회하면 freeable space에 대한 조각을 확인할 수 있다.
3. RECREATABLE : memory chunk가 heap에 할당될 때, chunk의 내용이 재생성가능한 것으로
명시할 수 있다. 이러한 option으로 생성되면, 이 chunk는 사용 중이지 않을 때 명시적으로
'unpinned'될 수 있다. 사용자가 heap으로부터 space를 요청할 때 공간이 없으면,
이러한 unpinned 혹은 recreatable chunk를 해제하고 사용할 수 있다.
Unpinned chunk는 LRU list에 존재하게 되어 무엇을 가장 먼저 비게 할 것인지 결정할 수
있으며, 이러한 방법은 row cache나 library cache에 이용된다.
4. PERMANENT : 이 영역은 일단 할당되면 해제되지 않는 메모리 부분인데, 각 heap descriptor는
이러한 permanent chunk 부분을 가리키는 pointer를 갖고 있다.
이 permanent chunk는 두 부분으로 나누어지는데, 앞 부분은 이미 permanent로 할당된
메모리 부분이고, 뒷 부분은 아직 할당되지 않은 reserved area 이다.
Chunk의 header에는 어느 부분부터가 reserved area의 시작인지 나타내는 pointer가 있다.
실제 permanent 메모리는 프로세스가 종료하여 heap 자체가 해제되면 그 영역도 해제가 된다.
5. FREEABLE WITH MARK
Permanent 메모리 영역을 해제할 때 완전히 free 시키지 않고, Freeable with MARK 상태로
두었다가 다시 restore 하기도 하는데, 이 chunk type은 oracle 10g 에서는 널리 알려져
있지는 않다.
Extent의 할당과 해제
연속된 chunk들의 집합을 extent라고 한다.
즉, heap에 포함되어 있는 extent들의 집합 안에서 요청한 크기의 조각을 할당받게 된다.
만약 이 때 발견하지 못하면, heap manager는 새로운 extent를 요청하여 이것을 heap에 추가한다.
각 extent는 오직 한 종류의 chunk type만 갖는 것이 아니고, 다양한 type의 chunk를 가질 수 있다.
프로세스가 memory chunk를 요청할 때 heap manager는 필요한 size 만큼의 공간을 할당해 준다.
프로세스가 종료하면 프로세스에게 할당되었던 모든 메모리는 자동으로 release가 된다.
프로세스 종료(logoff) 시 RECREATABLE chunk와 FREEABLE chunk는 FREELIST 로 등록되었다고
판단을 하고, 메모리가 release될 때 아직 남아 있는 할당된 heap들은 free가 되는데,
ORACLE server 입장에서는 일반적으로 heap이 free가 될 때 PERMANENT chunk로 할당된 chunk와
freelist 상에 있는 FREE chunk들을 free시킬 대상으로 삼는다.
프로세스가 FREEABLE 혹은 RECREATABLE type 으로 남아 있는 chunk를 발견한 경우는
해당 프로세스가 memory deallcation 을 제대로 수행하지 않았다는 것을 의미하게 된다.
이러한 상황을 space leak 이라 부른다.
오라클은 일반적으로 SGA heap, UGA heap, Large pool heap, 그리고, PGA heap에 대해
space leak을 check한다. Space leak error는 BACKGROUND_DUMP_DEST 또는
USER_DUMP_DEST 내에 trace file 안에 남게 된다.
Symptoms
Space leak problem은 일반적으로 trace information과 heap dump를 capture하여 떨어뜨리게 된다.
OS와 ORACLE process header 정보 다음에 trace file 내에 이와 같은 정보를 볼 수 있다.
*** 2006-10-03 18:43:11.598
*** SESSION ID:(34.50354) 2006-10-03 18:43:11.597
******** ERROR: UGA memory leak detected 560 ********
바로 위 라인을 보면 이 memory leak 은 UGA 영역에서 발생한 것이고, leak이 일어난 size는
560 bytes임을 알 수 있다.
Heap은 연속된 chunk의 집합으로 이루어지고, heap이란 heap descriptor와 extent라고 불리는
메모리 조각의 집합으로 구성되며, 각 extent는 연속된 메모리 조각으로 정의가 된다.
******************************************************
HEAP DUMP heap name="session heap" desc=0xaef81d0
extent sz=0xffb8 alt=32767 het=32767 rec=0 flg=3 opc=3
parent=0xaeb63e0 owner=0x7a4b7078 nex=(nil) xsz=0xffb8
위 dump에서 heap name은 SESSION HEAP 이고, Heap descriptor는 0xaef81d0 임을 알 수 있다.
아래의 extent 상세 정보를 보면 release되지 않은 chunk는 4085a350임을 나타낸다.
이것은 recreatable chunk이고, 그 size는 560 bytes이다. 이 수치는 729, 560, space leak
에러에 나타난 bytes와 수치가 정확히 일치한다.
EXTENT 0 addr=0x407cf048
Chunk 407cf050 sz= 65456 free " "
EXTENT 1 addr=0x408a0048
Chunk 408a0050 sz= 65456 free " "
EXTENT 2 addr=0x40890048
Chunk 40890050 sz= 65456 free " "
EXTENT 3 addr=0x40850048
Chunk 40850050 sz= 41728 free " "
Chunk 4085a350 sz= 560 recreate "bind var heap " latch=(nil)
EXTENT 4 addr=0x407df048
Chunk 407df050 sz= 65456 free " "
EXTENT 5 addr=0x40f91048
Chunk 40f91050 sz= 65456 free " "
EXTENT 6 addr=0x40880048
Chunk 40880050 sz= 65456 free " "
EXTENT 7 addr=0x40870048
Chunk 40870050 sz= 65456 free " "
메모리 leak issue를 분석할 때 FREEABLE과 RECREATABLE type의 chunk를 식별해야 한다.
그 수치는 에러의 arguments에 나타난 leak 현상을 보이는 memory bytes의 sum 과 일치해야 한다.
원인
ora-600729 error는 memory leak 현상으로 발생하는 오라클 에러라 할 수 있다.
그러나, 이러한 현상은 정상적인 경우도 발생할 수 있으며, 지속적으로 반복적으로 발생하여
memory free 영역이 계속 줄어드는 현상으로 나타나지 않는 한, 특별히 문제 시 되지 않으며,
일정 사이즈 이하의 leak은 message로 나타나게 하지 않도록 조치할 수 있다.
Workaround
아래의 예는 2M 이하의 leak 발생 시 에러가 나지 않게 하는 것으로, 만약 100k정도나 1~2M 이하의
leak 문제가 보인다면 발생하지 않게 이와 같이 셋팅할 수 있다.
event="10262 trace name context forever, level 2000000"
Solution Description
Space leak 문제를 어떻게 다룰지에 대해 자세한 사항은 다음의 문서에서 안내하고 있다.
Step 1. alert log를 review하고, trace file 정보를 분석해야 한다.
alert log 에는 이와 같은 에러가 남았을 것이다.
Sat Dec 02 21:52:17 2006
Errors in file d:\oracle\admin\testdb\udump\testdb_ora_5928.trc:
ORA-00600: internal error code, arguments: 729, 152, space leak], [, ], [, ], [
a. argument 729는 space leak 문제 발생 시 대표적인 에러 code이다.
b. argument 152는 에러에 보고된 leak된 bytes의 수치이다.
c. argument space leak 는 항상 space leak 으로 나타난다.
Step 2. 연관된 트레이스 화일 분석
일반적인 trace information은 다음과 같다.
*** 2006-12-13 02:01:13.859
*** SESSION ID:(54.11635) 2006-12-13 02:01:13.859
******** ERROR: UGA memory leak detected 152 ********
******************************************************
위 트레이스는 UGA로부터 leak된 메모리라는 것과 memory leak의 size가 152 bytes 라는 것을
의미한다.
Step 3. leak이 session logoff로부터 발생했다는 것을 확인한다.
Call Stack Trace 부분을 보면 opilof 가 stack 상에 보인다면 이것은 session logoff 시
발생했음을 알 수 있다.
실제 발생한 call stack trace의 예는 다음과 같다.
Call Stack Trace
==========
calling call entry argument values in hex
location type point (? means dubious value)
========= ======== ============ ==============
ksedmp()+184 ? ksedst() 800000010000B938 ?
ksfdmp()+32 ? ksedmp() 800003FFBFFF6418 ?
kgeriv()+152 ? ksfdmp() 20000000B168 ?
kgesiv()+132 ? kgeriv() 40000000000002D9 ?
ksesic2()+124 ? kgesiv() 000000000 ?
ksmuhe()+1040 ? ksesic2() 000000000 ?
ksmugf()+400 ? ksmuhe() 000000000 ?
ksuxds()+2692 ? ksmugf() 800003FFBFFF4020 ?
ksudel()+104 ? ksuxds() 8000000100131B38 ?
opilof()+876 ? ksudel() 800003FFBFFF5808 ?
opiodr()+2416 ? opilof() 0650AB9D8 ?
ttcpip()+1320 ? opiodr() 8000000100004790 ?
opitsk()+1260 ? ttcpip() 000000100 ?
opiino()+1484 ? opitsk() 8000000100138268 ?
opiodr()+2416 ? opiino() 000001560 ?
opidrv()+752 ? opiodr() 800003FFBFFF0870 ?
sou2o()+40 ? opidrv() 000000000 ?
main()+228 ? sou2o() 000000000 ?
Step 4. Dedicated Server인지, MTS 환경인지 확인한다.
1) 만약 Dedicated server 환경이라면 이 error의 impact은 process가 종료할 때 끝날 것이다.
사실 에러의 영향도는 거의 없고, 데이타베이스에 실질적인 문제는 없을 것이다.
2) MTS(Multi Threaded Server) 환경이거나 XA transaction process manager/monitor를 사용하는 환경이라면
leaked memory가 SGA 영역에 있을 것이다. 이 때에는 ora-4030, ora-4031 과 같은 다른 에러가 발생했는지
alert log를 보아야 한다.
Step 5. Leak problem을 무시할 수 있는가 ?
1) 이 물음에 대해서는 다른 에러는 없는지 우선 살펴보아야 한다. 만약 동시에 발생한 다른 에러가 전혀 없다면
이 에러는 무시해도 되고, 다시 재현하기가 쉽지 않은 case일 것이다. 무엇보다도 90,000 bytes 보다 작은
size의 leak은 중요하지 않다. 이에 대한 solution은 event 10262 를 셋팅하는 것이다.
2) 만약 leak이 SGA 내에 발생했는가?
ALERT log를 살펴보고, shared pool 이나 OS memory 와 관련한 추가적인 문제는 없는지 ORA-4030 또는
ORA-4031 발생 여부를 확인해야 한다.
3) 메모리 leak 현상이 특정 작업을 수행 시에 재현이 되는가?
만약 특정 작업 시에 재현이 된다면, leak 현상이 known bug인지 확인을 위해
추가적인 investigation이 필요한 경우이다.
다음 문서를 보면 known bug 와 fix된 version들을 확인할 수 있다.
Note 31056.1 ORA-600 729 UGA Space Leak for a list of known bugs and fixes
Step 6. Event 10262 셋팅하기
만일 leak된 bytes 수치가 무시해도 될 만한 수치라는 것이 확인이 되면, 이 에러를
무시하기 위해 event를 걸 수 있다.
이 event를 셋팅을 하게 되면 90,000 bytes보다 작은 크기의 leak에 대해서는 alert log에 나타나지 않게 할 수 있다.
a. 다음과 같이 initSID.ora file에 event를 셋팅한다.
event="10262 trace name context forever, level 90000"
b. 데이타베이스를 restart해야 event가 효력을 미친다.
참고
만일 level 을 1로 하게 되면, space leak checking이 disable된다. 1로 하게 되면 매우
큰 사이즈의 memory leak을 놓칠 수 있으므로, 권장하지 않는다.
Level 을 1보다 큰 수로 하게 되면 event 안에 명시된 숫자보다 작은 memory leak에
대해서는 무시하도록 하는 역할을 한다.
Reference documents
<Note:403584.1> Understanding and Diagnosing ORA-600 729 Space Leak Errors
출처 : http://kr.forums.oracle.com/forums/thread.jspa?messageID=3254377�
delayed Block Cleanout Problem (ORA-1555)
수만 개의 row를 가진 테이블을 갱신하는 transaction이 있다고 가정하자.
테이블의 데이타를 갱신하기 위해 상기 작업은 수많은 블록을 접근한다.
유저가 commit을 했을 때 오라클은 이러한 블록들을 다시 접근하여 permanent한
형태로 만들어 주지 않는다. 그러한 작업은 다음 transaction에 의해 수행되며
그 작업은 update에 의해 영향을 받은 block을 접근하여 그것을 깨끗한 형태로
다시 만들어 주는 작업을 말한다. (즉 delayed block cleanout 이라 함)
오라클이 데이타베이스 블록을 update 시마다 그 블록의 header에 롤백 정보를
가지고 있는 롤백 세그먼트에 대한 pointer 정보를 가지게 된다.
(이러한 정보는 다음에 유저가 'undo' 작업을 요구할 때 사용된다)
Commit되는 시점에서 데이타베이스는 단순히 rollback segment header entry에
commit이 되었다는 표시만 하게된다. 그 후 변경된 블록을 다른 transaction이
다시 방문할 때 오라클은 그 데이타블록의 헤더정보를 보고 이것이 과거 어떤
시점에 변경되었다는 것을 알게된다.
이 때 데이타베이스는 그 변경된 내용이 commit되었는지 아니면 아직 commit되지
않았는지 확인할 필요가 있다. 이러한 작업에는 이전 갱신 작업에서 사용된
rollback segment의 header정보를 참조하여 commit되었는지 그렇지 않은지
판단하게 된다.
그 블록이 commit되었다는 것을 알게 되면 data block의 header는 다시는 상기
작업을 반복하지 않도록 수정된다.
이러한 작업을 정상적으로 수행하는 도중에 rollback segment transaction
table의 overwriting에 의해 ORA-1555가 발생할 가능성이 있다. 다음에 그
예를 들어본다. (어떤 SCN을 가진 QUERY ENVIRONMENT을 *QENV scn*이라 한다)
EXAMPLE>
1. session 1은 time T1에 QENV 50
2. session 1 은 query 도중 B1 block을 select한다.
3. session 1은 SCN 51에 block을 update 작업을 수행한다.
4. session 1은 상기 갱신작업을 commit한다.
(이 때 다른 transaction들은 위의 rollback segment information을
overwrite할 수 있다.)
5. 임의의 다른 session이(session 1일수도 있고 다른 session들일 수도 있다.)
일련의 transaction commit 들에 의해서 같은 rollback segment를 사용한
다.
각각의 transaction들은 rollback segment transaction table의 slot들을
사용하게 되며 slot들은 circular하게 사용되므로 결국에 가서는 이전의
slot을 overwrite하게 된다. 오라클은 commit된 transaction에대해서는
재사용할 수 있다.
6. session 1의 query가 변경된 block을 다시 접근한다고 가정하면 이전 image
가 필요하게 된다.
이때 오라클은 data block에 의해 지칭되는 rollback segment header의
transaction slot을 찾게된다. 그때 오라클은 다른 transaction들에 의해
overwrite되었다는 것을 알게 된다. 오라클이 변경된 rollback segment
transaction table을 원래 상태로 되돌리지 못한다면 ORA-1555 에러 메시
지를 내보내게 된다.
해결방법 >
1. 일반적인 ORA-1555 를 해결하는 방법을 사용한다.
2. 만약 delayed block cleanout에 의한 원인이 의심되면 아래와 같은 방법을
이용하여 변경된 block들을 clean out 시킨다.
Alter session set optimizer_goal = rule;
select count(*) from table_name;
Reference Documents
Configuration Tools
- Starting HTTP Server 설치에러 dblib.so.2 가 없을때.
- 해당 버젼 선택후 rpm 설치
- Retry
ORA-1555 (SNAPSHOT TOO OLD)의 일반적인 원인 및 조치사항
===========================================
PURPOSE
-------
ORA-1555 (snapshot too old)는 db 관리 업무에 익숙하지 않은 경우, rollback
관련된 오류 중 혼란을 일으키기 쉬운 오류이다.
이미 문서 <bulletin:11152>와 그외 자료가 이 오류를 설명하고 해결하기 위해
만들어져 있지만, ORA-1555 원인 파악을 위해 내용이 다소 길고 복잡하게
구성되어 있는 편이다.
여기에서는 발생 가능한 여러가지 원인 중 일반적인 원을을 위주로, 초보자도
쉽게 이해할 수 있도록 간단히 설명한다.
Explanation
-----------
일반적으로 ORA-1555에 혼란을 일으키는 원인은 한편으로는 오류 메시지 자체에
있다고 볼 수 있다.
ORA-1555: snapshot too old: rollback segment %s too small
이와 같은 오류에서 마치 ora-1555가 rollback segment에 write시 space가
부족해서 발생하는것으로 착각하는 사용자가 많다.
중요한 것은 ORA-1555는 rollback segment에 정보를 write시에 발생하는 것이
아니고 rollback segment로 부터 before image를 읽으려는 시점에서 발생한다는
것이다.
쉬운 예를 들어보자.
(1) 사원이 천명인 회사에서 select한 문장으로 그 전체 사원의 정보를 읽는데
10분이 걸린다고 가정한다.
(2) 100번 사원 정보를 읽는데, 아직 읽지 않은 700번 사원에 대해 다른 session에서
급여를 인상하는 update문장을 수행하고 commit을 한다.
select문장은 lock을 걸지 않기 때문에 select도중 다른 update문장이
수행되고 commit하는데 아무 문제가 없다.
(3) 1번에서 수행중인 select문장이 계속 진행되면서 700번 사원 정보를 읽으려고
하면 이 정보가 수정되어 변경되었음을 알게 된다.
그럼 select문장은 정보의 일관성을 위해 첫번째 사원을 읽기 시작한 시점의
700번 사원에 대한 정보를 읽기 위해, 즉 before image를 읽기 위해
rollback segment를 찾아간다.
(4) rollback segment내에 급여 인상 전 정보가 있으면 읽는다.
단 이때,
이 시스템에 트랜잭션이 매우 많아서 commit이 매우 많이 발생한 경우
이미 2번에서 변경하고 commit한 정보는 다른 트랜잭션에서 overwrite했을
수 있다.
이런 경우 before image를 읽으러 간 select문장은 ora-1555를 만나게 되는
것이다.
(5) 4번에서 ora-1555를 만난 경우 다시 동일한 select문장을 수행하면,
이번에는 이미 급여가 인상된 후의 시점에서 시작하므로 700번 사원을
읽는 경우에도 급여 인상전의 before image가 필요하지 않아 ora-1555는
다시 발생하지 않을 수 있다.
이러한 이유로 ora-1555는 발생했다 안했다 하는 식으로 일정하게 발생되지
않고, 조치 방법이라는것도 100% 안전하기보다는 확률적으로 충분히 만나지
않을 수 있는 환경을 만드는것이라고 볼 수 있다.
결국 ora-1555가 발생하는 것은 읽어야 하는 before image가 다른 트랜잭션에
의해 이미 overwrite되어 읽을 수 없는 경우 발생하므로, 발생하지 않게 하기
위해서는 데이타를 조회시 consistency를 유지해야 하는 시점동안 가능하면
오래 동안 rollback의 image가 유지되어야 하는것이다.
이렇게 이미 기록된 정보를 가능하면 오랜 기간동안 유지한다는 것은 새로운
트랜잭션의 기록을 위해 space를 확보해야 하는 작업과는 반대된다.
즉, ORA-1562와 같이 rollback segment를 write시에 space가 부족하여
space를 확보하기 위한 조치 방법과, 이 ORA-1555의 조치 방법을 서로 상충되어
trade-off가 있음을 주의해야 한다.
두 오류를 모두 피해가기 위해서는 일반적으로 매우 큰 rollback space가
도움이 된다.
ORA-1555의 일반적인 발생 경우 및 해결 방법을 정리한다.
(1) 트랜잭션에 비해 rollback segment 갯수가 적은 경우
rollback segment하나에 동시에 기록 가능한 트랜잭션의 수는 rollback
segment header내의 transaction table의 entry갯수로 제한되어 있다.
이 수는 oracle version마다 다르지만 8i이상부터는 약 20개 정도이다.
(transactions_per_rollback_segment의 지정과는 무관한다.)
기본적으로 install시 생성되는 rollback segment는 4개인데, 이대로 놓고
사용한다면, 결국 80 (20 * 4) 만큼의 commit이 발생하고 난 뒤에는
다시 처음부터 transaction table의 entry 중 commit된 트랜잭션의
정보를 가지는 entry의 정보를 overwrite하게 되는 것이다.
해결 방법: rollback segment갯수를 증가시킨다.
즉 새로운 rollback segment를 create시킨다.
부작용: 제한된 rollback tablespace공간 내에서, 여러개의 rollback
segment를 유지하는것은 하나의 rollback segment가 평균 가질 수
있는 space가 그만큼 줄어드는 셈이다.
이 부작용까지 줄이려면, rollback tablespace자체가 충분히
커야 하고 space를 많이 요구하는 트랜잭션은 'set transaction
use rollback segment' 문장을 이용하여 큰 rollback을 지정하여
사용하도록 한다.
(2) rollback segment를 shrink하거나 optimal이 설정된 경우
rollback segment를 shrink하거나 optimal을 지정하게 되면 이미 쓰여진
rollback의 before image를 다른 트랜잭션이 overwrite도 하기 전에 미리
지워 버리게 되는 셈이다.
그러므로 이런 경우도 ora-1555의 원인이 된다.
해결 방법: optimal을 너무 적게 지정하지 말고, shrink를 너무 자주
하지 않는다. shrink를 수행 후 ora-1555가 발생하는 경우,
단지 다시 조회하는것만으로 앞의 예제 (5)번에서 설명한
이유로 인해, 해결되는 경우가 많다.
(3) proc와 같은 application에서 loop내의 fetch문장에서 자주 commit을
하는 경우
fetch문장은 loop를 도는 동안 일정하게 read consistency를 유지해야 한다.
그리고 미리 cursor를 정의시에 데이타를 읽어두는것이 아니고, fetch시에
loop를 돌면서 그때그때 데이타를 읽게 된다.
그런데 loop내의 dml에 대해 너무 자주 commit을 하게 되면 그만큼
여러개의 트랜잭션이 처리된 결과로 rollback segment의 transaction table이
빨리 사용되고 overwrite되게 된다.
해결 방법: loop내의 commit횟수를 줄인다. 예를 들어 loop를 돌때마다
commit하게 하였다면 천번에 한번 혹은 만번 loop를 돈 후
commit하는 식으로 늘려준다.
이 외에도 rollback tablespace자체의 space가 부족하여 transaction table의
entry들이 아직 overwrite되지도 않았는데, commit된 transaction이 사용한
rollback segment내의 space가 먼저 overwrite되는 경우도 있다.
그러나 일반적으로 rollback segment의 space를 너무 작게 유지하지는 않기
때문에 이렇게 space부족으로 ora-1555를 만나는 경우는 많지 않다.
이렇게 space가 절대적으로 부족한 경우는 rollback에 write하는 시점에서,
ora-1562가 먼저 발생하게 된다.
ora-1562에 대해서는 <bulletin:10823> "ORA-1562 분석 및 해결 방법
(ROLLBACK SEGMENT 크기 문제)"를 참조하고,
좀더 자세한 ora-1555의 개념에 대해서는 <bulletin:11152> "ORA-1555 원인
분석 및 조치 사항" 을 참조한다.
http://kr.forums.oracle.com/forums/thread.jspa?messageID=1698897
ORA-1555 Snapshot Too Old 에러가 발생하는 원인은 여러가지가 있을 수 있다. http://kr.forums.oracle.com/forums/thread.jspa?threadID=471354&tstart=285 ORA-1555 조치방법
게시일: 2007. 2. 4 오후 7:54
작성날짜 : 2005-11-06
이를 이해하기 위해서 오라클의 내부 메카니즘에 대해서 알아볼 필요가 있다.
오라클은 항상 Statement-Level Read Consistency를 유지한다. 즉, 하나의
Query 에서 읽어들이는 값은 그 Query가 발생한 시점의 값, 즉 Snapshot 을
반영한다. 따라서 Query 가 진행되는 동안 데이타가 변하더라도 Query의
결과값에는 아무런 영향을 끼치지 않는다.
오라클은 특정한 시점을 SCN(System Change Number)로 관리한다. 달리 말하면
SCN은 특정한 시점에서의 데이타베이스의 상태라고도 할 수 있다. Read
Consistency를 유지하기 위하여 Query가 실행되는 순간 해당 시점의 SCN이
세팅된다. 어떠한 Query든 조회 시점 이후의 SCN 값을 갖는 데이타를 읽어들여
서는 안된다.
Read Consistent Snapshot을 구현하기 위한 방법으로 롤백 세그먼트가
사용된다. 데이타가 변경되면 변경되기 이전의 값은 롤백 세그먼트에 기록되고
데이타 블럭 헤더에는 변경되기 이전 값이 기록된 롤백 세그먼트 블럭의 위치가
기록된다. 모든 데이타 블럭에는 가장 최근의 커밋 시점의 SCN이 기록되어
있다. Query 가 진행되면 데이타 블럭에서는 Query의 SCN 보다 이전의 SCN값을
갖는 블럭만이 읽혀지고 그 이후의 SCN 값을 갖는 블럭과 커밋되지 않은 값을
갖는 블럭에 대한 Query는 롤백 세그먼트에서 읽혀지게 된다. 이 때 만약 롤백
세그먼트에 원하는 블럭이 없어서 읽어들이지 못하게 되면 ORA-1555 에러가
발생하게 된다.
롤백 세그먼트는 트랜잭션이 끝나기 전까지 변경된 데이타의 원래 상태를
기록하고 있다. 그런데 트랜잭션이 종료되면 롤백 세그먼트에 의해 점유된
영역은 Free 상태로 되면서 다른 트랜잭션에 의해서 덮어씌워질 수도 있게
된다. 따라서 Query가 필요로하는 값을 가진 롤백 세그먼트 블럭이 더 이상
존재하지 않는 상황에서 그 블럭을 요구하게 되면 ORA-1555 에러가 발생하게
되는 것이다.
? ORA-1555 에러가 발생하는 경우
1. 데이타의 변경이 심한 데이타베이스에서 롤백 세그먼트의 갯수와 크기가
작을 경우에 발생한다. 많은 트랜잭션이 데이타를 자주 변경하고 커밋하게 되면
커밋된 트랜잭션이 이용하던 롤백 세그먼트 공간을 다른 트랜잭션이 이용하게
될 가능성이 많아진다.
따라서 긴 Query의 경우 원하는 값을 롤백 세그먼트에서 얻고자 할 때 이미
다른 트랜잭션이 그 값이 저장된 공간을 이용해 버리는 결과가 발생할 수
있다. 이와 같은 경우에는 크기가 큰 롤백 세그먼트를 이용하면 어느 정도 예방이
가능하다.
2. 롤백 세그먼트가 손상되어 읽을 수 없게 된 경우
3. Fetch Across Commit
한 테이블에 대하여 Query가 커서를 열고 루프 내에서 데이타를 Fetch하고
변경하고 커밋하는 과정에서 발생한다. 이 경우에는 ORA-1555 에러가 자주
발생할 소지가 있는데 예를 들어 커서가 SCN=10 에 Open되었다고 하자. 따라서
이 커서에 관련된 Fetch는 SCN<=10 인 블럭만을 읽어들여야 한다. 이
프로그램은 데이타를 Fetch 한 후에 변경하고 다시 커밋하는 과정을 계속
반복하는데 SCN=20에서 커밋했다고 하자. 만약 이후의 Query가 이전의 커밋된
블럭의 데이타를 요구할 경우 그 값이 이미 변경되었으므로 롤백 세그먼트를
검색 하지만 많은 변경이 있어왔기 때문에 SCN=10인 블럭을 찾지 못하고
ORA-1555 에러를 유발할 수 있다. 이를 방지하기 위해서는 커서가 Open된
상태에서는 커밋을 자주하지 않고 롤백 세그먼트 크기를 키워 나가도록 한다.
4. Fetch Across Commit 와 Delayed Block Clean Out
Delayed Block Clean Out 도 이 에러를 유발할 수 있다. 데이타 블럭이
변경되고 커밋되면 오라클은 롤백 세그먼트 헤더에 그 트랜잭션이 커밋되었다
고 기록하지만 데이타 블럭을 바로 변경하지는 않는다 (Fast Commit). 그리고
다음 트랜잭션이 변경된 블럭을 요구할 때야 비로소 변경 시키는데 이를
Delayed Block Clean Out 이라고 한다.
예를 들어 3 과 같은 경우에서 두개의 테이블에 대한 Query를 알아보자.
즉, 하나의 테이블로부터 데이타를 Fetch 하고 다른 테이블의 데이타를
변경한다고 하자. 데이타가 한쪽 테이블에서 커밋되고 있지만 데이타를
가져오는 테이블에 대해서는 Clean Out이 이루어지지 않았기 때문에 ORA-1555
에러가 발생할 수 있다. 이 문제는 커서를 사용하기 전에 Full Table Scan을
해주면 예방이 가능하다.
커서가 오픈된 상태에서의 커밋은 ANSI 표준에는 들어있지 않지만 오라클
에서는 지원이 된다. 하지만 ORA-1555 에러를 일으킬 수도 있다는 점에 유의
하여야 한다.
query시 발생하는 ORA-1555의 발생 원인과 조치 사항에 대해서 자세히 살펴 Explanation ORA-1555가 발생하는 주요 원인과, 이 오류 발생을 최소화할 수 있는 방법은 2. fetch across commit 3. delayed block clean out (2) xid1 트랜잭션이 update문을 이용하여 500번지 데이타 블럭의 2번째 Data Block 700 Rollback Segment Header 5 (5) 다른 트랜잭션이 데이타 블럭 500번지를 방문하였다. 4. OPTIMAL 크기가 아주 작을 때 (3) read consistent snapshot (read consistent view) (4) rollback segment의 wrap around/overwrite
본다.
ORA-1555가 발생하는 원인은 여러가지가 있지만 기본적으로는 사용자가 필요로
하는 롤백 세그먼트의 정보가 다른 트랜잭션에 의해 overwrite되어, 존재하지
않을 때 발생한다.
이 문서를 읽기 전에 기본적으로 알아야 하는 오라클의 read consistency와
관련된 다음 내용들은 이 문서의 마지막에 별첨으로 용어 및 개념에 대해 설명
하였으므로 참고할 수 있다.
(1) SCN (System Change Number)
(2) statement-read level read consistent
(3) read consistent snapshot
(4) rollback segment의 wrap around/overwrite
ORA-1555에 관한 자세한 설명에 앞서, 데이타 블럭과 롤백 세그먼트 사이의
구조에 대해 간단히 알아보도록 한다. 데이타 블럭의 헤더에는, 이 블럭 내에
포함된 데이타를 변경한 트랜잭션의 정보와, 롤백 세그먼트 내의 해당 active
transaction을 가리키는 영역이 존재한다. 롤백 세그먼트는 세그먼트의 첫 번째
블럭을 헤더 블럭으로 사용하는데, 그 안에 이 롤백 세그먼트를 최근에
사용한 트랜잭션들의 정보와, undo record들이 저장되어 있는 롤백 세그먼트 내의
주소가 저장되어 있는 트랜잭션 테이블이 포함되어 있다.
다음 예의 그림을 통해 다음과 같은 사항을 알 수 있다.
(1) 데이타 블럭 500번지의 row 2를 변경한 xid1 트랜잭션은 아직 commit
되지 않은 상태이다. 블럭의 헤더에는 트랜잭션이 아직 commit되지
않았다는 정보와 5번 롤백 세그먼트 헤더 내의 3번째 엔트리에 트랜
잭션의 정보와, undo record를 얻을 수 있는 자세한 정보가 있음을
알려준다.
(2) 롤백 세그먼트 5번의 3번째 슬롯은 이 트랜잭션이 변경한 undo record가
롤백 세그먼트내의 7109번지에 저장되어 있음을 나타낸다. 2, 4, nn번
엔트리의 경우는 이미 트랜잭션이 commit되었으므로, 다른 트랜잭션이
이 엔트리를 overwrite할 수 있다.
(3) xid1 트랜잭션에 의해 변경된 undo record가 포함되어 있는 6900, 7109
블럭은 link로 연결되어 있어 xid1 트랜잭션이 변경한 모든 record들의
before image를 구성할 수 있다.
Data Block 500 Rollback Segment Header 5
+------+-----------+---+ +----+------+----------+------+tx uncommitted 5,3 ----+ 01 xid4 ACTIVE 9012
+------+-----------+---+ | | 02 | xid9 | COMMITTED| 8100 |
| row 1 | --->| 03 | xid1 | ACTIVE | 7109 |---
| row 2 changed | | 04 | xid2 | COMMITTED| 7632 | |... .. .. ... ... 5098 row n nn xidm COMMITTED 6777
---------------------- +----+------+----------+------+ |
Block 6900 Block 7109 |
------------- ------------- |
| xid1 |<----+ | xid1 |<----+
| | | | | undo record undo record +------- 6900
------------- -------------
rollback segment block rollback segment block
다음과 같다.
1. 데이타베이스에 변경을 가하는 트랜잭션은 많고, 롤백 세그먼트는 크기도
작고, 갯수도 적은 경우
다음과 같은 상황을 가정할 수 있다.
(1) 약 30분이 걸려서 A 테이블의 대부분을 읽어야 하는 긴 query 하나를
수행시켰다.
이 때의 SCN이 10이었다.
(2) 위의 query가 결과값을 찾고 있는 동안, xid1 트랜잭션은 A 테이블에
대해서 update작업을 수행하고 commit하여 A table이 저장되어 있는
블럭 중 하나인 500번지 블럭의 SCN이 20으로 변경되었다
(3) query가 진행중인 동안 매우 많은 트랜잭션들이 database를 변경하고
commit하였다.
(4) 이 query가 500번지 블럭을 읽고자 할 때 SCN이 20임을 확인하고,
xid1 트랜잭션에 의해 변경된 undo record를 찾기 위해 롤백 세그먼트를
참조하였다.
(5) 그러나 xid1 트랜잭션은 이미 commit된 상태이고, query가 진행되는
동안 매우 많은 트랜잭션이 데이타베이스 변경 작업을 수행한 결과
롤백 세그먼트내의 xid1 트랜잭션의 undo record가 저장되어 있는
블럭이 다른 트랜잭션들에 의해 overwrite된 상태였다.
(6) ORA-1555가 발생한다.
해결 방법:
(1) 롤백 세그먼트의 크기를 크게 하고 갯수를 늘리면, 롤백 세그먼트가
wrap around/overwrite되는 주기가 늦추어진다.
(2) 트랜잭션의 수행이 많은 때에는 수행 시간이 오래 걸리는 query 문은
수행시키지 않도록 한다.
프로그램내에서 cursor를 선언하고 loop를 수행하면서 fetch하고 데이타를
변경하는 경우 많은 프로그래머들은 롤백 세그먼트의 사용량을 줄이기 위해서
매 loop시마다 commit을 한다. 그러나 cursor의 loop내에서 commit하는
것은 ANSI standard에서는 제공하는 것이 아니며, ORA-1555를 발생시킬 가능
성이 있다.
ORA-1555가 발생하는 경우는 (1)의 경우와 유사하다. cursor는 선언하고,
open시에 데이타를 읽는 것이 아니고 fetch 때마다 읽게 되므로 fetch를
수행하는 것은 long query를 시작하는 것과 같다. 즉, fetch문의 loop를
수행하는 동안, 처음 fetch문 수행시점의 SCN보다 작거나 같은 SCN의 데이
타를 읽어야 한다. 그런데 loop 수행시마다 데이타를 변경하고 commit하게
되면, commit한 block의 SCN은 증가되고 변경된 정보도 다른 트랜잭션에
의해 재사용되어질 수 있다. 이렇게 블럭은 변경되었으나, 변경된 정보가
이미 다른 트랜잭션에 의해 overwrite된 블럭의 데이타를 fetch하고자
하면, 오라클은 read consistent snapshot을 구성할 수 없게 되므로
ORA-1555가 발생하게 된다.
해결 방법:
(1) cursor 내에서 commit하는 횟수를 줄인다. 예를 들어 첨자를 이용해
5만건에 한번씩 commit할 수 있으며, 이렇게 되면 5만건의 데이타를
저장할 수 있는 큰 롤백 세그먼트가 있어야 한다.
(2) cursor 선언 시 구성될 active set의 범위를 줄인다. 즉 한번에 모든
데이타를 읽어 처리하기 보다는, where절을 이용하여 데이타를 나누어,
여러번에 걸쳐 수행한다.
(3) 1번의 경우와 마찬가지로, commit된 정보가 overwrite되는 주기를
늦추기 위해서 롤백 세그먼트의 갯수를 증가시키고 그 크기도 크게하면
도움이 된다.
오라클은 기본적으로 transaction이 commit하면, fast commit을 수행한다.
즉, 트랜잭션이 데이타를 변경시키고 commit하면, 변경된 데이타 블럭의
header부분에 트랜잭션이 commit되었음을 기록하는 것이 아니고 일단 롤백
세그먼트의 헤더부분에만 commit되었음을 기록한다. 이 후 그 데이타 블럭을
다른 트랜잭션이 access하게 되면, 그때 롤백 세그먼트의 정보를 이용하여
데이타 블럭에 commit된 상태를 반영하여 clean out시키는 것을 delayed
block clean out이라고 한다.
이 delayed block clean out이 어떻게 ORA-1555를 발생하게 되는지 다음의
상황을 살펴보면 된다.
(1) 다음과 같은 초기 상태를 가정할 수 있다.
500번지 데이타 블럭의 데이타를 변경하는 트랜잭션은 존재하지 않고,
rollback segment 5번 header의 3, 4, nn번째 트랜잭션 엔트리는 다른
트랜잭션에 의해 재사용되어 질 수 있다.
Data Block 500 Rollback Segment Header 5
+-------+-------------+ +----+------+-------------------+tx none 01 xid4 ACTIVE
+-------+-------------+ | 02 | xid9 | ACTIVE |row 1 03 xid7 COMMITTED row 2 04 xid2 COMMITTED ... .. .. ... ... row n nn xidm COMMITTED
--------------------- +----+------+-------------------+
데이타를 변경하였다.
500번지 데이타 블럭의 헤더에는 xid1 트랜잭션의 정보가 저장되고, 롤백
세그먼트 5번의 트랜잭션 슬롯 3 (5,3)을 가리키게 된다. COMMITTED로 표시
되었던 트랜잭션 슬롯 3번은 이제 ACTIVE 상태로 변경되었다.
Data Block 500 Rollback Segment Header 5
+-------+-------------------+ +----+------+-------------------+xid1 5.3uncommitted ----+ 01 xid4 ACTIVE
+-------+-------------------+ | | 02 | xid9 | ACTIVE |row 1 +---> 03 xid1 ACTIVE row 2 changed 04 xid2 COMMITTED ... .. .. ... ... row n nn xidm COMMITTED
--------------------------- +----+-------+------------------+
(3) xid1 트랜잭션이 commit을 수행하였다.
오라클은 롤백 세그먼트 헤더의 트랜잭션 테이블에서 xid1 트랜잭션의 정보를
찾아서 commit되었다고 기록하였다. 그러나 500번지 블럭의 헤더에는 commit
되었다는 정보를 기록하지 않는다. (fast commit)
Data Block 500 Rollback Segment Header 5
+-------+-------------------+ +----+-------+------------------+xid1 5.3uncommitted ----+ 01 xid4 ACTIVE
+-------+-------------------+ | | 02 | xid9 | ACTIVE |row 1 +---> 03 xid1 COMMITTED row 2 changed 04 xid2 COMMITTED ... .. .. ... ... row n nn xidmm COMMITTED
--------------------------- +----+-------+------------------+
(4) 데이타베이스에 변경을 가하는 매우 많은 트랜잭션이 수행되었다.
매우 많은 트랜잭션이 수행되어 롤백 세그먼트 헤더내에 있는 트랜잭션 테이블
의 엔트리가 대부분 재사용되었다. 트랜잭션 xid50이 롤백 세그먼트 5번의
3번째 슬롯이 COMMITTED로 표시되어 있으므로, 비어있는 엔트리로 인식하여
xid50에 관한 정보를 저장하였다.
+-------+-------------------+ +----+-------+------------------+xid50 5.3uncommitted ----+ 01 xid31 COMMITTED
+-------+-------------------+ | | 02 | xid46 | ACTIVE |row 1 changed +---> 03 xid50 ACTIVE row 2 04 xid60 COMMITTED ... .. .. .. ... row n nn xidmm ACTIVE
--------------------------- +----+-------+------------------+
새로운 트랜잭션인 xid70 트랜잭션이 500번지 블럭을 읽고자 하였다. (3)번의
그림에서 보듯이, 500번지 블럭 헤더에는 아직 commit되지 않은 트랜잭션이
이 블럭을 변경하였으며, before image를 구성할 수 있는 정보가 롤백 세그먼트
5번, 엔트리 3번에 있음을 나타낸다. 그러나 5번 롤백 세그먼트 헤더 내에 있는
트랜잭션 테이블의 3번 슬롯은 xid1번이 아닌 xid50번의 정보가 저장되어 있다.
즉, delayed block cleanout이 이루어지기 전에 롤백 세그먼트 헤더가 overwrite
된 것이다.
(6) xid7 트랜잭션은 read consistent snapshot을 구성할 수 없으므로
ORA-1555가 발생한다.
해결 방법:
(1) ORA-1555를 발생시킬 상황 이전에 읽고자 하는 테이블에 대해 full
scan을 실시한다면, 롤백 세그먼트안의 정보가 overwrite되기 전에
delayed block cleanout이 이루어지도록 할 수 있다.
(2) 1 ~ 4번의 모든 원인에 대해서 롤백 세그먼트를 크게 유지하면, 롤백
세그먼트의 정보가 overwrite되는 주기를 늦출 수 있어 ORA-1555를
피하는 데 도움이 될 수 있다.
롤백 세그먼트는 트랜잭션의 사용에 의해 한번 크기가 늘어나면 기본적으로
그 롤백 세그먼트를 지우고 다시 만들기까지는 크기가 줄어들지 않는다.
그러나 optimal size를 지정하게 되면, 롤백 세그먼트에서 새로운 extent를
요구하는 시점에, 현재 할당된 롤백 세그먼트의 크기와 optimal에 지정된
크기를 비교하게 된다. 할당된 공간이 optimal 크기보다 큰 경우, 할당된
extent중 active한 트랜잭션이 사용하고 있지 않은 extent들은 release시켜,
롤백 테이블스페이스의 공간으로 환원된다.
그러므로 이 optimal size가 지나치게 작다면, 트랜잭션이 commit되자마자
롤백 세그먼트 내의 정보는 잃게 될 것이다. 그러나, 위의 1 ~ 4번에서 살펴보
았듯이 이미 commit된 트랜잭션의 정보라 하더라도 이후에 필요하게 되는
경우가 발생하므로 이렇게 빈번히 commit된 트랜잭션의 정보가 포함되어 있는
롤백 세그먼트의 extent를 release시키는 것은 바람직하지 않을 수 있다.
해결 방법:
(1) optimal을 지정할 때는 20개의 extents정도의 크기정도로 지정하는
것이 적당하며, 그것보다 더 작게 지정하지 않도록 한다.
(2) 롤백 세그먼트를 많이 필요로 하는 batch job의 경우 set transaction
use rollback segment rollback_segment_name; 구문을 이용하여 특정
롤백 세그먼트를 사용하게 하고 나머지 롤백 세그먼트들은 OLTP job이
사용하도록 한다. 이렇게 하면 OPTIMAL을 지정하지 않아도 모든 롤백
세그먼트가 불필요하게 확장되는 일을 막을 수 있다.
별첨: 용어 및 기본 개념 설명--------------------------------------------------------
(1) SCN(System Change Number)
오라클은 특정한 시점의 데이타베이스 상태를 SCN으로 관리한다. 트랜잭션이
commit되면, SCN은 최근의 SCN 보다 크고 유일한 값이 할당되며, 이 값은 그
트랜잭션이 변경시킨 블럭에 반영되고, 그 데이타화일의 가장 최근의 SCN은
데이타화일의 헤더(header)에 기록된다.
(2) statement-level read consistent
하나의 query는 그 query가 시작되어 데이타를 읽기 시작하면, 모든 데이타를
읽어 query가 끝날 때까지 일관된 상태를 유지한다. 즉 query가 진행되는 동안
다른 트랜잭션이 읽고자하는 데이타를 변경하더라도 그 query는 변경 이전의
데이타 값을 읽게 된다.
데이타들이 query가 시작될 때와 같은 시점인지는 SCN을 통해 관리된다. 즉
SCN이 10인 상태에서 query가 시작되었다면 query가 진행되는 동안 항상 SCN이
10이하 상태의 데이타만을 읽게 되며, 이것은 롤백 세그먼트(rollback segment)
를 이용하여 read consistent snapshot을 구성함으로써 가능하다.
트랜잭션이 변경작업을 수행할 때 마다, 오라클은 변경 작업이 이루어지기
전의 before image(snapshot)을 롤백 세그먼트에 저장해둔다. 한 트랜잭션이
commit되기 전에 변경된 데이타를 다른 트랜잭션이 읽거나 수정하고자 한다면,
롤백 세그먼트의 정보를 이용하여 read consistent snapshot을 구성한 후 이
데이타값을 이용하여 operation을 수행한다.
또한 (2)에서 설명한 statement-level read consistent를 이루기 위해서도
query가 진행되는 동안 읽고자 하는 블럭의 SCN이 증가하면, 롤백 세그먼트의
정보를 이용하여 원하는 SCN상태의 read consistent snapshot을 구성한 후
데이타를 읽게 된다.
롤백 세그먼트는 하나의 롤백 세그먼트를 여러개의 트랜잭션이 함께 사용하며,
하나의 extent도 여러개의 트랜잭션이 동시에 사용가능하다. 단 각 블럭은
하나의 트랜잭션에 할당된다. 트랜잭션들이 사용 중인 extent에 정보를 저장
하고 다음 extent가 필요하면, 해당 롤백 세그먼트에 이미 할당되어 있는 다음
extent가 active한 undo 정보를 가지고 있는지를 검사한다. active한 undo
정보를 담고 있지 않은 다음 extent가 current extent가 되며, 트랜잭션들은
이 extent에 undo image를 저장한다. 할당된 맨 마지막 extent를 확인하게
되면, 다시 첫번째 extent부터 extent로 돌아와 다시 사용하는 것을 wrap
around라고, 모두 commit된 트랜잭션의 정보만 담고 있는 extent는 overwrite
된다.
이렇게 롤백 세그먼트의 undo image를 담고 있는 블럭 뿐 아니라 롤백 세그먼트
헤더 내의 트랜잭션 테이블의 엔트리도 wrap around/overwrite될 수 있다.
트랜잭션 테이블은 고정된 수의 엔트리를 가지고 있으며, 트랜잭션이 이미
COMMITTED된 엔트리는 비어있는 것으로 인식하여 다음 트랜잭션이 사용 가능하게
된다.