Database/Oracle2011. 11. 2. 00:04


First of all, make sure the database is started. If it is not, you'll get this message (In 10g release 2).

C:>sc query OracleServiceXE

SERVICE_NAME: OracleServiceXE
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 1  STOPPED
                                (NOT_STOPPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 1077       (0x435)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

C:>sqlplus myuser@xe

SQL*Plus: Release 10.2.0.1.0

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Enter password:
ERROR:
ORA-12514: TNS:listener does not currently know of service requested in connect
descriptor
If the database is running, probably the database hasn't registered yet with the listener.
This occurs when the database or listener just starts up.

Normally this problem should be solved by waiting a minute or so.

If you are using dynamic registration (using the local_listener database parameter), you can try to register the database service with the listener using the following command (from Oracle 9i onwards):
show parameter local listener
-- if the above is empty
alter system set local_listener='(address=(protocol=tcp)(host=localhost)(port=1521))';
alter system register;
If this does not work or you're using static registration, make sure the SERVICE_NAME entry used in the connection string (TNSNAMES.ORA, NAMES, OID, ...) matches a valid service know by the listener.
eg.
C:>tnsping ora920

TNS Ping Utility for 32-bit Windows: Version 9.2.0.7.0 - Production

Copyright (c) 1997 Oracle Corporation.  All rights reserved.

Used parameter files:
c:\oracle\ora920\network\admin\sqlnet.ora

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = DEV01)(PORT =
 2491))) (CONNECT_DATA = (SERVICE_NAME = UNKNOWN) (SERVER = DEDICATED)))
OK (20 msec)
As one can see, this is the connection information stored in a tnsnames.ora file:
ORA920.EU.DBMOTIVE.COM =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = DEV01)(PORT = 2491))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = UNKNOWN)
      (SERVER = DEDICATED)
    )
  )
However, the SERVICE_NAME UNKNOWN is not known by the listener at the database server side.
In order to test the known services by a listener, we can issue following command at the database server side:
C:>lsnrctl services

LSNRCTL for 32-bit Windows: Version 10.1.0.2.0 - Production

Copyright (c) 1991, 2004, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=DEV01)(PORT=1521)))
Services Summary...
Service "ORA10G.eu.dbmotive.com" has 1 instance(s).
  Instance "ORA10G", status UNKNOWN, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0
         LOCAL SERVER
Service "ORA920.eu.dbmotive.com" has 2 instance(s).
  Instance "ORA920", status UNKNOWN, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:0 refused:0
         LOCAL SERVER
  Instance "ORA920", status READY, has 1 handler(s) for this service...
    Handler(s):
      "DEDICATED" established:2 refused:0 state:ready
         LOCAL SERVER
The command completed successfully
Know services are ORA10G and ORA920.

Changing the SERVICE_NAME in our tnsnames.ora to a known service by the listener (ORA920.EU.DBMOTIVE.COM) solved the problem.

 

원본 :  http://www.dbmotive.com/ora-12514-tnslistener-does-not-currently-know-of-service-requested-in-connect-descriptor/
 

Posted by 아로나
Database/Oracle2011. 8. 21. 18:11

FUNCTION-BASED INDEX ( ORACLE 8I NEW FEATURE )
==============================================

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

1. 개요

Function-based index는, 함수(function)이나 수식(expression)으로 계산
된 결과에 대해 인덱스를 생성하여 사용할 수 있는 기능을 제공한다.
질의 수행 시 해당 함수나 수식을 처리하여 결과를 가져 오는 것이 아니라,
인덱스 형태로 존재하는 미리 계산되어 있는 결과를 가지고 처리하므로
성능 향상을 기할 수 있다.

2. 제약사항

1) aggregate function 에 대한 function-based index 생성 불가.
(예 : sum(...) )

2) LOB, REF, nested table 컬럼에 대한 function-based index 생성 불가.

3. 주요 특징

1) cost-based optimizer에 의해 사용됨.
2) B*Tree / bitmap index로 생성 가능.
3) 산술식 (arithmetic expression), PLSQL function, SQL built-in
function 등에 적용 가능.

4) 함수나 수식으로 처리된 결과에 대한 range scan 가능
5) NLS SORT 지원
6) SELECT/DELETE를 할 때마다 함수나 수식의 결과를 계산하는 것이 아니라
INSERT/UPDATE 시 계산된 값을 인덱스에 저장.
7) 질의 속도 향상
8) object column이나 REF column에 대해서는 해당 object에 정의된
method에 대해 function-based index 생성 가능.

4. 생성 방법

CREATE [UNIQUE | BITMAP ] INDEX <index_name>
ON <tablename> (<index-expression-list>)

<index-expression-list> -> { <column_name> | <column_expression> }

예) CREATE INDEX EMP_NAME_INDEX ON EMP (UPPER(ENAME));
CREATE INDEX EMP_SAL_INDEX ON EMP( SAL + COMM, empno);

* Function-based index를 생성하기 위해서는 QUERY REWRITE 권한이
부여 되어 있어야만 한다.

예) GRANT QUERY REWRITE TO SCOTT;

5. Function-Based Index 사용을 위한 사전 작업

1) Function-based index는 cost based optimizer에서만 사용 가능하므로,
테이블에 대해 미리 analyze 해 주는 것이 바람직하다.
그리고 init 파일에서 OPTIMIZER_MODE 를 FIRST_ROWS 나 ALL_ROWS 등으
로 지정하거나 HINT 등을 사용하여 cost based optimizer가 사용되도록
한다.
2) init 파일에서 COMPATIBLE 파라미터 값을 8.1 이상으로 설정되어 있어야
한다.
( 예 : COMPATIBLE = 8.1.6 )
3) session/instance level 에서 QUERY_REWRITE_ENABLED 값이 TRUE 지정
되어 있어야 한다.
( 예 : ALTER SESSION SET QUERY_REWRITE_ENABLED = TRUE; )

6. 예제

1) init 파라미터에서 다음과 같이 지정

compatible = 8.1.6 (반드시 8.1이상이어야 한다)
query_rewrite_enabled = true
query_rewrite_integrity = trusted

2) SCOTT 유저에서 function_based_index 생성

create index idx_emp_lower_ename
on emp
( lower(ename) ) ;

3) EMP table analyze

analyze table emp compute statistics ;

4) PLAN_TABLE 생성

@ ?/rdbms/admin/utlxplan.sql

5) Cost based optimizer 선택

alter session set optimizer_mode = FIRST_ROWS ;

6) Query 실행
explain plan set statement_id=''qry1'' FOR
select empno, ename
from emp
where lower(ename) = ''ford'' ;

7) PLAN 분석

SELECT LPAD('' '',2*level-2)||operation||'' ''||options||'' ''||object_name query_plan
FROM plan_table
WHERE statement_id=''qry1''
CONNECT BY prior id = parent_id
START WITH id = 0 order by id ;

-> 결과

QUERY_PLAN
------------------------------------------------
SELECT STATEMENT
TABLE ACCESS BY INDEX ROWID EMP
INDEX RANGE SCAN IDX_EMP_LOWER_ENAME

7. 결론

Function-based index는 적절하게 사용될 경우 성능상의 많은 이점을 가져
온다. Oracle8i Designing and Tuning for Performance에서도 가능한 한
Function-based index를 사용하는 것을 권장하고 있으며, LOWER(), UPPER()
등의 함수를 사용하여 불가피하게 FULL TABLE SCAN을 하는 경우에 대해서도
효과적으로 처리해 줄 수 있는 방안이라 할 수 있다.

출처 : 파란블로그 mystery님 블로그 http://blog.paran.com/testhan/228857

Posted by 아로나
Database/Oracle2011. 6. 25. 18:12

3.4 테스트를 통한 Undo Retention 및 Automatic Undo Retention 동작 방식 분석

Undo Retention 개요

언두 리텐션이란 지정된 수치(오라클 9i까지는 UNDO_RETENTION 파라미터의 설정 값) 동안은 트랜잭션이 종료된 후에라도,
트랜잭션과 관련되었던 언두 세그먼트를 재사용하지 못하도록 하는 기능이다.

하지만, 오라클 9i까지는 언두 테이블스페이스의 공간 부족 현상이 발생할 경우 지정된 수치에 도달하기 전에도 언두 세그먼트의
재사용이 가능하였다. 언두 리텐션 기능은 언두 세그먼트의 인그텐트 단위로 관리되며, 각 인스텐트 당 Commit Time 을 관리하여
언두 리텐션 기간을 계산하게 된다. 언두 리텐션과 관련된 내용은 언두 세그먼트 헤더 블록의 리텐션 테이블에서 관리된다.
커밋 전과 커밋 후의 리텐션 테이블의 변화 사항을 테스트를 통해 확인해보자.

Session_A>create table undo_layer_t2 ( c1 number ,c2 varchar2(10), c3 char(20)) ;
Table created.

Session_A>insert into undo_layer_t2 values ( 1, 'A','a');
1 row created.

Session_A>select sid from v$mystat where rownum = 1 ;

       SID
----------
       148

 

SYS_Session>select xidusn, xidslot, xidsqn
  2  from v$transaction
  3  where addr=(select taddr from v$session where sid = 148 ) ;

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         2         34        973

SYS_Session>alter system dump undo header '_SYSSMU2$';
System altered.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU2$' ;

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2         25          8 EXPIRED
         1          2         33          8 EXPIRED
         2          2     204169       1024 ACTIVE

Session_A>commit ;
Commit complete.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU2$' ;

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2         25          8 EXPIRED
         1          2         33          8 EXPIRED
         2          2     204169       1024 EXPIRED

SYS_Session>alter system dump undo header '_SYSSMU2$';
System altered.


-- Commit 전 
 Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1305867652
 Extent Number:1  Commit Time: 1305867652
 Extent Number:2  Commit Time: 1305867652

-- Commit 후
 Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1305867652
 Extent Number:1  Commit Time: 1305867652
 Extent Number:2  Commit Time: 1305867652

테스트 결과

( 결과 )

예상과 달리 DBA_UNDO_EXTNETS 뷰의 STATUS 칼럼 값은 EXPIRED 로 변경되고,
언두 리텐션 테이블의 Commit Time 수치에 아무런 변화가 없다.

( 예상 )

커밋 수행 후에는 언두 리텐션 테이블의 Commit Time 이 커밋 시점으로 변경되고, DBA_UNDO_EXTENTS 뷰의
STATUS 칼럼 값은 UNEXPIRED 로 변경될 것 이라고 예상
어떠한 트랜잭션을 수행해야만 UNEXPIRED 상태로 변경되는 것일까 ?

Undo Retention 동작방식 테스트

Case 1: 언두 세그먼트의 익스텐트를 1개 이상 사용하는 경우

Session_A>create table undo_layer_t3 ( c1 number,  c2 varchar2(10), c3 char(20)) ;
Table created.

Session_A>begin
  2  for i in 1 .. 10000 loop
  3  insert into undo_layer_t3 values (i, 'c2','c3');
  4  end loop ;
  5  commit ;
  6  end ;
  7  /
PL/SQL procedure successfully completed.

Session_A>delete from undo_layer_t3 where rownum <= 5000 ;
5000 rows deleted.

Session_A>select sid from v$mystat where rownum = 1 ; 

       SID
----------
       148

SYS_Session>select xidusn, xidslot, xidsqn
  2  from v$transaction
  3  where addr=(select taddr from v$session where sid = 148 ) ;

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         8          9        925

SYS_Session>alter system dump undo header '_SYSSMU8$';
System altered.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU8$';
 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2        121          8 ACTIVE
         1          2        385          8 ACTIVE
         2          2        393        128 ACTIVE

Session_A>commit ;
Commit complete.

 
SYS_Session>alter system dump undo header '_SYSSMU8$';
System altered.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU8$';

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2        121          8 UNEXPIRED
         1          2        385          8 UNEXPIRED
         2          2        393        128 UNEXPIRED

 
-- 컷밋 전
Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1306119643
 Extent Number:1  Commit Time: 1305869453
 Extent Number:2  Commit Time: 1306119643

 
-- 컷밋 후
 Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1306123682
 Extent Number:1  Commit Time: 1306123682
 Extent Number:2  Commit Time: 1306123682

커밋 수행 후에는 언두 리텐션 테이블의 Commit Time 이 커밋 시점으로 변경되고,
DBA_UNDO_EXTENTS 뷰의 STATUS 칼럼 값은 UNEXPIRED 로 변경된 것을 확인 할 수 있다.

Case 2: 언두 세그먼트의 익스텐트 중에 UNEXPIRED 상태가 존재하는 경우

Session_A>delete from undo_layer_t3 where rownum = 1 ;
1 row deleted.

Session_A>select sid from v$mystat where rownum = 1 ; 

       SID
----------
       148

SYS_Session>select xidusn, xidslot, xidsqn
  2  from v$transaction
  3  where addr=(select taddr from v$session where sid = 148 ) ;

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         4         27        944

SYS_Session>alter system dump undo header '_SYSSMU4$';
System altered.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU4$';

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2         57          8 EXPIRED
         1          2         81          8 EXPIRED
         2          2       1929        128 ACTIVE
         3          2       2185        128 UNEXPIRED  ( 책내용 ) 

Session_A>commit ;
Commit complete.

SYS_Session>alter system dump undo header '_SYSSMU4$';
System altered.

SYS_Session>select extent_id, file_id, block_id, blocks, status 
  2  from dba_undo_extents
  3  where segment_name ='_SYSSMU4$';

 EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS STATUS
---------- ---------- ---------- ---------- ---------------
         0          2         57          8 EXPIRED
         1          2         81          8 EXPIRED
         2          2       1929        128 UNEXPIRED
         3          2       2185        128 UNEXPIRED ( 책내용 ) 

  
-- 컷밋 전
Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1305880256
 Extent Number:1  Commit Time: 1305885617
 Extent Number:2  Commit Time: 1305885617
 Extent Number:3  Commit Time: 1305885617  ( 책내용 ) 
 
-- 컷밋 후
 Retention Table
  -----------------------------------------------------------
 Extent Number:0  Commit Time: 1305880256
 Extent Number:1  Commit Time: 1305885617
 Extent Number:2  Commit Time: 1305885617
 Extent Number:3  Commit Time: 1305885617  ( 책내용 )

커밋 수행 후에 DBA_UNDO_EXTENTS 뷰의 STATUS 칼럼 값은 UNEXPIRED 로 변경되었으나,
레텐션 테이블의 Commit Time 은 변경되지 않는다.

언두 세그먼트 익스텐트의 상태를 관리하는 원칙
● 일정 크기 이상의 언두 레코드를 발생시키는 트랜잭션의 경우에만
DBA_UNDO_EXTENTS 뷰의 STATUS 칼럼과 리텐션 테이블의 내용이 변경된다.
● 일정 크기 이하의 언두 레코드를 발생시키는 트랜잭션은
DBA_UNDO_EXTENTS 뷰의 STATUS 칼럼과 테이블의 내용을 변경시키지 않는다.
● 일정 크기 이하의 언두 레코드를 발생시키는 트랜잭션이 UNEXPIRED 상태의 익스텐트를
소유한 언두 세그먼트를 사용할 경우에는,
DBA_UNDO_EXTENTS 뷰의 STATUS 컬럼만 변경하고, 리텐션 테이블의 내용은 변경하지 않는다.

일정 크기 이하의 언두 레코드를 발생시키는 트랜잭션의 동작방식은 언두 세그먼트의 공간을 효율적으로 관리하고자
하는 목적에는 부합, 하지만, 커밋 수행 후에 언두 세그먼트의 인스텐트를 UNEXPIRED 로 변경하지 않고 EXPIRED로
변경함에 따라 ORA-0155의 발생가능성이 있는 것은 아닐까 ?
아마도, 오라클에서는 이러한 경우에도, 몇 가지 기법을 더 적용하여 효율적으로 ORA-1555의 발생을 최적화시킬 것으로
생각되지만, 테스트를 통해 이 부분을 파악하는 것은 무리이므로.. 여기까지만..

Automatic Undo Retention 개요

자동 언두 리텐션(automatic undo retention) 기능은 오라클 10g부터 제공하는 기능으로써,
다이나믹하게 언두 리텐션의 수치를 조절한다.

자동 언두 리텐션 기능을 제공함으로써 부적절하게 설정된 UNDO_RETENTION 파라미터로 인한 ORA-01555
발생을 최소화할 수 있다. 자동 언두 리텐션 기능의 동작 방식은 오라클 10gR1 과 오라클 10gR2간에도 차이가 나며,
undo guarantee 사용 여부와 언두 데이터 파일의 autoextend 사용 여부에 따라 다르게 동작한다.

언두 테이블스페이스를 undo guarantee 모드로 사용할 경우, 언두 리텐션을 보장한다.
즉, 언두 테이블스페이스의 공간 부족 현상이 발생할 경우에도, UNEXPIRED 된 언두 익스텐트를 재사용하는 것을
방지함으로써, 언두 리텐션을 보장하는 것이다.

오라클 9i까지는 언두 테이블스페이스가 부족한 경우, UNEXPIRED 된 언두 익스텐스를 재사용함에 따라 언두 리텐션을
보장하지 못하였다. 언두 테이블스페이스의 undo guarantee 사용 여부는 언두 테이블스페이스 생성 시점 또는 생성
후에 변경이 가능하다.

SYS_Session>select tablespace_name, retention
  2  from dba_tablespaces
  3  where tablespace_name ='UNDOTBS1'; 

TABLESPACE_NAME                RETENTION
------------------------------ ---------------------------------
UNDOTBS1                       NOGUARANTEE

SYS_Session>alter tablespace undotbs1 retention guarantee ;
Tablespace altered.

SYS_Session>select tablespace_name, retention
  2  from dba_tablespaces
  3  where tablespace_name ='UNDOTBS1'; 

TABLESPACE_NAME                RETENTION
------------------------------ ---------------------------------
UNDOTBS1                       GUARANTEE

SYS_Session>alter tablespace undotbs1 retention noguarantee ;
Tablespace altered.

SYS_Session>select tablespace_name, retention
  2  from dba_tablespaces
  3  where tablespace_name ='UNDOTBS1'; 
TABLESPACE_NAME                RETENTION
------------------------------ ---------------------------------
UNDOTBS1                       NOGUARANTEE

자동 언두 리텐션 기능으로 인해 재설정된 언두 리텐션 수치는 V$UNDOSTAT 뷰의 TUNED_UNDORETENTION 칼럼을 통해 확인할 수 있다.
V$UNDOSTAT 뷰는 오라클 9iR2부터 제공되며 언두 사용 통계정보를 10분 단위로 샘플링하며, 언두 사용에 대한 유용한 통계정보를 제공

Automatic Undo Retention 동작 방식 테스트

h3. 테스트를 위한 파라미터 기본 설정
- _UNDO_AUTOTUNE = TURE ( 기본설정 값 )
- UNDO_RETENTION = 0
h3. 테스트 초기화 
Session_A>create  table undo_layer_t4 as select * from dba_objects nologging ;
Table created.

테스트1 - Retention Guarantee = No Autoextend = No

Session_A>alter tablespace undotbs1 retention noguarantee ;
Tablespace altered.


Session_A>alter database datafile '/u01/app/oracle/db/TLO/undotbs01.dbf' autoextend off ;
Database altered.

 

SYS_Session>startup
ORACLE instance started.

Total System Global Area 1073741824 bytes
Fixed Size                  1223540 bytes
Variable Size             880805004 bytes
Database Buffers          188743680 bytes
Redo Buffers                2969600 bytes
Database mounted.
Database opened.
SYS_Session>@chk_undostat.sql

BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
14:27:34                 14:28:28                          0                                                600

SYS_Session>@chk_undostat.sql

BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
14:27:34                 14:28:49                          0                                             345600


SQL> !more t111.sql           
set linesize 140
col sql_text for a15

select count(*) from undo_layer_t444, undo_layer_t444, undo_layer_t444 ;

select to_char(a.begin_time,'HH24:MI:SS') begin,
       to_char(a.end_time,'HH24:MI:SS') end,
       a.maxquerylen max_q_len,
       a.maxqueryid max_q_id,
       a.tuned_undoretention tuned_ur,
       substr(b.sql_text,1,30) sql_text
from v$undostat a, v$sql b
where a.maxqueryid = b.sql_id(+)
and rownum <= 4
;
 

SQL> @t111.sql
  COUNT(*)
----------
1.5161E+10


BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ------------------------------
17:07:34                 17:15:55                        846 cw0wvgj78aq76                               345600    select count(*) from undo_laye
16:57:34                 17:07:34                        246 cw0wvgj78aq76                               345600    select count(*) from undo_laye
16:47:34                 16:57:34                       1327 cw0wvgj78aq76                               345600    select count(*) from undo_laye
16:37:34                 16:47:34                        727 cw0wvgj78aq76                               345600    select count(*) from undo_laye

테스트 1 - 결과 분석

오라클이 기동된 직후에 TUNED_UNDORETENTION 은 600초로 설정되며,
몇 분 후 345,600(96H) 초로 자동 설정된다. 345,600초(는 언두 테이블스페이스의 크기와 관련이 있는 것으로 보인다.
즉, 언두 테이블스페이스는 확장이 불가능하므로, 현재 크기에 해당되는 최대값으로 설정하는 것이며,
쿼리 수행 시에 MAXQUERYLEN, MAXQUERYID 컬럼에 값을 등록 한다.

테스트 2 - Retention Guarntee = No Autoextend = YES

SQL> alter tablespace undotbs1 retention noguarantee ;
Tablespace altered.

SQL> alter database datafile '/u01/app/oracle/db/TLO/undotbs01.dbf' autoextend on next 10m ;
Database altered.

SYS_Session>shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS_Session>startup
ORACLE instance started.

Total System Global Area 1073741824 bytes
Fixed Size                  1223540 bytes
Variable Size             880805004 bytes
Database Buffers          188743680 bytes
Redo Buffers                2969600 bytes
Database mounted.
Database opened.


SQL> @chk_undostat.sql

BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
17:42:21                 17:43:22                          0                                                600

....

SQL> @chk_undostat.sql

BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
17:42:21                 17:43:25                          0                                                600

SQL> @t111.sql

  COUNT(*)
----------
1.5161E+10


BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ------------------------------
17:52:21                 18:01:28                        948 0t9kys4buvt4y                                 1728 select ENQUEUE_ENABLED, DEQUEU
17:42:21                 17:52:21                        348 0t9kys4buvt4y                                 1188 select ENQUEUE_ENABLED, DEQUEU

테스트 2 - 결과 분석

오라클이 가동된 직후에 TUNED_UNDORETENTION 은 600초로 설정되며,
쿼리가 수행되지 않을 경우 TUNED_UNDORETNTION 은 600초로 유지한다.
장시간 쿼리가 수행될 경우에, MAXQUERYLEN 컬럼의 값은 300 초 단위로 갱신된다.
TUNED_UNDORETENTION 값은 장시간의 쿼리를 감지한 직후에는 대략 MAXQUERYLEN + UNDORETENTION + 60 초로 증가하며,
그 이후로는 매 60초 단위로 증가하게 된다.
즉, 언두 테이블스페이스가 확장 가능하므로, 쿼리의 수행시간에 근거하여 언두 리텐션을 튜닝한다.

테스트 3 - Retention Gurantee = YES Autoextentd = No

SQL> alter tablespace undotbs1 retention guarantee ;
Tablespace altered.
SQL> alter database datafile '/u01/app/oracle/db/TLO/undotbs01.dbf' autoextend off ;
Database altered.

SYS_Session>shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SYS_Session>startup
ORACLE instance started.

Total System Global Area 1073741824 bytes
Fixed Size                  1223540 bytes
Variable Size             880805004 bytes
Database Buffers          188743680 bytes
Redo Buffers                2969600 bytes
Database mounted.
Database opened.

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
18:25:06                 18:25:58                          0                                                600

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
18:25:06                 18:26:16                          0                                             345600

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
18:25:06                 18:25:58                          0                                                600

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
18:25:06                 18:26:16                          0                                             345600

테스트 결과3 의 내용은 테스트 1의 결과와 동일하다.

다만, undo guarantee 모드를 사용함에 따라, 언두 테이블스페이스의 공간 부족이 발생할 시점의 동작 방식이 차이가 있다.
undo guarantee 모드는 언두 리텐션을 보장하는 것에 우선순위가 있으므로, 언두 세그먼트를 확장하려고 시도하는
트랜잭션은 ORA-30036 이 발생한다.
undo gurantee 모드를 사용하지 않는다면, 이러한 경우, 다른 언두 세그먼트의 익스텐트를 스틸링(stealing)한다.

테스트 4 - Retention Gurantee = YES Autoextend = YES

SQL> alter tablespace undotbs1 retention guarantee ;
Tablespace altered.

SQL> alter database datafile '/u01/app/oracle/db/TLO/undotbs01.dbf' autoextend on next 10m ;
Database altered.

SQL> shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 1073741824 bytes
Fixed Size                  1223540 bytes
Variable Size             880805004 bytes
Database Buffers          188743680 bytes
Redo Buffers                2969600 bytes
Database mounted.
Database opened.
SQL> 

 

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
08:40:40                 08:41:51                          0                                                600

SQL> @chk_undostat.sql
BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ---------------
08:40:40                 08:43:03                          0                                                600
 

SQL> @t111.sql

  COUNT(*)
----------
1.5161E+10

BEGIN                    END                       MAX_Q_LEN MAX_Q_ID                                  TUNED_UR SQL_TEXT
------------------------ ------------------------ ---------- --------------------------------------- ---------- ------------------------------
08:50:40                 08:59:36                        795 cw0wvgj78aq76                                 1518 select count(*) from undo_laye
08:40:40                 08:50:40                        195 cw0wvgj78aq76                                 1035 select count(*) from undo_laye

테스트 4 - 결과분석

테스트 결과의 내용은 테스트 2의 결과와 동일하다.
다만, undo guarantee 모드를 사용함에 따라, 언두 테이블스페이스의 공간 부족이 발생할 시점의
동작 방식이 차이가 있다는 것이다.

문서정보

Posted by 아로나
Database/Oracle2011. 6. 25. 17:52
Posted by 아로나
Database/Oracle2011. 6. 25. 17:33
안녕하세요...
rollback segment와 관련해서 질문이 한가지 있습니다.
현재 java source를 보면 대략 1000만건을 Select 하고서 조회한 데이타를 테이블에
insert를 합니다.
source를 잠시 보면

rs = stmt.executeQuery(" Select empno, ename, job from emp ");

pstmt = conn.prepareStatement(
                " Insert Into Temp (empno,  " +
                "                   ename,   " +
                "                   Job)   " +
                " Values (?,?,?)");

while(rs.next()) {
                pstmt.clearParameters();
                pstmt.setString(1, rs.getString("empno"));
                pstmt.setString(2, rs.getString("ename"));
                pstmt.setString(3, rs.getString("Job"));

                try {
                    pstmt.executeUpdate();
                } catch (SQLException se) {
                    System.out.println( "Message(execute) : " + se.getMessage());
                    System.out.println( "sql state(execute) : " + se.getSQLState());
                    System.out.println( "error code(execute) : " + se.getErrorCode());
                } catch (Exception e) {
                    System.out.println( "Insert Exception(execute) Error");
                }
            }

source는 대략 이러한 방식으로 되어있습니다.
그런데 이렇게 하다보니까 700만건도 못되어서 ORA-0155: snapshot too old" error가
발생하였습니다.

그래서 대량의 데이타를 처리할수 있는 rollback segment를 만들고 나서 다음과 같이
하였습니다.

위의 source에서 select를 하기 이전에 다음을 넣었습니다.

try {
                pstmt2 = conn.prepareStatement(
                    " set transaction use rollback segment TEMPRBS " );

                try {
                    pstmt2.executeUpdate();
                } catch (SQLException se) {
                    System.out.println( "Message(RBS) : " + se.getMessage());
                    System.out.println( "sql state(RBS) : " + se.getSQLState());
                    System.out.println( "error code(RBS) : " + se.getErrorCode());
                } catch (Exception e) {
                    System.out.println( "Insert Exception(RBS) Error");
                }
            } catch (SQLException se) {
                System.out.println( "Message(insert : RBS) : " + se.getMessage());
                System.out.println( "sql state(insert : RBS) : " + se.getSQLState());
                System.out.println( "error code(insert : RBS) : " + se.getErrorCode());
            } catch (Exception e) {
                System.out.println( "Insert Exception(RBS) Error");
            }

그런데 이렇게 하여도 ROLLBACK SEGMENT ERROR가 발생을 하는데 잘못된 부분이 어디 있는지
알고 싶습니다.

감사합니다...

제목 : Re: 2가지 방법...
글쓴이: 손님(guest) 2003/12/09 13:03:17 조회수:375 줄수:16  
이게 가능할지는 잘 모르겠네요...

일단 첫번째 방법으로 속도가 조금 떨어질 가능성은 있습니다만...
select를 할 경우에, order by를 사용하지 못할 특별한 이유가 없으면...
order by를 사용해 보는 게 좋을 듯하구요...
이걸로도 해결이 안되면...

두번째 방법은...
이건 오라클 9i일 경우(8i의 경우도 같은지 잘 모르겠네요...)에는...
UNDO_RETENTION을 조금 크게 잡아보심이...
쿼리가 실행되는 데 걸리는 시간 이상의 충분한 시간을 잡아보면 해결이 될지도...

뭐, 확실한 건 아닙니다만...
나쁘지 않다면 한번정도 테스트해 보심이 좋을 듯하네요...

그럼...

제목 : Re: rollback Segment 관리
글쓴이: 손님(claystudio) 2003/12/10 19:18:38 조회수:413 줄수:11  

insert 하다가 읽어 왔던 데이터가 바뀐것 같습니다.

"snapshot too old"오류를 자세히 찾아보시면 원인을 더 정확히 알 수 있을듯합니다...

ps. 데이터 양으로 봐서는 웹상에서 돌아가는 프로그램은 아니고 배치성 프로그램인듯 한데
    쿼리를 바꿔보심이...
    ==> Insert into Temp(empno, ename, job)
             Select empno, ename, job from emp;



제목 : Re: OTN에서 퍼왔습니다.
글쓴이: 손님(guest) 2003/12/12 15:43:22 조회수:905 줄수:147  
No. 20241

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 원인
분석 및 조치 사항" 을 참조한다.

============================================================================

write할 rbs가 모자라서 그런 게 아니랍니다.
제 생각엔 루프안의 SQL에 대한 명시적인 트랜잭션 컨트롤 구문이 없는 것으로 보아
(commit or rollback) autocommit으로 그냥 사용중이신 것같은데요
autocommit을 꺼주시고 트랜잭션에 대한 매뉴얼한 컨트롤을 해주셔야할 듯합니다.
그냥... 명시적으로 commit과 rollback을 해주셔야할 듯하단 말입니다. ^^

직접적인 관련은 없는 듯하지만, rbs가 적다면 적절하게 늘려주시는 게 좋을 듯합니다.


- 출처 : http://www.ezslookingaround.com/blog/tech/?no=950 -
Posted by 아로나
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 아로나