Database/Oracle2011. 6. 25. 17:13
Tip] ORA-01555 에러에 대한 원인 및 조치방법


query시 발생하는 ORA-1555의 발생 원인과 조치 사항에 대해서 자세히 살펴
본다.


Explanation
-----------

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


ORA-1555가 발생하는 주요 원인과, 이 오류 발생을 최소화할 수 있는 방법은
다음과 같다.

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 문은
수행시키지 않도록 한다.


2. fetch across commit

프로그램내에서 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되는 주기를
늦추기 위해서 롤백 세그먼트의 갯수를 증가시키고 그 크기도 크게하면
도움이 된다.


3. delayed block clean out

오라클은 기본적으로 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 |
+---------------------+ +----+------+-------------------+

(2) xid1 트랜잭션이 update문을 이용하여 500번지 데이타 블럭의 2번째
데이타를 변경하였다.
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에 관한 정보를 저장하였다.

Data Block 700 Rollback Segment Header 5
+-------+-------------------+ +----+-------+------------------+
| 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 |
+---------------------------+ +----+-------+------------------+

(5) 다른 트랜잭션이 데이타 블럭 500번지를 방문하였다.
새로운 트랜잭션인 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를
피하는 데 도움이 될 수 있다.


4. OPTIMAL 크기가 아주 작을 때

롤백 세그먼트는 트랜잭션의 사용에 의해 한번 크기가 늘어나면 기본적으로
그 롤백 세그먼트를 지우고 다시 만들기까지는 크기가 줄어들지 않는다.
그러나 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을 구성함으로써 가능하다.

(3) read consistent snapshot (read consistent view)
트랜잭션이 변경작업을 수행할 때 마다, 오라클은 변경 작업이 이루어지기
전의 before image(snapshot)을 롤백 세그먼트에 저장해둔다. 한 트랜잭션이
commit되기 전에 변경된 데이타를 다른 트랜잭션이 읽거나 수정하고자 한다면,
롤백 세그먼트의 정보를 이용하여 read consistent snapshot을 구성한 후 이
데이타값을 이용하여 operation을 수행한다.
또한 (2)에서 설명한 statement-level read consistent를 이루기 위해서도
query가 진행되는 동안 읽고자 하는 블럭의 SCN이 증가하면, 롤백 세그먼트의
정보를 이용하여 원하는 SCN상태의 read consistent snapshot을 구성한 후
데이타를 읽게 된다.


(4) rollback segment의 wrap around/overwrite
롤백 세그먼트는 하나의 롤백 세그먼트를 여러개의 트랜잭션이 함께 사용하며,
하나의 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된 엔트리는 비어있는 것으로 인식하여 다음 트랜잭션이 사용 가능하게
된다.



Reference Documents
-------------------
ORA-01555 "Snapshot too old" - Detailed Explanation

-출처 : http://kr.blog.yahoo.com/javanux/1257 -


'Database > Oracle' 카테고리의 다른 글

ORA-30036 조치 관련 링크  (0) 2011.06.25
ORA-01555  (0) 2011.06.25
오라클 에러 조치법 : ORA-01547 , ORA-01552 , ORA-01555 ....  (0) 2011.06.25
Segment?  (0) 2011.06.25
롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Posted by 아로나
Database/Oracle2011. 6. 25. 17:01

======================================================================
ORA-01547 조치방법 :ORACLE 블럭을 할당받지 못할 경우
======================================================================


 ORA-1547 에러 발생의 원인으로는,  TABLESPACE가 에러에 명시된 만큼의  연속된 ORACLE BLOCK 수의  FREE
 SPACE를 갖고있지 못해서 새로운 EXTENT를 할당하지 못 하기 때문이다.

 ORA-1547 에러는 일반적으로 다음과 같은 과정에서 발생할 수 있다.

 1) 데이타 INSERT나 UPDATE시 DATA SEGMENT가 차지하게될 연속적인 ORACLE 블럭을 할당 받지 못할  경우에
 발생한다.

 2) 인덱스를 생성할 경우에 발생한다. -  ROLLBACK SEGMENT가 사용할 RBS 또는 USER  TABLESPACE의 영역이
 부족 하여 발생할 수 있다. -  인덱스 생성시 SORT 영역으로 사용되는 TEMPORARY  TABLESPACE내의 SPACE의
 부족 으로 발생할 수 있다.

 3) SQL*FORMS30, SQL*REPORTWRITER등의 프로그램을  데이타베이스에 [SAVE]시 관련 테이  블들을 포함하고
 있는 SYSTEM 또는 TOOLS TABLESPACE등의 영역이  부족한 경우에 발생 된다. 이러한 경우  EXTENT에 관련된
 DATA DICTIONARY VIEW인 USER_TABLES, USER_EXTENTS, USER_SEGMENTS와 DBA_FREE_SPACE등을 조회해서  관련
 내용을 확인한다. 예를 들어, 데이타 INSERT시 ORA-1547  : Failed to allocate extent of size  'num' in
 tablespace 'TOOLS' 에러가 발생될 경우를 고려해 보자.

1) [USER_TABLES]에서 INSERT에 관련된 테이블의 NEXT_EXTENT 크기를 확인한다.
SQL> SELECT  initial_extent, next_extent, pct_increase, min_extents, max_extents
       FROM  user_tables
      WHERE  table_name = 'EMP';

 INITIAL_EXTENT   NEXT_EXTENT   PCT_INCREASE   MIN_EXTENTS   MAX_EXTENTS
----------------  -----------  -------------- ------------- -------------
     10240          190464           50            1            121

(A)
(A) : 다음에 할당되는 EXTENT의 크기를 나타내며 BYTES 단위이다.
2) [DBA_FREE_SPACE]에서 현재 TABLESPACE에 존재하는 FREE SPACE 중 가장 큰 연속된 영역을 확인한다.

SQL> SELECT  MAX(bytes) MAX_CONTIGUOUS_SPACE
       FROM  dba_free_space
      WHERE  tablespace_name = 'TOOLS';

     MAX_CONTIGUOUS_BYTES
    ----------------------
          19730432
(B)

(B) : 현재 TABLESPACE에 남아있는 FREE SPACE 중 가장 큰 연속된 영역으로 BYTES 단위로 나타난다.

3) 위에서 살펴본바와 같이 2)-(B)의 MAX(BYTES) 크기가 1)-(A)의 NEXT_EXTENT 크기보다 작기 때문에
   ORA-1547이 발생하게 되는 것이며 이를 해결하는 방법으로는 다음의 몇 가지가 있다.

① 최소 1)-(A)의 NEXT_EXTENT크기 이상의 데이타 화일을 'TOOLS' TABLESPACE에 추가한다.
  ALTER TABLESPACE tools ADD DATAFILE *file_name* SIZE integerM ;

② TABLE의 STORAGE  PARAMETER에서 INITIAL EXTENT,  NEXT EXTENT의 크기를 조정하여 TABLE을 재구축할 수
 있다.  즉, TABLE의 STORAGE PARAMETER 중에서 NEXT를 현재 TABLESPACE에 남아있는 FREE SPACE 중 가장 큰
 연속된 영역( DBA_FREE_SPACE의 MAX(BYTES))보다 작게 변경할 수 있다.
  SQL> ALTER TABLE emp STORAGE ( NEXT 100K );

③ 다음으로는 관련 TABLESPACE내의 OBJECT들을 EXPORT후 TABLESPACE를 재생성하고 IMPORT하여 DISK
 FRAGMENTATION을 없애서 결과적으로 해당 TABLESPACE에 활용공간을 확보할 수 있다.

 
======================================================================
ORA-01552 조치방법 : SYSTEM ROLLBACK SEGMENT를 사용할 경우
======================================================================

 

<PRE>
본 내용은 ORACLE 7.3 이전의 VERSION에 해당하는 내용입니다.

 SYSTEM ROLLBACK  SEGMENT 는  SYSTEM TABLESPACE에서  발생하는 ROLLBACK  정보들만을 가질수  있으므로,
 SYSTEM TABLESPACE 이외의 TABLESPACE에 대해서  발생하는 OPERATION (TABLE의 생성 등)을  위하여 SYSTEM
 ROLLBACK SEGMENT를 사용할 경우에는 ORA-1552가 발생한다.

 ORA-1552 발생 원인을 해소하기 위해 우선, SYSTEM TABLESPACE에 하나 이상의 ROLLBACK SEGMENT를  임시로
 추가한 다음, NON-SYSTEM TABLESPACE에 ROLLBACK SEGMENT를 생성하고, 다른 데이타베이스 오브젝트(TABLE등
 )를 생성하는 작업을 진행하여 이들 NON-SYSTEM TABLESPACE의 ROLLBACK SEGMENT를 이용하도록 유도한다.

 CREATE ROLLBACK SEGMENT 문에서 PRIVATE/PUBLIC으로 ROLLBACK SEGMENT를 생성한 후, ORACLE 데이타베이스를
 SHUTDOWN, STARTUP 한다. PRIVATE으로 생성된 ROLLBACK SEGMENT는 INITSID.ORA 화일의 'ROLLBACK_SEGMENTS'
 PARAMETER에 등록한다.

1) SQLDBA> CONNECT INTERNAL;
2) SQLDBA> CREATE ROLLBACK SEGMENT r0 TABLESPACE SYSTEM ;
   임시로 사용할 ROLLBACK SEGMENT를 SYSTEM TABLESPACE에 생성
3) SQLDBA> ALTER ROLLBACK SEGMENT r0 ONLINE ;
   생성한 ROLLBACK SEGMENT를 ONLINE시킨다.
4) SQLDBA> CREATE ROLLBACK SEGMENT r1 TABLESPACE rbs ;
   계속해서 사용할 ROLLBACK SEGMENT를 NON-SYSTEM TABLESPACE에 생성한다.
5) $ORACLE_HOME/dbs/initSID.ora 화일의 'ROLLBACK_SEGMENTS' PARAMETER에 생성된 ROLLBACK SEGMENT 이름을
   등록한다.
6) ORALCE 데이타베이스를 SHUTDOWN 및 STARTUP을 수행한다.

 SYSTEM  TABLESPACE에  임시로  추가해 주었던  ROLLBACK  SEGMENT는  NON-SYSTEM TABLESPACE의  ROLLBACK
 SEGMENT를 생성하기 위해  필요한 것이었으므로 작업이  끝난 후 DROP한다. 
 SQLDBA> ALTER  ROLLBACK SEGMENT  r0  OFFLINE  ; 
 SQLDBA> DROP  ROLLBACK  SEGMENT  r0  ; 

 
======================================================================
ORA-01555 : Rollback segment의 정보가 다른 transaction에 의해 overwrite된 경우
======================================================================


 변경을 일으킨 트랜잭션 슬롯이 재사용되었을 때, 롤백 세그먼트의 이전 이미지가 다른 트랜잭션에 의해 겹
 쳐 쓰여졌을때, 01555, 00000, 'snapshot too old: rollback segment number %s with name '%s' too small'
 // *Cause: rollback records needed by a reader for consistent read are
 // overwritten by other writers
 // *Action: Use larger rollback segments
 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되지 않은 상태이다.    
 블럭의 헤더에는 트랜잭션이 아직 cimmit되지 않았다는 정보와 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를 구성할 수 있다. ORA-1555가 발생하는 주요 원인과, 이
 오류 발생을 최소화할 수 있는 방법은 다음과 같다.

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문은 수행시키지 않도록 한다.

2. fetch across commit 
 프로그램내에서  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되는 주기를 늦추기  위해서 롤백 세그먼트의
 갯수를 증가시키고 그 크기도 크게하면 도움이 된다. 

3. delayed block clean out 
 오라클은 기본적으로  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번째 트랜잭션 엔트리는 다른 트랜잭션에 의해 재사용
  되어 질수있다. 
 (2) xid1 트랜잭션이 update문을 이용하여 500번지 데이타 블럭의 2번째 데이타를 변경 하였다.   500번지
 데이타 블럭의 헤더에는 xid1 트랜잭션의 정보가 저장되고, 롤백 세그먼트 5번의 트랜잭션 슬롯 3 (5,3)을
 가리키게 된다. COMMITTED로 표시되었던 트랜잭션 슬롯 3번은 이제 ACTIVE 상태로 변경되었다. 

(3) xid1 트랜잭션이 commit을 수행하였다. 
 오라클은 롤백 세그먼트 헤더의 트랜잭션 테이블에서 xid1 트랜잭션의 정보를 찾아서 commit되었다고 기록
 하였다. 그러나 500번지 블럭의 헤더에는 commit  되었다는 정보를 기록하지 않는다. (fast commit) 
(4)  데이타베이스에 변경을 가하는 매우 많은 트랜잭션이 수행되었다. 
 매우 많은 트랜잭션이 수행되어 롤백 세그먼트 헤더내에 있는 트랜잭션 테이블의 엔트리가 대부분 재사용되
 었다. 트랜잭션  xid50이 롤백  세그먼트 5번의  3번째 슬롯이  COMMITTED로 표시되어  있으므로, 비어있는
 엔트리로 인식하여 xid50에 관한 정보를 저장하였다. 

(5) 다른 트랜잭션이 데이타 블럭 500번지를 방문하였다. 
 새로운  트랜잭션인 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를 피하는데 도움이 될 수 있다.

 4.  OPTIMAL  크기가 아주  작을  때 롤백  세그먼트는  트랜잭션의 사용에  의해  한번 크기가  늘어나면
 기본적으로 그 롤백세그먼트를 지우고 다시 만들기 까지는 크기가 줄어들 지 않는다. 그러나 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을 구성함으로써 가능하다. 

(3) read consistent snapshot (read consistent view) 
 트랜잭션이 변경작업을 수행할 때 마다, 오라클은 변경 작업이 이루어지기 전의 before image(snapshot)을
 롤백 세그먼트에 저장해둔다.  한 트랜잭션이 commit되기  전에 변경된 데이타를  다른 트랜잭션이 읽거나
 수정하고자 한다면, 롤백 세그먼트의 정보를 이용하여 read consistent snapshot을 구성한 후 이 데이타값
 을 이용하여 operation을 수행한다. 또한 (2)에서 설명한 statement-level read consistent를 이루기 위해
 서도 query가 진행되는동안 읽고자 하는 블럭의 SCN이 증가하면, 롤백 세그먼트의 정보를 이용하여 원하는
 SCN상태의 read consistent snapshot을 구성한 후 데이타를 읽게 된다. 

(4)  rollback segment의 wrap around/overwrite 
 롤백 세그먼트는 하나의 롤백 세그먼트를 여러개의 트랜잭션이 함께 사용하며, 하나의 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된 엔트리는 비어있는 것으로 인식하여 다음 트랜잭션이 사용 가능하게 된다.


 01560 : tablespace에 충분한 공간이 없을때
 01560, 00000, 'global hash table size mismatch for %s (%s != %s)'
 // *Cause: The specified 'gc_' INIT.ORA parameter was incompatible
 // with that of another instance which already has the database mounted.
 // *Action: Fix the 'gc_' parameter and restart.



- 출처 : 오라클클럽 http://www.oracleclub.com/article/12244 -

'Database > Oracle' 카테고리의 다른 글

ORA-01555  (0) 2011.06.25
[Tip] ORA-01555 에러에 대한 원인 및 조치방법  (0) 2011.06.25
Segment?  (0) 2011.06.25
롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
Posted by 아로나
Database/Oracle2011. 6. 25. 16:43

Overview of Segments

Segment란?

  익스텐트 상위의 논리적인 데이터베이스 저장 수준을 세그먼트라고 하며, 하나의 세그먼트는 특정 논리적 구조에 할당된 익스텐트들로 구성 됩니다.

  Oracle은 각 table에 대해 하나 이상의 extent를 Table의 Data Segment에 할당하며 각 Index를 위해 하나 이상의 extent를 Index Segment에 할당 합니다.

 

Data Segments

  데이터 세그먼트는 클러스터 되지 않은 테이블, 클러스터 테이블, 파티션 테이블로 구분되어져 저장 됩니다.

  각각의 클러스터 되지 않은 테이블(SnapShot과SnapShot Log 포함)은 하나의 데이타 세그먼트를 갖습니다. 모든 테이블의 데이타는 자기 데이타 세그먼트의 익스텐트 내에 저장 됩니다.

  클러스터 테이블은 하나의 데이타 세그먼트를 갖습니다. 클러스터 내의 모든 테이블 데이타는 클러스터의 데이타 세그먼트 내에 저장됩니다.

 

Index Segments

  모든 일반 index와 partitioned index는 각각 자신의 모든 데이타를 저장하고 있는 하나의 인덱스 세그먼트를 갖습니다.

  세그먼트의 할당은 인덱스 생성시(CREATE INDEX)나, 인덱스 테이블 스페이스를 생성할때 STORAGE절을 통해 지정할 수 있습니다.

 

Temporary Segments

  임시 세그먼트는 SQL문의 완전한 실행을 위해 임시 작업 영역이 필요할 때 생성 됩니다. 명령문 실행이 끝나면 임시 세그먼트의 확장 영역은 이후 사용을 위해 시스템으로 복귀합니다.

  아래와 같은 명령은 Temporary Segments를 필요로 합니다.
      - CREATE INDEX - SELECT ... ORDER BY
      - SELECT DISTINCT ... - SELECT ... GROUP BY
      - SELECT . . . UNION - SELECT ... INTERSECT
      - SELECT ... MINUS

  CREATE TEMPORARY TABLESPACE로 임시 테이블스페이스를 생성해서 CREATE USER나, ALTER USER 명령시 지정 할 수 있습니다.

  TEMPORARY TABLESPACE를 지정를 지정하지 않으면 유저는 SYSTEM 테이블스페이스를 사용 합니다.

  Oracle9i는 부터는 DEFAULT TEMPORARY TABLESPACE를 생성해서 TEMPORARY TABLESPACE를 지정받지 않은 사용자가 SYSTEM 테이블스페이스를 사용하는 것을 방지 할 수 있습니다.

 

Undo Management

Rollback 세그먼트와 Undo 세그먼트의 관계

  Rollback과 Undo는 기본적으로는 동의어 입니다.

  Oracle 9i 이전엔 Rollback Segement라는 용어를 사용했는데, Oracle 9i 이후버전 부터는 Undo Segment라는 용어를 사용합니다.

  Rollback(Oracle 9i 이전 버전) = Undo(Oracle 9i 이후 버전)

  Undo 세그먼트는 관리 방식에 있어서 9i 이후 버전에서 자동 관리 모드와 수동 관리 모드를 선택 할 수 있는 기능이 추가 되었고, 트랜잭션 처리를 위한 알고리즘이 개선되었습니다.

  Undo 세그먼트는 생성, 할당 및 튜닝을 오라클 서버가 관리하므로 DBA는 더 이상 몇개의 Rollback 세그먼트를 생성 할 것인지, 크기는 어떻게 할 것인지, 트랜잭션에 따라 어떻게 할당할 것인지를 결정하지 않아도 됩니다.

Undo 세그먼트 사용 목적

  Undo Segments는 Transaction Rollback, 일기 일관성 유지(Read Consistency), Transaction Recovery를 위해 존재 합니다.

  Transaction Rollback
      - Oracle 서버에서 Undo Segment에 저장된 값을 이용해서 원래의 값으로 복원하는 기능을 말합니다.
      - Transaction Rollback이 실행되는 경우는 사용자가 Rollback command를 실행하거나, Transaction이 비정상 종료되어 PMON이 자동 Rollback 처리하는 경우 입니다.

  읽기 일관성
      - Transaction이 진행되는 동안 Database의 다른 사용자는 이 Consistent Read에 의해 Commit되지 않은 변경 사항을 볼 수 없는 기능 입니다.

  Transaction Recovery
      - Transaction이 진행되는 동안 Instance가 실패한 경우 Database가 다시 열릴 때 Commit되지 않은 사항은 Rollback되어야 하는데 이때 Undo Segment정보가 사용 됩니다.

문서에 대하여

  • - 작성자 : 김정식 (oramaster _at_ naver.com)
  • - 작성일 : 2006-04-11
  • - 강좌 URL : http://www.oracleclub.com/lecture/1898
  • - 이 문서를 다른 블로그나 홈페이지에 게재하실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
  • - 오라클클럽의 모든 강좌는 크리에이티브 커먼즈의 저작자표시-비영리-동일조건변경허락(BY-NC-SA) 라이선스에 따라 자유롭게 사용할 수 있습니다
Posted by 아로나
Database/Oracle2011. 6. 25. 15:59

롤백 세그먼트란 ?

롤백 세그먼트란?

  - 롤백 세그먼트는 트랜잭션 진행시 그 이전 이미지를 기록하기 위해 사용되는 CIRCULAR구조의 세그먼트입니다.

  - 롤백 세그먼트는 프로세스가 데이터베이스의 데이터에 변경 할 때 이전 값을 저장하는데 사용됩니다.

  - 롤백 세그먼트는 수정되기 전의 파일, 블록 ID같은 블럭 정보 및 데이터를 저장합니다.

  - 롤백 세그먼트의 헤더는 현재 세그먼트를 사용하고 있는 트랜잭션에 대한 정보를 저장하는 있는 트랜잭션 테이블을 포함하고 있습니다.

  - 트랜잭션은 단 하나의 롤백 세그먼트에 롤백(실행 취소) 기록 전부를 기록합니다.

  - 많은 트랜잭션이 동시에 하나의 롤백 세그먼트에 쓰기를 할 수 있습니다.

롤백 세그먼트의 목적

  롤백 세그먼트는 트랜잭션 롤백, 트랜잭션 복구, 읽기 일관성을 제공하기 위해서 사용 됩니다.

트랜잭션 롤백

  트랜잭션이 테이블내의 행을 변경할 때 Before image를 롤백세그먼트에 저장함으로써 트랜잭션이 롤백되는 경우에 다시 데이터값을 행으로 옮겨서 원래의 값으로 복원하는데 사용합니다.

트랜잭션 복구

  트랜잭션이 수행되고 있을 때 인스턴스가 비정상적으로 종료하면 오라클 서버는 데이터베이스를 다시 오픈할 때 커밋되지 않은 변경 사항을 롤백해야 합니다.

  트랜잭션 복구라 불리는 이와 같은 롤백은 롤백 세그먼트에 가해진 변경 사항 역시 리두로그 파일에 의해서 보호되어야만 가능합니다.

읽기 일관성

  트랜잭션이 수행되고 있을 때 데이터베이스의 다른 사용자는 이 트랜잭션이 커밋하지 않은 변경된 데이터를 볼 수가 없습니다.

  또한 SELECT문이 실행된 시점에서는 그 이전에 커밋된 데이터 까지의 정보만 볼 수 있습니다. SELECT문 수행도중 다른 사용자에 의해 변경된 데이터는 볼 수 없습니다.

트랜잭션과 롤백세그먼트

  1) 트랜잭션이 시작하려면 반드시 롤백 세그먼트가 있어야 합니다.

  2) 오라클은 트랜잭션을 여러 롤백세그먼트 중에서 가장 적은 수의 트랜잭션이 지정된 롤백세그먼트를 설정하여 할당해 줍니다

  3) 만약 사용자가 특정 트랜잭션에 대해서 롤백 세그먼트를 지정하고 싶으면 아래의 명령어를 사용하면 됩니다. (큰 트랜잭션을 따로 수행할 경우 많이 사용 합니다. )

 
  SET TRANSACTION USE ROLLBACK SEGMENT 롤백세그먼트이름
    

  4) 트랜잭션은 현재의 롤백세그먼트 내의 Extent가 꽉차면 다른 익스텐트로 옮겨 가는데(이 단계를 WRAP라고 부름) 만약 다음 익스텐트가 활성화 중이면 새로운 익스텐트를 생성 합니다. 롤백세그먼트는 원형구조로 되어 있기 때문에 다음이나 그 다음 익스텐트로 건너 뛸수 없습니다.

  5) 롤백 세그먼트의 한 익스텐트에 하나 이상의 트랜잭션이 쓰기를 할 수 있습니다. 하지만, 롤백 세그먼트의 각 블록은 오직 하나의 트랜잭션에서 나온 정보만을 기록할 수 있습니다.

문서에 대하여

  • - 작성자 : 김정식 (oramaster _at_ naver.com)
  • - 작성일 : 2003-03-17
  • - 강좌 URL : http://www.oracleclub.com/lecture/1726
  • - 이 문서를 다른 블로그나 홈페이지에 게재하실 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
  • - 오라클클럽의 모든 강좌는 크리에이티브 커먼즈의 저작자표시-비영리-동일조건변경허락(BY-NC-SA) 라이선스에 따라 자유롭게 사용할 수 있습니다.

'Database > Oracle' 카테고리의 다른 글

오라클 에러 조치법 : ORA-01547 , ORA-01552 , ORA-01555 ....  (0) 2011.06.25
Segment?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
아카이빙(archiving)이란?  (0) 2011.06.22
Oracle에서 데이터 문자열을 구분자로 나누기  (0) 2011.06.14
Posted by 아로나
Database/Oracle2011. 6. 22. 12:46

'Database > Oracle' 카테고리의 다른 글

Segment?  (0) 2011.06.25
롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
아카이빙(archiving)이란?  (0) 2011.06.22
Oracle에서 데이터 문자열을 구분자로 나누기  (0) 2011.06.14
Oracle Cursor2  (0) 2011.05.26
Posted by 아로나
Database/Oracle2011. 6. 22. 09:37

최근 들어 아카이빙이라는 용어가 매우 빈번하게 사용되고 있으나 아카이빙이 갖는 용어는 상황에 따라 매우 큰 차이를 두고 다르게 사용되고 있기 때문에 간단하게 정리해 봅니다.

아카이빙이란 주로 데이터를 원래 있던 위치에서 다른 곳으로 이동하여 보관하는 의미로 백업과 함께 데이터 보전을 위한 하나의 방법으로 사용되기도 하나 백업이 제공하는 것 이상의 의미를 갖고 있습니다. 현재, IT 업계에서는 다양한 기술의 아카이빙 기술을 제공하는데 이는 크게 세가지로 도식화해서 정리해 볼 수 있습니다.

1. 백업후 삭제 - 이 것은 가장 원시적인 방법으로 백업 소프트웨어를 이용해서 테이프나 이차 스토리지로 백업을 한 후 즉시 또는 일정 기간이 지나 일차 스토리지에서 원래의 데이터를 삭제하는 방법입니다. 대부분은 수작업이나 스크립트를 이용해서 이루어지며 데이터를 다시 찾고자 할 경우 백업 소프트웨어로 부터 정보를 찾아 일차스토리지로 다시 리스토어과정을 거쳐야 합니다. 대신에 새로운 소프트웨어를 구매해야 하는 비용은 필요 없는 것이 이점이라면 이점입니다.

2. HSM(Heirachycal Storage Manager) - HSM은 이미 메인프레임 환경에서 오래 전부터 개발되어 사용해온 기술로 오픈시스템 환경에 적용하기 시작한 것은 10년 전 정도로 추산됩니다. HSM은 이전하고자 하는 데이터의 포인터 부분(유닉스 시스템에서는 "inode"에 해당되며, "Stub" 이라고도 합니다.)은 원래의 위치에 두고 그 이하부분(데이터 영역)은 이차스토리지나 테이프로 이전하는 방법을 제공하는 기술입니다. HSM은 일반적으로 애플리케이션 영역보다는 파일시스템 영역에서 동작하며 입출력을 중간에서 가로채어 이 기능을 수행하게 됩니다. 따라서, 일부 시스템에는 HSM을 위한 별도의 파일시스템으로 전환하는 방법을 사용하며 HSM 지원을 위한 표준인 DMAPI(Data Management API)를 지원하는 시스템에서는 파일시스템 전화없이 적용하기도 합니다. 이런 특성으로 HSM은 지원가능한 시스템이 매우 제한되어 있습니다. HSM은 현재 특화된 시장을 중심으로 매우 활발한 움직임을 보이고 있는데, 대표적인 경우가 Email Archiving 이고, 이외에도 Healthcare(병원의 PACS), Security Surveillance(디지탈 비디오 보안시스템), Documents(문서관리 시스템) 등이 있습니다.

3. 아카이빙 툴 - 이 것은 좁은 의미의 아카이빙을 의미하는 것으로 넓은 의미의 아카이빙과 많이 혼동되어 사용되기도 합니다. 아카이빙 툴은 애플리케이션 서버와 데이터 시스템 사이에 별도의 아카이빙 툴을 두고 이 툴을 이용해서 데이터를 이전하고 관리하는 방법입니다. 따라서 애프리케이션은 아카이빙 툴에 데이터를 요청하고 아카이빙 툴은 데이터의 위치 정보를 갖고 해당 데이터를 읽어 들여 애플리케이션에 제공하는 원리입니다. 이 아카이빙 툴은 주로 방송시스템의 대용량 영상데이터를 관리하는 시스템으로 사용되고 있습니다.

대략적으로 아카이빙의 개념을 정리해 보았는데, 특히 HSM은 최근에 ILM(Information Lifecycle Management)의 활성화와 함께 급부상하고 있는 IT 기술 중의 하나이기도 합니다.

- 출처 ; http://www.mini7.co.kr/board/view.php?id=study&page=1&sn1=on&divpage=1&sn=on&ss=off&sc=off&keyword=cho78&select_arrange=headnum&desc=asc&no=50&PHPSESSID=cba6d75b664bfe2dd51db84af8dd703d -

'Database > Oracle' 카테고리의 다른 글

롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
Oracle에서 데이터 문자열을 구분자로 나누기  (0) 2011.06.14
Oracle Cursor2  (0) 2011.05.26
Oracle Cursor  (0) 2011.05.26
Posted by 아로나
Database/Oracle2011. 6. 14. 00:12

ex)
SELECT SUBSTR(TEST,1,INSTR(TEST,'.',1,1)-1) AS FIRST,
SUBSTR(TEST,INSTR(TEST,'.',1,1)+1,INSTR(TEST,'.',1,2)-INSTR(TEST,'.',1,1)-1) AS SECOND,
SUBSTR(TEST,INSTR(TEST,'.',1,2)+1) AS THIRD
FROM (SELECT '1.22.333' TEST
FROM DUAL);


설명)
SUBSTR('Hello',1,5) => 'Hello'
SUBSTR('Hello',2,4) => 'ell'
SUBSTR('Hello',3) => 'llo' (3번째 문자열부터 끝까지 출력)

INSTR('HelloWorld','W') => 6 ('HelloWorld'에서 'W'의 위치를 숫자로 리턴)

INSTR('HelloWorld','l'1,1) => 3 (첫번째 위치에서 문자 'l'을 첫번째로 만나는 위치을 숫자로 리턴)
INSTR('HelloWorld','l'1,3) => 9 (첫번째 위치에서 문자 'l'을 세번째로 만나는 위치을 숫자로 리턴)
INSTR('HelloWorld','l'5,1) => 9 (다섯번째 위치에서 문자 'l'을 첫번째로 만나는 위치을 숫자로 리턴)

그러므로 위의 예제에서
INSTR('1.22.333','.',1,1) => 2
INSTR('1.22.333','.',1,2) => 5
가 된다.

이를 참고하여 이해하기 바란다.

간단한 위의 예제 쿼리의 결과는
아래와 같다.

 FIRST   SECOND    THIRD
    1           22            333



'Database > Oracle' 카테고리의 다른 글

롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
아카이빙(archiving)이란?  (0) 2011.06.22
Oracle Cursor2  (0) 2011.05.26
Oracle Cursor  (0) 2011.05.26
Posted by 아로나
Database/Oracle2011. 5. 26. 14:15

 커서란 SQL*Plus에서 사용자가 실행한 SQL문의 단위를 의미합니다. 오라클에서 수행한 모든 쿼리문은 커서 단위로 처리합니다. 커서는 암시적 커서와 명시적 커서로 나뉩니다. PL/SQL의 SQL문처럼 하나의 결과를 리턴하는 경우 커서 없이도 SQL문의 실행된 결과가 암시적으로 커서에 저장되므로 이를 암시적 커서라고 합니다.

- SQL문을 수행한 후에 결과로 얻어지는 행이 여러 개일 경우에는 암시적인 커서에 정보를 저장할 수 없기에 에러가 발생합니다. 이런 경우에 반드시 명시적인 커서를 사용해야 합니다.

# 커서의 상태
사용자 삽입 이미지







- 명시적인 커서는 PL/SQL의 레코드(RECORD)와 PL/SQL 의 테이블(TABLE)을 결합한 것으로서 프로그램 언어의 구조체 배열과 유사합니다. 커서를 사용하기 위해서는 다음과 같은 4가지 단계를 거쳐야 합니다.
1. 커서를 선언한다. (CURSOR cur_name)
2. 커서를 오픈한다. (OPEN cur_name)
3. 커서의 조회한 결과를 인출해 저장한다. (FETCH cur_name)
4. 커서를 닫는다. (CLOSE cur_name)

1. 커서를 선언한다.
CURSOR cursor_name
IS statement;

- 커서를 선언할 때에는 실행할 SELECT 문을 IS 다음에 서브쿼리 형태로 기술합니다.
CURSOR C1 IS
SELECT EMPNO, ENAME, SAL
FROM EMP
WHERE DEPTNO = 20;
- C1은 커서의 이름이고 이 커서는 사원 테이블에서 부서번호가 20인 행을 조회합니다.

2. 커서를 오픈한다.
- 커서를 오픈 하게 되면 커서를 선언할 때 작성한 SELECT 문을 실행하게 됩니다.
OPEN C1;

3. 커서에 조회한 결과를 인출해 저장한다.
- FETCH 명령어를 수행하면 오픈한 SELECT문에 의해 검색된 한 개의 정보를 읽어오게 됩니다.
읽어온 정보는 변수에 저장합니다.
FETCH C1 INTO VEMPNO, VENAME, VSAL;

- SELECT 문의 결과로 얻어지는 행이 여러개일 경우에는  LOOP-END LOOP와 같은 반복문을 이용해서 마지막 행을 읽을 때가지 반복해서 수행해야 합니다.
LOOP
    FETCH C1 INTO VEMPNO, VENAME, VSAL;
    EXIT WHEN C1%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(TO_CHAR(VEMPNO) || VNAME || TO_CHAR(VSAL));
END LOOP;

- 만족하는 행을 발견하지 못할 때 즉, 마지막 행을 읽었을 때 반복문을 벗어나도록 하기 위해서는 'EXIT WHEN C1%NOTFOUND'와 같이 기술 합니다.

4. 커서를 닫는다.
- CLOSE 명령문으로 더 이상 사용되지 않을 커서를 닫습니다.
CLOSE C1;
- 커서를 닫으면 (CLOSE) 커서에 선언되 SELECT문의 선언이 해제됩니다.

- 20번 부서에 근무하는 사원의 정보를 출력해 봅니다.
SQL> SET SERVEROUTPUT ON -- DBMS_OUTPUT 출력 가능하도록 설정.
SQL> DECLARE
-- 커서를 실행한 결과를 저장할 지역 변수 선언
  2     vempno   NUMBER(4);
  3     vename   VARCHAR2(20);
  4     vsal    NUMBER(7, 2);
  5 
-- 번호가 20인 사원의 정보를 조회하는 SELECT문을 커서로 선언.
  6     CURSOR C1
  7     IS
  8     SELECT EMPNO, ENAME, SAL
  9     FROM EM01
 10     WHERE DEPTNO = 20;
 11 
 12  BEGIN
 13     OPEN C1; -- 커서를 오픈하면 커서를 선언할 때 작성한 SELECT 문이 실행됩.
 14     dbms_output.put_line('번호   이름   급여');
 15 
 16     LOOP
 17             FETCH C1 INTO VEMPNO, VENAME, VSAL; -- SELECT 문을 실행한 결과를 한행씩 가져와서 변수에 저장
 18             EXIT WHEN C1%NOTFOUND; -- 마지막 행까지 읽어서 행이 발견되지 않으면 반복문을 벗어남.
 19             DBMS_OUTPUT.PUT_LINE(TO_CHAR(VEMPNO) || '       ' || VENAME || '         ' || TO_CHAR(VSAL)); -- 검색된 결과를 사용자 화면에 출력.
        END LOOP ;
-- LOOP 구문 : 커서 실행 결과 구해진 행이 여러 개이면 반복문을 사용하여 처리.
 20   21        CLOSE C1;
 22  END ;
 23  /
번호   이름   급여
7566    JONES    2975
7902    FORD     3000
7368    SMITH    800
7788    SCOTT    3000
7876    TEST3    1100

PL/SQL procedure successfully completed.

SQL>

# OPEN-FETCH-CLOSE가 없이 커서 처리
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
  2  -- 커서를 수행한 결과 값을 저장할 레코드 형태의 변수.
  3     vemp     emp%ROWTYPE;
  4 
  5  -- 커서 선언
  6     CURSOR C1
  7     IS
  8     SELECT EMPNO, ENAME, SAL
  9     FROM EM01
 10     WHERE DEPTNO = 20;
 11 
 12  BEGIN
 13     dbms_output.put_line('번호   이름   급여');
 14 
 15  /* FOR 레코드명 IN 커서명 LOOP */
 16  -- OPEN-FETCH-CLOSE문을 하나의 FOR문으로 대체할 수 있음.
 17 
 18     FOR vemp IN C1 LOOP
 19             EXIT WHEN C1%NOTFOUND;
 20             DBMS_OUTPUT.PUT_LINE(TO_CHAR(vemp.empno) || '   ' || vemp.ename || '    ' || TO_CHAR(vemp.sal) || '------------->'||C1%ROWCOUNT);
 21     END LOOP;
 22  END ;
 23  /
번호   이름   급여
7566    JONES   2975------------->1
7902    FORD    3000------------->2
7368    SMITH   800------------->3
7788    SCOTT   3000------------->4
7876    TEST3   1100------------->5

PL/SQL procedure successfully completed.

# 커서를 활용한 실용 예제
SQL> DECLARE
  2     tot      NUMBER := 0;
  3     CURSOR emp_cursor
  4     IS
  5     SELECT ENAME, SAL
  6     FROM EM01;
  7  BEGIN
  8     dbms_output.put_line('이름                          급여');
  9     dbms_output.put_line('-------------------------');
 10 
 11     FOR cur_var IN emp_cursor LOOP
 12             tot := tot + cur_var.sal;
 13             dbms_output.put_line(cur_var.ename);
 14             dbms_output.put_line('_                ' || cur_var.sal);
 15     END LOOP;
 16     dbms_output.put_line('-------------------------');
 17     dbms_output.put_line('_                            ' || tot);
 18  END;
 19  /
이름                          급여
-------------------------
MARTIN
_                1250
JONES
_                2975
TURNER
_                1500
FORD
_                3000
SMITH
_                800
KING
_                5000
WARD
_                1250
BLAKE
_                2850
CLARK
_                2450
MILLER
_                1300
ALLEN
_                1600
SCOTT
_                3000
JAMES
_                1957
TEST
_                800
TEST3
_                1100
-------------------------
_                            30832

PL/SQL procedure successfully completed.

- 사원별 급여 현황을 그래프로 표현
SQL> DECLARE
  2     CURSOR emp_cursor
  3     IS
  4     SELECT ENAME, SAL
  5     FROM EMP
  6     ORDER BY SAL DESC;
  7 
  8     star    VARCHAR2(100);
  9     cnt     NUMBER := 0;
 10  BEGIN
 11     dbms_output.put_line('                       사원별 급여 현황');
 12     dbms_output.put_line('----------------------------------------');
 13 
 14     FOR cur_var IN emp_cursor LOOP
 15             star := NULL;
 16             cnt := round(cur_var.sal/100, 0);
 17 
 18             FOR i IN 1.. cnt LOOP
 19                     star := star || '*';
 20             END LOOP;
 21 
 22     dbms_output.put_line(cur_var.ename);
 23     dbms_output.put_line('_               ' || star || '    ' || ' (' || cur_var.sal || ')');
 24     END LOOP;
 25  END;
 26  /
사원별 급여 현황
----------------------------------------
KING
_               **************************************************       (5000)
FORD
_               ******************************   (3000)
SCOTT
_               ******************************   (3000)
JONES
_               ******************************   (2975)
BLAKE
_               *****************************    (2850)
CLARK
_               *************************        (2450)
JAMES
_               ********************     (1957)
ALLEN
_               ****************         (1600)
TURNER
_               ***************  (1500)
MILLER
_               *************    (1300)
MARTIN
_               *************    (1250)
WARD
_               *************    (1250)
ADAMS
_               ***********      (1100)
SMITH
_               ********         (800)
SMITH
_               ********         (800)

PL/SQL procedure successfully completed.

'Database > Oracle' 카테고리의 다른 글

롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
아카이빙(archiving)이란?  (0) 2011.06.22
Oracle에서 데이터 문자열을 구분자로 나누기  (0) 2011.06.14
Oracle Cursor  (0) 2011.05.26
Posted by 아로나
Database/Oracle2011. 5. 26. 14:13
1.  커서의  정의

커서란  SQL  Plus에서  사용자가  실행한  SQL문의  단위를  의미합니다.
오라클렝서  수행한  모든  쿼리문은  커서  단위로  처리합니다.

PL/SQL의  SQL문처럼  하나의  결과를  리턴하는  경우  커서  없이도  SQL문의  실행결과가 
암시적으로  커서에  저장되므로  이를  암시적  커서라고  합니다.

SQL문을  수행한  후에  결과로  얻어지는  행이  여러  개일  경우에는  암시적인  커서에  정보를 
저장할  수  없기에  에러가  발생합니다.  이럴  경우에는  반드시  명시적인  커서를  사용해야  합니다.

명시적인  커서는  PL/SQL의  레코드(RECORD)와  PL/SQL의  테이블(TABLE)을  결합한  것으로서
프로그램  언어의  구조체  배열과  유사합니다.



[커서의  사용]

1)  커서를  선언한다.
CURSOR  cur_name

2)  커서를  오픈한다.
OPEN  cur_name

3)  커서에  조회한  결과를  인출해  지정한다.
FECTCH  cur_name  ...

4)  커서를  닫는다
CLOSE  cur_name






2.  20번  부서에  근무하는  사원의  정보를  출력하는  예제


ed  cur01


SET  SERVEROUTPUT  ON
declare
   vempno   NUMBER(4);
   vename   VARCHAR2(20);
   vsal   NUMBER(7,  2);

   CURSOR   C1
   IS
   select  empno,  ename,  sal
   from  emp
   where  deptno=20;

begin
   OPEN  C1;

   dbms_output.put_line('empno   ename   sal');

   LOOP
      FETCH  C1  INTO  vempno,  vename,  vsal;
      EXIT  WHEN  C1%NOTFOUND;

      dbms_output.put_line(to_char(vempno)||'   '||vename||'   '||to_char(vsal));
   END  LOOP;


end;
/



저장하고  실행합니다.

@cur01
empno   ename   sal
7369   SMITH   800
...
...
...
...
...

PL/SQL  procedure  successfully  completed.





3.  OPEN-FETCH-CLOSE가  없이  커서  처리

ed  cur02


SET  SERVEROUTPUT  ON
declare
   vemp   emp%ROWTYPE;

   CURSOR   C1
   IS
   select  empno,  ename,  sal
   from  emp
   where  deptno=20;

begin
   dbms_output.put_line('empno   ename   sal');

   FOR   vemp   IN   C1   LOOP
      EXIT  WHEN  C1%NOTFOUND;

      dbms_output.put_line(to_char(vemp.empno)||'   '||vemp.ename||'   '||to_char(vemp.sal));
   END  LOOP;

end;
/


정장하고  실행합니다.

@cur02
empno   ename   sal
7369   SMITH   800
...
...
...
...
...

PL/SQL  procedure  successfully  completed.



4.  커서의  상태

%NOTFOUND   커서  영역의  자료가  모두  FETCH  됬는가를  알려줌
%FOUND      커서  영역에  FETCH가  되지  않은  자료가  있는가를  알려줌
%ISOPEN      커서가  OPEN된  상태인가를  알려줌
%ROWCOUNT   FETCH된  RECORD가  몇  개  있는지  알려줌

cur02  예제를  수정합니다.

ed  cur02

SET  SERVEROUTPUT  ON
declare
   vemp   emp%ROWTYPE;

   CURSOR   C1
   IS
   select  empno,  ename,  sal
   from  emp
   where  deptno=20;

begin
   dbms_output.put_line('empno   ename   sal   record  count');

   FOR   vemp   IN   C1   LOOP
      EXIT  WHEN  C1%NOTFOUND;

      dbms_output.put_line(to_char(vemp.empno)||'   '||vemp.ename||'   '||to_char(vemp.sal)||'   '||C1%ROWCOUNT);
   END  LOOP;

end;
/


저장하고  실행합니다.

@cur02

결과는  record  count  추가되었습니다.




5.  커서를  활용한  실용  예제
1)  급여  총합을  구하는  예제
ed  cur03

SET  SERVEROUTPUT  ON
declare
   tot   NUMBER  :=  0;

   CURSOR   emp_cursor
   IS
   select  ename,  sal
   from  emp;

begin
   dbms_output.put_line('name   sal');
   dbms_output.put_line('------------------------------------------');

   FOR  cur_var  IN  emp_cursor  LOOP
      tot  :=  tot  +  cur_var.sal;
      dbms_output.put_line(cur_var.ename);
      dbms_output.put_line('-   '||cur_var.sal);
   END  LOOP;
  
   dbms_output.put_line('------------------------------------------');
   dbms_output.put_line('-   '||tot);
end;
/


저장하고  실행합니다

@cur03




2)  사원별  급여  현황을  그래포로  표현
ed  cur04

SET  SERVEROUTPUT  ON
declare
   CURSOR   emp_cursor
   IS
   select  ename,  sal
   from  emp
   order  by  sal  desc;

   star   varchar2(100);
   cnt   number  :=  0;

begin
   dbms_output.put_line('   sal  of  emp');
   dbms_output.put_line('------------------------------------------');

   FOR  cur_var  IN  emp_cursor  LOOP
      star  :=  NULL;
      cnt  :=  round(cur_var.sal/100,  0);

      for  i  in  1..  cnt  loop
         star  :=  star||'*';
      end  loop;

   dbms_output.put_line(cur_var.ename);
   dbms_output.put_line('-   '||star||'('||cur_var.sal||')');
   END  LOOP;
end;
/


저장하고  실행합니다

@cur04

'Database > Oracle' 카테고리의 다른 글

롤백 세그먼트(rollback segment)란 ?  (0) 2011.06.25
Oracle Lock  (0) 2011.06.22
아카이빙(archiving)이란?  (0) 2011.06.22
Oracle에서 데이터 문자열을 구분자로 나누기  (0) 2011.06.14
Oracle Cursor2  (0) 2011.05.26
Posted by 아로나
Database/MySQL2011. 4. 22. 10:05
사용자 정의 변수
--------------------------------------------------------------------------------
MySQL에서는  두   가지  방법으로   사용자가  정의한  변수를   지원한다.  변수이름은
alphanumeric 문자와 '_', '$', '.'로 구성된다. 변수에 초기값이 지정되지 않으면, NULL이 디
폴트이며, integer, real, string 값을 저장할 수 있다. 변수이름은 버전 5.0부터는 대·소문자
구분이 없다.

방법1)
SET 문을 사용하여 변수를 설정
SET @variable={integer expression | real expression | string expression }
        [,@variable=...]
【예제】
mysql> set @t3=5;
mysql> select @t3;
+------+
| @t3  |
+------+
| 5    |
+------+
mysql>

방법2)
@variable:=expr 문을 사용하여 설정
【예제】
mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
      +----------------------+------+------+------+
      | @t1:=(@t2:=1)+@t3:=4  |  @t1  |  @t2  | @t3  |
      +----------------------+------+------+------+
      |                              5  |   5    |    1    |   4    |
      +----------------------+------+------+------+


'Database > MySQL' 카테고리의 다른 글

How to simulate FULL OUTER JOIN in MySQL  (0) 2011.04.22
MYSQL 날짜 데이터 타입  (0) 2011.04.21
Posted by 아로나