ORACLE/ADMIN2014. 11. 12. 14:16
반응형
Windows 
C:\> cd \oracle\ora92\network\log 
C:\oracle\ora92\network\log> lsnrctl set log_status off 
C:\oracle\ora92\network\log>
리스너로그파일 덮어쓰기로삭제
rename listener.log listener.old 
C:\oracle\ora92\network\log> lsnrctl set log_status on 



UNIX 
% cd /u01/app/oraclein/product/9.2.0/network/log 
% lsnrctl set log_status off 
% mv listener.log listener.old 
% cp /dev/null listener.log
% lsnrctl set log_status on



반응형
Posted by [PineTree]
ORACLE/ADMIN2014. 8. 15. 13:09
반응형
출처 :https://community.oracle.com/message/1701073#1701073

제품 : ORACLE SERVER

작성날짜 : 2004-11-30


SEGMENT SHRINK 관련 10G 신규 기능
===========================



PURPOSE
-------
Oracle10g에서는, 세그먼트를 shrink 시킬 옵션이 존재하며, 이 기능을 활용하면 DBA가가 공간을 좀더 효율적으로 활용할 수
있다 이 기능은, 또한 질의 처리 속도 개선에도 도움이 된다. 


Explanation
-----------
1. 준비 사항

Init.ora 파라미터인 'Compatible' 값이 10.0 이상이어야 함.
세그머트는, AUTO Segment Space Managed Tablespace에 존재해야 함.

2. 동작 방법

1) 테이블의 row movement 기능을 활성화 시킨다.
SQL> ALTER TABLE scott.emp ENABLE ROW MOVEMENT;

2) 테이블을 shrink 시키지만, HWM (High Water Mark)을 shrink 시키지 않는다.
SQL> ALTER TABLE scott.emp SHRINK SPACE COMPACT;

3) 테이블과 HWM을 shrink 시킨다.
SQL> ALTER TABLE scott.emp SHRINK SPACE;

4) 테이블 및 관련된 인덱스를 모두 shrink시킨다.
SQL> ALTER TABLE scott.emp SHRINK SPACE CASCADE;

5) MView 형태의 테이블을 shrink시킨다.
SQL> ALTER TABLE <table name> SHRINK SPACE;

6) 인덱스만 shrink 시킨다.
SQL> ALTER INDEX <index nam> SHRINK SPACE;


3. 적용 대상

1) Normal Table
2) Index
3) Lob
4) IOT
5) MView


4. Query/DML Concurrency

Segment shrink를 할 때의 online 처리는, DML-호환 락을 사용한다. 따라서 DML은
shrink를 처리 하는동안에도 사용할 수 있다. space-release/HWM 조정을 하는 단계에서는,
테이블에 대해 DML고 호환되지 않는 락을 사용한다 따라서, DML은 shink가 끝날 때 까지
잠시 중단되나.

shrink를 실행함으로써 발생하는 DML 처리 관련 에러는 없다.

쿼리는 세그먼트의 HWM에 대한 캐쉬를 사용한다. 오라클은, HWM이 언제나 커질 것으로 간주한다. 따라서
CR은 세그먼트 헤더 및 익스텐트 맵 블럭에 대해서는 필요하지 않다. 세그먼트 HWM이 작아지는 유일한
경우는, drop 또는 truncate 작업 뿐이다.

오라클은, drop/truncate DDL와 질의처리가 동시에 존재할 수있게 허용하는데, 이것은 질의 처리가
락을 필요로 하지 않기 때문이다. 만약 drop/truncate 작업이 끝난 후라면, 해당 공간은 다른 세그먼트에
의해 사용되며, 질의는 "8103 - object does not exist"라는 에러 메시지와 함께 실패하게 된다.

세그먼트를 shrink하는 동안, 세그먼트의 HWM가 변경된다면, 해당 세그먼트와 관련된 비트맵 블럭과 
세그먼트 헤더의 incarnation number가 변경된다. 후속 데이터 블럭 관련 작업은 새로 부여된
incarnation number를 사용한다.

만약 이 단계에서 실행되는 질의가 있었다면, "10632 - invalid rowid" 에러와 함께 실패하는데
다음과 같은 조건이 만족 되어야 한다.

1) 갱신된 비트맵 블럭을 읽는다 (새로운 inc#). 이 경우 failure는, 해당 공간이 재 사용되지 않았다면
발생하게 된다.

2) 공간이 동일한 객체 또는 다른 객체에 의해 재 활용 되었다.


5. Online Segment Shrink와 관련된 제약사항

ASSM의 세그먼트는 shrink 가능하다. 그러나, ASSM 테이블스페이스에 위치하는 객체
가운데 다음과 같은 객체에는 제약사항이 따른다 :

1) 클러스터에 속하는 테이블
2) long 컬럼을 포함한 테이블
3) on-commit materialized view와 연관된 테이블
4) rowid based materialized view와 연관된 테이블
5) Lob index


6. Shrink 수행시 의존 관계 관리와 제약사항 

세그먼트를 shrink 하는동안, 고려되는 유일한 의존 관계는, 테이블 - 인덱스간 관계이다.
인덱스는, shrink 후에도 unusable 상태로 남지 않는다.

세그먼트 shink를 과정에서 압축 (compaction)단계는 insert/delete 작업을 쌍으로 처리하여
이루어진다. DML trigger는 데이터를 이동하는 단계에서는 호출되지 않는다. 데이터의 내용이
변경되는 것이 아니므로, trigger가 호출 될 필요가 없다.

ROWID에 기반을 둔 trigger는, shrink를 하기 전 disable 시켜야 하는데 이것은 shink 하는동안
트리거가 호출 되지 않도록 하기 위해서이다.

on-commit materialized view와 연관된 세그먼트는 shrink 시킬 수 없다.
Primary key를 기반으로 한 materialized view는, shrink를 시킨 이후에 refresh 또는 rebuild
할 필요가 없다.

하지만, rowid에 기반을 둔 materialized view에 대해서는 refresh 또는 rebuild를 수행해 주어야
한다.


7. 가용성

세그먼트 shrink는, 온라인중에 수행될 수 있다. 따라서, 객체에 대한 가용성이 향상 되었다.
DML 작업은 세그먼트 shrink 중에도 수행 가능하나, parallel DML을 수행될 수 없다.

세그먼트를 shrink 시키는동안 데이터는 압축(compaction) 단계에서 이동이된다. 압축 단계가 진행되는
동안 개별 row 또는 데이터 블럭에 대한 lock이 사용된다.
이 상황은, lock을 이용해, update나 delete와 같은 concurrent DML이 수행되는 상황과 유사하다.
압축은, 작은 트랜잭션 다뉘로 수행되므로, 객체에 대한 가용성은 심각하게 영향을 받지 않는다.

하지만, 세그먼트를 shrink 시키는 특정 단계에서는 (HWM을 조정하는 단계), 세그먼트는, exclusive 모드로
lock이 걸린다.
이 단계는 매우 짧은 기간이며, 객체에 대한 가용성에 미치는 영향이 최소호 된다.


8. 보안

세그먼트 shrink를 수행하기 위해서는 객체에 대해서 ALTER 시키는 권한과 동등한 권한이 필요하다.


9. 상세 예제

SQL> set serveroutput on
SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
12 v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 1
FS3 Blocks = 1
FS4 Blocks = 3
Full Blocks = 0

PL/SQL procedure successfully completed.

SQL> alter table t_shrink shrink space compact;
alter table t_shrink shrink space compact
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled

SQL> ALTER TABLE t_shrink ENABLE ROW MOVEMENT;
Table altered.

SQL> ALTER TABLE t_shrink SHRINK SPACE COMPACT;
Table altered.

SQL> set serveroutput on
SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
12 v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 0
FS3 Blocks = 0
FS4 Blocks = 2
Full Blocks = 1

PL/SQL procedure successfully completed.

SQL> ALTER TABLE t_shrink SHRINK SPACE;
Table altered.

SQL> declare
2 v_unformatted_blocks number;
3 v_unformatted_bytes number;
4 v_fs1_blocks number;
5 v_fs1_bytes number;
6 v_fs2_blocks number;
7 v_fs2_bytes number;
8 v_fs3_blocks number;
9 v_fs3_bytes number;
10 v_fs4_blocks number;
11 v_fs4_bytes number;
v_full_blocks number;
13 v_full_bytes number;
14 begin
15 dbms_space.space_usage ('SYSTEM', 'T_SHRINK', 'TABLE', v_unformatted_blocks,
16 v_unformatted_bytes, v_fs1_blocks, v_fs1_bytes, v_fs2_blocks, v_fs2_bytes,
17 v_fs3_blocks, v_fs3_bytes, v_fs4_blocks, v_fs4_bytes, v_full_blocks, v_full_bytes);
18 dbms_output.put_line('Unformatted Blocks = '||v_unformatted_blocks);
19 dbms_output.put_line('FS1 Blocks = '||v_fs1_blocks);
20 dbms_output.put_line('FS2 Blocks = '||v_fs2_blocks);
21 dbms_output.put_line('FS3 Blocks = '||v_fs3_blocks);
22 dbms_output.put_line('FS4 Blocks = '||v_fs4_blocks);
23 dbms_output.put_line('Full Blocks = '||v_full_blocks);
24 end;
25 /
Unformatted Blocks = 0
FS1 Blocks = 0
FS2 Blocks = 0
FS3 Blocks = 0
FS4 Blocks = 1
Full Blocks = 1

PL/SQL procedure successfully completed.



Example
-------


Reference Documents
-------------------
<Note:242090.1>


    반응형
    Posted by [PineTree]
    ORACLE/ADMIN2014. 7. 5. 14:58
    반응형

    Oracle Client / Server Interoperability Support

    이 노트는 오라클 클라이언트 버전들이 어떤 오라클 데이터베이스의 버전들과 함께 동작하는 지, 지원되는 것을 이해하기 위해 사용한다.

    Introduction

    이 노트는 오라클 클라이언트 및 서버 버전들 사이의 상호 운용성을 위해 지원의 요약을 제공한다. 또한 이 자료에는 오라클 버젼들간의 데이버베이스 링크의 접속을 지원내용도 포함되어 있다. 참고로 이 자료를 통해 버그 수정을 할 수 있거나, 제품 결함을 조사하기 위한 지원과도 활용한다.

    참고로 이 자료는 단지 상호 운용성에 대한 일반적인 가이드 한다. - 어떤 제품 또는 유틸리티는 지원에 대한 특정 제품 / 유틸리티에 대한 특정 조합에 대해서는 추가적인 제약이 따를 수 있다. 예를 들면 : 프리 컴파일러, 익스포트/임포트 유틸리티 등.

    각 오라클 버젼 릴리스의 지원 상태에 대한 요약정보는 다음 자료를 참조 한다. Note:161818.1

    일반적인 정책

    오라클의 일반적인 정책은 이전 릴리스와의 호환성을 위해 각각 새로운 오라클 버전을 테스트하고 지원하는 것이다. :
    • 신규 버전이 출시 되면 당시 이전 릴리스가 계속 프리미어 지원 - Premier Support (이전의 기본 오류 수정 지원 - Primary Error Correction support )에 포함되는 각각의 이전 서버 릴리스에 대해 신규 클라이언트를 테스트한다.
    • 신규 서버 릴리스에 대해 이전 클라이언트를 테스트 한다 - 즉, 이전 릴리스가 계속 프리미어 지원 - Premier Support (이전 기본 오류 수정 지원 - Primary Error Correction support)에 포함되어 있거나 또는 확장 지원- Extended Support (이전 확장 유지 보수 지원 - Extended Maintenance support) 의 첫번째 도래한 2 년인 제품에 국한.
    • 오라클은 이러한 버전 간의 상호 운용성을 지원하는 것에 대한 신규 버전과 기타 이전 릴리스 간의 테스트를 추가 할 수 있다.

    현재의 상호 운용성 지원 상황

    매트릭스는 아래의 클라이언트 및 서버사이에 지원되는 조합을 요약해 놓았다.

    새로운 상호 운용성 문제는 만일 관련괸 양쪽 릴리스에 대한 문제가 보고되는 시점에 유효한 지원 계약에 해당 되는 범위 한도내에 조사 할 것이다. 
    예를 들면 :

    11.2.0 서버에 대해 10.2.0 클라이언트의 문제를 조사하기 위해 오라클의 10.2.0 클라이언트에 대해 유효한 연장 지원 - Extended Support 계약이 있어야 한다.


    Server Version
    Client Version11.2.011.1.010.2.010.1.09.2.09.0.18.1.78.1.68.1.58.0.68.0.57.3.4
    11.2.0YesESES #7NoWas #5No #3No #3No #3No #3No #3No #3No #3
    11.1.0ESESES #7Was #6Was #5No #3No #3No #3No #3No #3No #3No #3
    10.2.0ES #7ES #7ESWasWas #5NoWasNo #3No #3No #3No #3No #3
    10.1.0(#4)Was #6Was #6WasWasWasWasWas #2No #3No #3No #3No #3No #3
    9.2.0Was #5Was #5Was #5WasWasWasWasNoNoWasNoNo #1
    9.0.1NoNoNoWasWasWasWasWasNoWasNoWas
    8.1.7NoNoWasWasWasWasWasWasWasWasWasWas
    8.1.6NoNoNoNoNoWasWasWasWasWasWasWas
    8.1.5NoNoNoNoNoNoWasWasWasWasWasWas
    8.0.6NoNoNoNoWasWasWasWasWasWasWasWas
    8.0.5NoNoNoNoNoNoWasWasWasWasWasWas
    7.3.4NoNoNoNoWasWasWasWasWasWasWasWas

    Key:
    Yes지원된다
    LES제한된 확장 지원은 이전에는 9.2 버전에 적용하였으나 현재는 종료되었다.
    ES지원은 되지만 확장 지원 - Extended Support 이 있는 고객에게만 수정이 가능하다.
    Was지원이 되는 조합이었으나 현재는 Premier Support , Primary Error Correct support , Extended Support 가 더 이상 불가한 버젼으로 Extended Maintenance Support 로도 더 이상 수정이 가능하지 않다.
    No지원되지 않는다.
    Specific Notes:
    • #1 - 참조 - Note:207319.1
    • #2 - 10g 쿨라이언트에서 8.1.7.3 또는 그 이하 버전의 서버를 접속할 때 ORA-3134 오류가 잘못 보고 되었다. 참고 - Note:3437884.8 .
    • #3 - 이 버전에 연결을 시도 할 때 ORA-3134 오류가 올바르게 보고됩니다.
    • #4 - EBCDIC 기반의 8i/9i 서버에 10g 클라이언트에서 연결 문제가 있다. 참조 - Note:3564573.8
    • #5 - 10.2 (또는 그 이상 버젼) 과 9.2 간의 접속시 9.2 는 반드시 9.2.0.4 또는 그 이상 버전이어야 한다. 10.2 (또는 그 이상 버젼) 과 9.2.0.1, 9.2.0.2 또는 9.2.0.3 간의 접속은 지원하지 않는다.
    • #6 - 11.1 (또는 그 이상 버젼) 데이터베이스 서버와 10.1 / 10.2 데이터베이스 서버간의 데이터베이스 링크를 통한 접속의 경우 해당 버젼 간의 PLSQL을 사용하기 위해 10.1.0.5 / 10.2.0.2 (또는 그 이상 버젼)을 반드시 사용해야 한다. (이는 일반적인 11g 클라이언트에서 10g 데이터베이스 서버에 적용되는 사항은 아니며, 단지 서버와 서버 와 몇몇 특정 클라이언트 예를 들어 오라클 Forms 에서 확인이 된다.) 보다 자세한 내용은 다음의 문서를 참조 - Note:4511371.8
    • #7 - 11.1 (또는 그 이상 버젼) 과 10g의 마지막인 10.2 간의 데이터베이스 링크를 통한 접속의 경우 해당 버젼 간의 PLSQL을 사용하기 위해 10.2.0.2 (또는 그 이상 버젼)을 반드시 사용해야 한다. 보다 자세한 내용은 다음의 문서를 참조 - Note:4511371.8
    일반적인 주의사항 :
    1. 서로 다른 오라클 버전사이의 데이터베이스 링크 를 이용한 연경의 경우 위의 지원 메트릭스에서 반드시 양방향으로 지원되어야 한다.
      예를 들면 : 11.2 -> 10.1 처럼 지원되지 않는 다면, 이 두 버전간에 데이터베이스 링크는 어느 방향에서도 지원되지 않는다.
    2. 지원되지 않는 조합이 동작하는 것처럼 보일 수도 있지만 특정 작업에 오류가 발생할 수 있다. 그들이 동작하는 것 처럼 사실에 의존해서는 안되며 지원되지 않는 조합에 대한 문제는 조사되지 않는다.
    3. 신규 데이터베이스 서버는 이전의 OCI 클라이언트의 제한된 세트와 호환이 있기 때문에, 데이터베이스를 업그레이드 할 때 클라이언트 소프트웨어를 반드시 업그레이드 할 필요가 없다. 그러나 몇 가지 새로운 기능은 클라이언트 소프트웨어를 업그레이드하지 않고 작동하지 않을 수 있다. 따라서, 예를 들어, 오라클 10.2 클라이언트는 11.2 데이터베이스에 연결할 수 있지만, 클라이언트 결과 캐시 (11.1에서 도입) 등과 같은 새로운 기능을 활용할 수 없다.
    4. 오라클 응용 프로그램 또는 다른 오라클 제품들은 위의 매트릭스에서 나열되지 않은 구성들을 지원했을 수 있다. 다시 말하자면, 여기에 나열되어 있는 일부 버전들은 호환이 안될 수 있다. 우리는 종종 지원을 지속적으로 제공한다. 즉 Forms 8.0.6 과 10g RDBMS의 예를 볼 수 있다.
    5. 위의 매트릭스에서는 또한 오라클 클라이언트 / 서버의 서로 다른 플랫폼간과 32 / 64 비트 버전 사이에 오라클 플랫폼 지원 중단에 대한 별도의 공지가 나타내는 경우를 제외하고 적용된다.
    6. 유닉스 BEQUEATH (BEQ) 연결은 서로 다른 버전 사이에서 지원되지 않는다. 예를 들면 : 클라이언트 10.2는 위에 나열된 상호 운용성 지원에 관계없이 BEQ 프로토콜 어댑터를 사용하여 11.2 서버에 오라클 네트워크 연결을 지원하지 않는다. 자세한 내용은Note:364252.1 를 참고 한다.


    반응형
    Posted by [PineTree]
    ORACLE/ADMIN2014. 7. 2. 16:19
    반응형
    목적
    상세 내역
     소개
     손상을 처리하는 단계들의 개요
     노로깅(NOLOGGING) 또는 복구 불가능(UNRECOVERABLE)으로 인한 손상 
     (1) 손상 문제의 범위를 결정
     (2) 의심스러운 하드웨어를 교체 또는 이동
     (3) 어떤 객체가 영향을 받는가?
     (4) 관련 객체와 복구 방법
     캐쉬(CACHE)
     클러스터(CLUSTER) 
     파티션 인덱스(INDEX PARTITION)
     인덱스
     롤백(ROLLBACK)
     TYPE2 UNDO
     파티션 테이블(TABLE PARTITION)
     테이블(TABLE)
     IOT (인덱스 구성 테이블, Index Organized Table)
     LOB 인덱스(LOBINDEX)
     LOBSEGMENT
     임시(TEMPORARY)
     다른 세그먼트 유형(Other Segment Types)
      "반환된 행이 없음"
     (5) 복구 방법을 선택
     (5A) 전체 복구
     블록 수준 복구
     데이터파일 복구
     데이터베이스 복구
     전체 복구 후
     (5B) 인덱스 재생성
     (5C) 테이블로부터 데이터를 살리기
     손상된 블록 주변의 손상된 테이블에서 데이터를 추출하는 방법
     손상된 LOB 세그먼트 블록이 있는 테이블에서 데이터를 추출하는 방법
     손상된 블록 자체에서 데이터를 추출
     (5D) 손상된 위치를 남겨두기
     손상된 위치를 남겨 둘 때 경고
      (5E) 마지막 방법
    참고

    적용 대상:

    Oracle Database - Enterprise Edition - 버전 7.0.16.0 to 11.2.0.4 [릴리즈 7.0 to 11.2]
    이 문서의 내용은 모든 플랫폼에 적용됩니다.

    목적

    이 문서는 오라클 데이터파일에 하나 이상의 블록 손상들을 어떻게 처리하는지 설명하고 손상된 블록들을 다루기 위한 주요 작업에 대해 설명한다. 작업을 수행하기 전에 문서 전체를 읽는다.

    상세 내역

    소개

    이 문서는 오라클 데이터파일에 하나 이상의 블록 손상들을 어떻게 처리하는지 설명하고 손상된 블록들을 다루기 위한 주요 작업에 대해 설명한다. 작업을 수행하기 전에 문서 전체를 읽는다.

    이 노트는 메모리 손상 문제 (일반적으로 ORA-600 [17xxx] 유형 오류)를 포함하지 않는다.

    주의 : STARTUP중에 ORA-1578 문제가 발생하는 경우에는 문서:106638.1를 참조하여 상담 받기 위해 해당지역의 지원 센터에 문의하십시오.

             - 이 노트는 고객에게 공개되어 있지 않지만 관련 단계들은 경험이 많은 지원 분석가에 의해 제공되어질 수 있습니다.

     

    많은 오류 유형에 대해 여러 곳에서 이 문서를 참조 할 수 있다 - 손상된 블록에 대해 다음 정보를 확보하는 것이 중요하다 :

    • 손상된 블록을 포함하고 있는 파일의 절대 파일 번호(FILE NUMBER).
      이 문서에서 "&AFN"과 같이 사용되었다.
    • 손상된 블록을 포함하는 파일의 파일 이름(FILE NAME).
      이 문서에서 "&FILENAME"과 같이 사용되었다.
      파일 번호는 알고 있지만 파일 이름을 모르는 경우 파일 이름을 알기 위해 V$DATAFILE을 사용할 수 있다: 
    SELECT name FROM v$datafile WHERE file#=&AFN;       

      Oracle8i에서 파일 번호가 V$DATAFILE 표시되지 않고 &AFN이 DB_FILES 매개변수(parameter) 값보다 크다면 아마도 임시 파일(TEMPFILE) 일 것이다. 
      이 경우 파일 이름은 이 SQL문을 사용하여 찾을 수 있다:

    SELECT name FROM v$tempfile WHERE file#=(&AFN - &DB_FILES_value);
    • 해당 파일에서 손상 블록의 블록 번호(BLOCK NUMBER).
      이 문서에서 "&BL"과 같이 사용되었다.
    • 영향을 받는 블록을 포함하는 테이블스페이스 번호와 이름
      이 문서에서 "&TSN"(테이블스페이스 번호)와 "&TABLESPACE_NAME"과 같이 사용되었다.
      이들을 모를 경우 다음 SQL문을 사용하여 찾을 수 있다 :
    SELECT ts# "TSN" FROM v$datafile WHERE file#=&AFN;
    SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN;
    • 손상된 부분이 있는 테이블스페이스의 블록 크기(BLOCK SIZE).
      이 문서에서 "&TS_BLOCK_SIZE"와 같이 사용되었다.
    SELECT block_size FROM dba_tablespaces 
    WHERE tablespace_name = 
    (SELECT tablespace_name FROM dba_data_files WHERE file_id=&AFN);

    오라클 7, 8.0 그리고 8.1인 경우 :
    데이터베이스의 모든 테이블스페이스는 동일한 블록 크기를 가지고 있다.
    이 버전에서는 "SHOW PARAMETER DB_BLOCK_SIZE"로 &TS_BLOCK_SIZE 값을 사용할 수 있다.

     

    예 : ORA-1578 오류인 경우 :
                ORA-01578: ORACLE data block corrupted (file # 7, block # 12698)
                ORA-01110: data file 22: '/oracle1/oradata/V816/oradata/V816/users01.dbf'
          이라면:

    &AFN      은 "22"     (ORA-1110 오류 부분으로부터)
    &RFN      은 "7"      (ORA-1578의 "file #"로부터)
    &BL       은 "12698"  (ORA-1578의 "block #"로부터)
    &FILENAME 은 '/oracle1/oradata/V816/oradata/V816/users01.dbf'
    &TSN 등은 위의 SQL문으로부터 결정해야 한다.

     
    다른 오류(ORA-600, ORA-1498 등)에서 위의 값은 오라클 지원에 의해 제공되거나 관련 오류를 포함한 문서에서 제공된다.


    ORA-1410 "invalid ROWID" , ORA-12899 "value too large for column" 등과 같은 일부 오류는 손상된 파일 / 블록의 세부 사항을 제공하지 않는다. 이러한 경우 Document 869305.1가 손상된 행의 위치를 찾는 데 도움이 될 수 있다.

     

    손상을 처리하는 단계들의 개요

    블록 손상에는 여러 가지 원인이 있다.

      • 하드웨어 / 펌웨어의 잘못된 I/O
      • OS 문제
      • 오라클 문제
      • 노로깅(NOLOGGING) 또는 복구 불가능(UNRECOVERABLE)인 데이터베이스에서 복구
        (ORA-1578의 경우는 예상되는 동작이다.- 아래를 확인한다.)

    오라클 오류가 발생한 시점이 손상이 처음에 발생했을 때보다 훨씬 나중일 수 있다.

    근본 원인은 일반적으로 손상이 발생 된 시점에 알 수 없고, 대부분 가장 중요한 요구 사항은 정상적으로 다시 운영하는 것이다. 이 문서에서 손상 문제를 해결하기 위해 사용되는 단계는 아래와 같다:

      1. 손상 문제의 범위를 결정하고 문제가 영구적인지 또는 일시적인지 결정
        문제가 넓은 범위이거나 오류가 자주 발생하는 경우에는 먼저 원인을 파악에 주력한다(하드웨어를 확인하는 등..). 하드웨어에 결함이 있는 경우 시스템을 복구하는 것은 소용이 없기 때문에 매우 중요하다.
         
      2. 결함이 있거나 의심되는 하드웨어를 교체 또는 제거
      3. 어떤 데이터베이스 객체들이 영향을 받았는지 결정
      4. 가장 적합한 데이터베이스 복구 / 데이터 살리기 방법을 선택

    위의 모든 단계에서 증거를 수집하고 어떤 작업을 했는지에 대해 정확하게 기록하는 것이 중요하다. 이 문서의 '증거 >>' 태그들은 문제의 근본 원인 식별을 지원하기 위해 수집되어져야 하는 정보를 나열한 것이다.

     

    노로깅(NOLOGGING) 또는 복구 불가능(UNRECOVERABLE)으로 인한 손상 

    노로깅(또는 복구 불가능) 동작이 객체에서 수행되어 졌고 해당 객체가 포함 된 데이터파일이 나중에 복구되었다면 노로깅 동작에 의해 영향을 받은 데이터 블록들은 손상된 것으로 표시되어지고 액세스 할 때 ORA-1578가 발생할 것이다. Oracle8i에서 ORA-26040은 ("ORA-26040: Data block was loaded using the NOLOGGING option" ) 원인이 매우 분명하게 표시되지만 과거 버전은 추가적인 오류 메시지가 없다. 블록이 노로깅 동작을 통한 복구에 의해 손상된 경우에는 이 문서의 섹션 3 "어떤 객체가 영향을 받는가?"를 활용할 수 있지만 아래 사항을 주의해야 한다 :

      1. 복구 방법으로는 노로깅 데이터를 살릴 수 없다
      2. 블록 내부에서 살릴 수 있는 데이터는 없다

     

    (1) 손상 문제의 범위를 결정

    손상 오류가 발생할 때 마다 오류 메시지 전체를 기록하고 관련 오류에 대한 인스턴스의 경고 로그(alert log)와 추적 파일(trace file)을 확인한다. 하나의 블록 손상 또는 UNRECOVERABLE 작업으로 인한 오류인지 더 심각한 문제로 인한 오류지 확인하기 위해 가장 먼저 이 작업을 하는 것이 중요하다.

    문제의 범위를 결정하고 다른 손상이 있는지 확인하기 위해 영향 받는 파일(및 중요한 파일)에 DBVERIFY를 사용하여 분석하는 것이 좋다. 
    DBVERIFY 사용에 대한 상세내용은 Document 35512.1를 참고한다.

    손상된 파일/블록 목록들을 결정한 다음 조치할 수 있는 작업을 결정하는 데 아래 단계들은 도움이 될 수 있다.

    증거>>

    • 오류가 발생한 응용 프로그램의 세부 사항과 함께 원래 오류 전부를 기록
    • 경고 로그(alert log)에서 최초로 기록 된 문제 시점으로부터 몇 시간 전까지를 발췌하여 저장
    • 경고 로그에 언급 된 모든 추적 파일(trace file)들을 저장
    • 발생했던 최근 O/S 문제를 기록
    • 특별한 기능을 사용한다면 확인 - 예: 비동기 IO(aync IO),  빠른 디스크 저장(fast write disk) 기능 등
    • 현재 백업 상태를 기록(날짜, 유형 등)
    • 데이터베이스가 ARCHIVELOG 모드인지 아닌지 확인 - 예: SQL*Plus(또는 Server Manager)에서 "ARCHIVE LOG LIST" 실행

     

    (2) 의심스러운 하드웨어를 교체 또는 이동

    손상 문제의 대부분은 하드웨어 결함에 의해 발생한다.

    하드웨어 오류 또는 의심스러운 구성 요소가 있다면 하드웨어 문제를 해결하거나 복구 방법을 진행하기 전에 서브 시스템에서 사용 가능한 별도의 디스크 공간을 만드는 것이 좋다.

    다음 단계를 사용해서 데이터 파일을 이동할 수 있다 :

      • 이관되어야 할 파일이 OFFLINE이거나 인스턴스가 마운트(MOUNT) 상태(OPEN이 아님)인지 확인
      • 물리적으로 새로운 위치에 데이터 파일을 복원(또는 복사)
        예: /newlocation/myfile.dbf
      • 파일의 새로운 위치를 오라클에게 알려줌.
        예: ALTER DATABASE RENAME FILE '/oldlocation/myfile.dbf' TO '/newlocation/myfile.dbf';
            (임시 파일의 이름은 변경할 수 없음을 주의 – 임시 파일은 삭제 후 새로운 위치에 재생성 되어야 한다.)

    중요 : 여러 오류가 있다면(NOLOGGING으로 인한 것이 아닌)
            또는 영향을 받는 파일에 대한 OS의 오류가 있다면
            또는 오류가 과도하고 지속적으로 발생한다면
            근본적인 문제가 해결되거나 대체 디스크에서 사용할 수 공간이 확보 될 때까지 진행되는 작은 절차다. 하드웨어 공급 업체가 시스템을 확인하고 모든 오류의 세부 내용과 함께 오라클 지원 센터에 문의한다.

    참고 : 하드웨어 검사가 실패한 것은 하드웨어와 관련된 문제가 있다는 좋은 지표이고, 하드웨어 검사가 성공했어도 하드웨어 관련 문제가 없다는 것으로 증명될 수 없다. - 실제 근본적인 결함이 있음에도 불구하고 하드웨어 테스트는 성공했다고 보고되는 것은 매우 일반적이다.

     direct IO , async IO 또는 유사한 특별한 IO 기능을 사용한다면 잠재적인 문제의 원인을 제거하기 위해 그러한 기능을 비활성화하는 것은 좋을 수 있다.

     

    (3) 어떤 객체가 영향을 받는가?

    복구하는 방법에 대해 결정을 하기 전에 어떤 객체가 영향을 받았는지 확인하는 것이 가장 좋다. - 다시 만들기 쉬운 객체에 손상이 있을 수 있기 때문이다.
    예: 테이블의 5개 행에서 손상인 경우 테이블을 삭제하고 다시 생성하는 것이 복구를 수행하는 것보다 더 빠를 수 있다.

    각 손상에 대해 다음 표에 있는 정보를 수집한다.
    이 작업을 수행하기 위한 단계는 아래에 설명되어 있다. 

    각 손상에 대해 기록해야 하는 정보
    최초 오류절대 파일 번호 &AFN상대 파일 번호 &RFN블록 번호 &BL테이블스페이스세그먼트 유형세그먼트 소유자 이름관련 객체복구 방법

     각 손상에 대해서 이 표를 기록하는데 아래 정보가 도움이 될 것이다.

     

    1. "최초 오류" 최초에 보고된 오류다. 예 : ORA-1578 / ORA-1110 , 모든 인수(argument)를 포함한 ORA-600 등..

    2. "절대 파일 번호", "상대 파일 번호" 그리고 "블록 번호" 파일 번호 및 블록 번호는 오류, 오라클 지원, 또는 이 문서에서 제공된 오류 문서 안의 단계에 의해 확인할 수 있다.

        Oracle8/8i/9i/10g: 절대 파일번호와 상대 파일 번호는 거의 동일하지만 다를 수도 (특히 데이터베이스가 Oracle7에서 이관 된 경우) 있다. &AFN과 &FN에 대한 정확한 번호를 확인하는 것이 중요하며 틀릴 경우에는 잘못된 객체를 살릴 수도 있다.

        ORA-1578은 동반된 ORA-1110 오류 안에 절대 파일 번호와 함께 상대 파일번호를 알려준다. ORA-600 오류에서는 절대 파일 번호를 알려준다.

        다음 질의는 데이터베이스 안의 데이터파일에 대한 절대 및 상대 파일 번호를 표시할 것이다 :

    SELECT tablespace_name, file_id "AFN", relative_fno "RFN" 
    FROM dba_data_files;

        Oracle8i/9i/10g:

        위의 정보 외에도 Oracle8, Oracle8i 이후부터는 임시 파일(TEMPFILE)을 가질 수 있다. 아래 질의는 데이터베이스 안의 임시 파일에 대한 절대 및 상대 파일 번호를 표시할 것이다 :

    SELECT tablespace_name, file_id+value "AFN", relative_fno "RFN" 
    FROM dba_temp_files, v$parameter 
    WHERE name='db_files';

        Oracle7:  절대 파일 번호와 상대 파일 번호 모두 동일한 파일 번호를 사용한다.

     

    3. "세그먼트 유형", "소유자", "이름" 그리고 "테이블스페이스"
    다음 질의는 주어진 절대 파일 번호 &AFN"과 손상된 블록의 블록 번호 "&BL"에 대해 객체 타입, 소유자, 세그먼트의 이름을 확인해 줄 것이다. – 질의를 하기 위해서 데이터베이스는 열려(OPEN) 있어야 한다 :

    SELECT tablespace_name, segment_type, owner, segment_name 
    FROM dba_extents 
    WHERE file_id = &AFN 
    and &BL between block_id AND block_id + blocks - 1;

     

    만약 블록이 임시 파일 안에 있다면 위의 질의의 결과는 없을 것이다.
    임시 파일에 대한 "세그먼트 유형"은 "TEMPORARY" 이다.

    위의 질의가 어떠한 행도 반환되지 않는 경우 손상된 블록이 로컬 관리 테이블스페이스(Locally Managed Tablespace, LMT)의 세그먼트 헤더일 수 있다.손상된 블록이 LMT안의 세그먼트 헤더 블록일 때, 위의 질의는 경고 로그(alert log)에 손상 메시지를 생성하지만 질의가 실패하지는 않는다. 이 경우 아래 질의를 사용한다:

    SELECT owner, segment_name, segment_type, partition_name 
    FROM dba_segments 
    WHERE header_file = &AFN 
    and header_block = &BL ;

     

    (4) 관련 객체와 복구 방법

    관련 객체와 복구 방법은 세그먼트 유형에 따라 달라질 수 있다. 추가적인 질의와 가능한 복구 방법은 가장 일반적인 세그먼트 유형 각각에 대해서 아래에 설명되어 있다.

    캐쉬(CACHE)
    클러스터(CLUSTER) 
    파티션 인덱스(INDEX PARTITION)   인덱스(INDEX) 
    LOB 인덱스(LOBINDEX)                LOB 세그먼트(LOBSEGMENT) 
    롤백(ROLLBACK) 
    파티션 테이블(TABLE PARTITION)   테이블(TABLE)
    임시(TEMPORARY)
    TYPE2 UNDO
    다른 세그먼트 유형(Other Segment Types)
    질의로부터 "no rows"

     

    캐쉬(CACHE)

    -세그먼트 유형이 CACHE인 경우에는 정확하게 SQL과 매개 변수(parameter)를 입력하였는지 재확인한다. 동일한 결과가 나온다면 모든 정보와 함께 오라클 지원을 받는다.

    방법:

       데이터베이스 복구를 필요로 할 가능성이 있다.

     

    클러스터(CLUSTER) 

    - 세그먼트가 클러스터인 경우에는 클러스터에 포함되어 있는 테이블들을 확인한다.

    예 : SELECT owner, table_name fROM dba_tables WHERE owner='&OWNER' AND cluster_name='&SEGMENT_NAME';


    방법:
       소유자가 "SYS"인 경우 모든 상세 내용과 함께 오라클 지원을 받는다.
       데이터베이스 복구를 필요로 할 가능성이 있다.

       딕셔너리 클러스터가 아닌 경우 가능한 방법:
          복구
          또는 클러스터 안의 모든 테이블에서 데이터를 살린 후 클러스터와 모든 테이블을 재생성 한다.

       클러스터는 몇 개의 테이블로 구성되기 때문에 복구 방법을 결정을 하기 전에 클러스터 안의 각 테이블에 대한 정보를 수집하는 것이 가장 좋다.

     

    파티션 인덱스(INDEX PARTITION)

    - 세그먼트가 파티션 인덱스인 경우 이름과 소유자를 기록한 다음 영향 받는 파티션을 확인한다 :

        SELECT partition_name
        FROM dba_extents
        WHERE file_id = &AFN AND &BL BETWEEN block_id AND block_id + blocks - 1

     

    그런 다음 세그먼트가 인덱스 세그먼트였다면 아래와 같이 계속 진행한다.

    방법:
      파티션 인덱스는 아래와 같이 사용하여 재생성(rebuild) 할 수 있다:
        ALTER INDEX xxx REBUILD PARTITION ppp;    
      (아래 "(5B)인덱스 재생성"에서 설명된 것처럼 재생성(REBUILD) 방법을 다룬다.)

     

    인덱스

    - 세그먼트 유형이 인덱스이면서 소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.

      딕셔너리 인덱스나 파티션 인덱스가 아닌 경우는 인덱스의 테이블을 확인한다:

        SELECT table_owner, table_name
        FROM dba_indexes
        WHERE owner='&OWNER' AND index_name='&SEGMENT_NAME';


      제약 조건의 유형(CONSTRAINT_TYPE)에 대한 값은 다음과 같다.

    P    인덱스는 기본 키 제약 조건(primary key constraint)을 지원한다.
    U    인덱스는 고유 키 제약 조건(unique constraint)을 지원한다.

      인덱스가 기본 키 제약 조건("P" 유형)을 지원할 경우는 기본 키가 외래 키 제약 조건(foreign key constraint)에 의해 참조되었지 확인한다.

        SELECT owner, constraint_name, constraint_type, table_name
        FROM dba_constraints
        WHERE r_owner='&TABLE_OWNER' AND r_constraint_name='&INDEX_NAME';


    방법:
      소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 인덱스가 아닌 경우에 대한 가능한 방법은 다음과 같다:
      복구
      또는 인덱스 재생성(관련된 모든 제약 조건에 대해 활성화(enable)/비활성화(disable)와 함께)
      (아래 "(5B)인덱스 재생성"에서 설명된 것처럼 재생성(REBUILD) 방법을 다룬다.)

     

    롤백(ROLLBACK)

    - 세그먼트가 롤백 세그먼트인 경우에는 롤백 세그먼트 손상에 대한 특별한 조치가 필요하므로 오라클 지원을 받는다.


    방법:
    데이터베이스 복구를 필요로 할 가능성이 있다.

           

    TYPE2 UNDO

    - TYPE2 UNDO는 롤백 세그먼트의 특별한 유형으로 시스템에서 관리하는 실행 취소 세그먼트(system managed undo segment)이다. 이 세그먼트의의 손상은 특별한 조치가 필요하다.

    방법:
      데이터베이스 복구를 필요로 할 가능성이 있다.

     

    파티션 테이블(TABLE PARTITION)

    - 세그먼트 유형이 파티션 테이블인 경우는 이름과 소유자를 기록한 다음 영향 받는 파티션을 결정한다 :

    SELECT partition_name
    FROM dba_extents
    WHERE file_id = &AFN
    AND &BL BETWEEN block_id AND block_id + blocks - 1;


      그런 다음 세그먼트가 테이블 세그먼트였다면 아래와 같이 계속 진행한다.

    방법:
      모든 손상이 동일한 파티션 안에 있는 상황에선 비어있는 테이블을 손상된 파티션과 교체(EXCHANGE)하는 방법이 있다. - 테이블로부터 정상적인 데이터를 추출하는 동안 (손상된 파티션 안의 데이터를 조회하지 않고) 지속적으로 응용 프로그램을 허용할 수 있다.

      다른 방법은 아래 "테이블(TABLE)" 방법을 참조한다.

     

    테이블(TABLE)

    - 소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 테이블이나 파티션 테이블이 아닌 경우는 테이블에 존재하는 인덱스를 확인한다.

          예: SELECT owner, index_name, index_type
              FROM dba_indexes
              WHERE table_owner='&OWNER'
                AND table_name='&SEGMENT_NAME';


      그리고 테이블에 기본 키(primary key)가 있는지 확인한다.

          예:SELECT owner, constraint_name, constraint_type, table_name
             FROM dba_constraints
             WHERE owner='&OWNER'
               AND table_name='&SEGMENT_NAME'
               AND constraint_type='P';

     
      기본 키(primary key)가 있는 경우는 외래 키 제약 조건(foreign key constraint)에 의해 참조되는지 확인한다.

          예:
            SELECT owner, constraint_name, constraint_type, table_name
            FROM dba_constraints
            WHERE r_owner='&OWNER'
              AND r_constraint_name='&CONSTRAINT_NAME';


    방법:
      소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 테이블이 아닌 경우에 대한 가능한 방법은 다음과 같다:
      복구
      또는 테이블(또는 파티션)으로부터 데이터를 살린 다음 테이블(또는 파티션)을 재생성 한다.
      또는 손상된 위치를 그대로 남겨둔다.
            (예: 생략해야 될 문제의 블록을 표시하기 위하여 DBMS_REPAIR를 사용한다.)

     

    IOT (인덱스 구성 테이블, Index Organized Table)

    - IOT 테이블의 손상은 힙(heap)이나 파티션 테이블과 같은 방식으로 처리 해야 한다.
      PK가 손상된 경우는 예외이다.
      IOT 테이블의 PK는 테이블 자체이며, 삭제나 재생성은 할 수 없다.

    방법:
      소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 테이블이 아닌 경우에 대한 가능한 방법은 다음과 같다: 
      복구
      또는 테이블(또는 파티션)으로부터 데이터를 살린 다음 테이블(또는 파티션)을 재생성 한다.
      또는 손상된 위치를 그대로 남겨둔다.
            (DBMS_REPAIR는 IOT에서 사용할 수 없다.)

     

    LOB 인덱스(LOBINDEX)

    - LOB가 속해 있는 테이블을 확인한다:

     SELECT table_name, column_name
     fROM dba_lobs
     wHERE owner='&OWNER'
     AND index_name='&SEGMENT_NAME';


    - 테이블의 소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

    - LOB 인덱스는 재생성(rebuild)될 수 없으므로 영향 받는 테이블의 LOB 컬럼의 손상과 같은 문제로 다뤄야 한다.
      "테이블(TABLE)" 부분의 SQL을 사용하여 손상된 LOB 인덱스를 가지는 테이블에 대한 인덱스와 제약 조건 정보를 확인한 다음 다시 여기로 돌아 온다.

    방법:
      소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 테이블이 아닌 경우에 대한 가능한 방법은 다음과 같다:
      복구
      또는 테이블(또는 파티션)으로부터 데이터를 살린 다음 테이블(또는 파티션)을 재생성 한다.

      문제의 컬럼에 추가적인 DML이 없는 경우를 제외하고 손상을 그대로 남겨 두는 것은 일반적으로 좋지 않다.

     

    LOBSEGMENT

    - LOB가 속해 있는 테이블을 확인한다:

    예:
    SELECT table_name, column_name
      FROM dba_lobs
       WHERE owner='&OWNER'
       AND segment_name='&SEGMENT_NAME'; 


    소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다. 데이터베이스 복구를 필요로 할 가능성이 있다.

    딕셔너리 테이블이 아닌 경우 ...

      "테이블(TABLE)" 부분의 SQL을 사용하여 손상된 LOB 인덱스를 가지는 테이블에 대한 인덱스와 제약 조건 정보를 확인한 다음 영향 받는 행의 상세한 내용을 확인하기 위해 다시 여기로 돌아온다.

      손상된 LOB를 가지는 테이블 행에 대해 어떠한 상세 내용 없이 오류가 보고되기 때문에 손상된 LOB 블록을 참조하는 정확한 행을 찾는 것은 힘들 수 있다.

      일반적으로 응용프로그램의 로그나 SQL_TRACE 또는 오류가 발생한 세션의 10046 TRACE(해당되는 경우)에서 확인

    event "1578 trace name errorstack level 3"

      현재의 SQL/바인드/행을 식별하는데 도움이 된다.

    예:
    ALTER SYSTEM SET EVENTS '1578 trace name errorstack level 3'; 


      그런 다음 응용 프로그램에서 오류가 발생하기를 기다리고 추적파일(trace file)을 찾는다.

      추가적인 단서가 없는 경우 문제 테이블의 행을 검색하기 위해 오류가 발생할 때까지 반복하여 LOB 데이터를 추출하는 PLSQL 블록을 만들 수 있다. 이러한 방법은 시간이 걸릴 수 있지만 손상된 LOB 블록을 참조하는 기본 키 또는 행의 ROWID를 얻을 수 있다.

    예:
    set serverout on
    exec dbms_output.enable(100000);
    declare
     error_1578 exception;
     pragma exception_init(error_1578,-1578);
     n number;
     cnt number:=0;
     badcnt number:=0;
    begin
      for cursor_lob in
            (select rowid r, &LOB_COLUMN_NAME L from &OWNER..&TABLE_NAME)
      loop
        begin
          n:=dbms_lob.instr(cursor_lob.L,hextoraw('AA25889911'),1,999999) ;
        exception
         when error_1578 then
           dbms_output.put_line('Got ORA-1578 reading LOB at '||cursor_lob.R);
           badcnt:=badcnt+1;
        end;
        cnt:=cnt+1;
      end loop;
      dbms_output.put_line('Scanned '||cnt||' rows - saw '||badcnt||' errors');
    end;
    /


      보다 일반적인 다른 스크립트

    set serverout on
    exec dbms_output.enable(100000);
    declare
      pag    number;
      len    number;
      c      varchar2(10);
      charpp number := 8132/2;

    begin
      for r in (select rowid rid, dbms_lob.getlength (<your_clob_column>) len
                from   <your_table_with_clcob_column>) loop
        if r.len is not null then
          for page in 0..r.len/charpp loop
            begin
              select dbms_lob.substr (<your_clob_column>, 1, 1+ (page * charpp))
              into   c
              from   <your_table_with_clcob_column>
              where  rowid = r.rid;
           
            exception
              when others then
                dbms_output.put_line ('Error on rowid ' ||R.rid||' page '||page);
                dbms_output.put_line (sqlerrm);
            end;
          end loop;
        end if;
      end loop;
    end;
    /

     

    방법:
      소유자가 "SYS"인 경우는 모든 상세 내용과 함께 오라클 지원을 받는다.
      데이터베이스 복구를 필요로 할 가능성이 있다.

      딕셔너리 테이블이 아닌 경우에 대한 가능한 방법은 다음과 같다:
      복구
      또는 테이블(그리고 LOB 컬럼)으로부터 데이터를 살린 다음 테이블(또는 파티션)을 재생성 한다.
      또는 손상된 위치를 그대로 남겨둔다.
            (DBMS_REPAIR는 LOB 세그먼트에서 사용되어 질 수 없다.)

     

    임시(TEMPORARY)

    - 세그먼트 유형이 TEMPORARY인 경우 손상은 영구적인 객체(permanent object)에 영향을 주지 않는다. 문제가 발생한 테이블 스페이스가 TEMPORARY 테이블스페이스인지 확인한다.

    SELECT count(*) FROM dba_users WHERE temporary_tablespace='&TABLESPACE_NAME';


    방법:
      임시 테이블스페이스인 경우 새로운 임시 테이블스페이스를 생성할 수 있고 모든 사용자에 대해해당 테이블스페이스로 변경한 다음  문제의 테이블스페이스를 삭제할 수 있다.

      임시 테이블스페이스가 아닌 경우 그 블록은 다시 읽지 말아야 하고 다음에 그 블록을 사용할 때 다시 포맷되어야 한다 - 치유된 근본 원인을 반복해서는 안 된다.

      디스크가 의심되고 테이블스페이스가 자주 사용되는 데이터를 포함한다면 영향 받는 파일의 데이터베이스는 복구 될 수 있지만 일반적으로 복원은 필요하지 않다.

    다른 세그먼트 유형(Other Segment Types)

    - 세그먼트 유형이 위의 결과가 아닌 경우 현재까지 수집된 모든 정보와 함께 오라클 지원을 받는다.

     

     "반환된 행이 없음"

    손상된 블록을 포함하는 영역(extent)이 없는 경우에는 먼저 질의에 사용된 숫자를 다시 확인한다. 파일과 블록이 정확하다고 확신하고 DBA_EXTENTS에서 객체에 속한 것이 표시되지 않는다면:

      • 임시 파일에 속한 파일인지 다시 확인한다.
      • 임시 파일 번호가 init.ora의 DB_FILES 매개변수에 의존하기 때문에 이 매개 변수의 변경사항이 오류에 포함된 절대 파일 번호를 변경한다.
      • DBA_EXTENT는 로컬로 관리하는 테이블스페이스(locally managed tablespace)의 로컬 공간 관리에 사용되어진 블록을 포함하지는 않는다.
      • 지금 질의하는 데이터베이스가 오류가 발생한 데이터파일과 다른 지점이라면 문제가 되는 객체는 삭제되었을 수 있고 DBA_EXTENTS에 대한 조회 결과는 없을 수 있다.
      • 조사중인 오류가 DBVERIFY에 의해 보고된 경우에는 객체에 속하는지에 대한 여부와 상관없이 DBV는 모든 블록을 검사한다. 다른 객체에 사용되지 않는 블록이지만 데이터파일에 존재하는 손상된 블록일 수 있다.

    방법:
      사용하지 않는(UNUSED) 오라클 블록에서의 오류는 기존의 문제가 있는 블록은 읽지 않으며 오라클이 새로운 블록 이미지를 만들 것이기 때문에 무시할 수 있다.

      공간을 관리하는 블록(space management block)이 의심되는 경우 문제를 확인하기 위하여 아래와 같이 DBMS_SPACE_ADMIN를 사용할 수 있다:

    exec DBMS_SPACE_ADMIN.TABLESPACE_VERIFY('&TABLESPACE_NAME');


      이렇게 하는 것은 추적 파일(trace file)에 일관성 없이 쓰여지겠지만 심각하게 손상된 블록을 발견하면 아래와 같은 오류가 발생할 것이다:

    ORA-03216: Tablespace/Segment Verification cannot proceed

     

    증거>>

    각각의 손상된 블록에 대하여 손상의 실제 원인을 식별 하고 확인할 필요가 있다면 다음과 같은 물리적 증거를 수집하는 것도 좋은 생각이다.

    1. 손상 블록과 그 블록의 전/후 블록에 대한 운영체제 HEX 덤프

       유닉스 :

    dd if=&FILENAME bs=&TS_BLOCK_SIZE skip=&BL-1 count=3 of=BL.dd
       ^^^^^^^^      ^^^^^^^^^^^^^^         ^^^

      예 : BL=1224 라면:

    dd if=ts11.dbf bs=4k skip=1223 count=3 of=1223_1225.dd

     

      VMS:

    DUMP/BLOCKS=(start:XXXX,end:YYYY)/out=dump.out &FILENAME

      XXXX= OS 블록 번호(512바이트 조각)일 때 '&TS_BLOCK_SIZE/512'로 보고된 블록 번호를 곱하여 계산.

    2. ARCHIVELOG 모드인 경우 오류가 발생한 시간 주위, 바람직하게는 오류가 발생하기 전 몇 시간 동안의 ARCHIVELOG 파일의 안전한 복사본을 만든다. 또한 이전 이미지와 REDO로 원인을 파악하는데 도움이 될 수 있기 때문에 오류가 발생하기 전의 문제 데이터파일의 백업을 확보한다.

        (DBV는 파일의 백업 복사본에 문제가 존재하는지 확인하기 위하여 종종 사용되어진다.) 이상적인 시나리오는 어떠한 손상도 없는 데이터파일 백업 이미지와 손상이 처음 보고된 시점과 그 이전의 시간까지의 모든 REDO를 확보하는 것이다.

    3. 문제 블록의 오라클 덤프를 확보:

    ALTER SYSTEM DUMP DATAFILE '&FILENAME' BLOCK &BL;

        (결과는 USER_DUMP_DEST의 추척 파일(trace file)이다.)

     

    (5) 복구 방법을 선택

    영향 받는 객체에 따라 가장 좋은 복구 방법은 달라진다. 각 영향 받는 객체에 사용할 수 있는 주요 방법은 위 섹션 (3)의 정보에서 강조했다. 선택되어진 실제 복구 방법은 하나 이상의 방법을 조합할 수 있다 :

    복구가 필요한가?

    오류가 임시 테이블스페이스에 있거나 더 이상 데이터베이스 객체의 일부분이 아닌 블록인 경우 다른 스토리지 장비에 문제의 테이블스페이스를 재배치하는 것이 바람직할 수 있을지라도 아무런 조치가 필요하지도 않을 수 있다. 경고를 확인한다.

    완전 복구 방법인가?

    완전 복구를 위해서 다음의 조건이 참이어야 한다.

    • 데이터 베이스는 ARCHIVELOG 모드이다.

      ( "ARCHIVE LOG LIST" 명령어는 ARCHIVELOG 모드인지 보여준다.)

    • 영향 받는 파일들의 좋은 백업이 있어야 한다. 몇 가지 경우에서 현재 손상은 되었지만 오랜 시간 동안 발견되지 않을 수도 있음을 주의한다. 가장 최근의 데이터파일 백업이 여전히 손상을 포함하고 있다면 필요한 ARCHIVELOG 전체가 있는 한 더 이전의 백업이 필요할 수 있다. 
      ( 백업파일의 복구된 복사본에서 특정 블록이 손상되었다면 검증하기 위하여 종종 DBV START= / END= 방법을 사용할 수 있다.)

    • 모든 ARCHIVELOG는 백업 받은 시간으로부터 현재 시점까지 이용 가능해야 한다.

    • 현재 온라인 로그는 이용 가능해야 하고 아무 이상이 없어야 한다.

    • NOLOGGING 동작을 통해서는 오류를 복구할 수 없다. 

    위의 조건이 만족 될 때 완전 복구는 일반적으로 선호되는 방법이다. 

    *하지만 주의한다*

    (a) 트랜잭션의 롤백이 자체의 롤백 세그먼트 외에 다른 객체에서 손상된 블록을 나타낸다면 UNDO는 삭제되었을 수 있다.이 경우 인덱스를 재생성(rebuild) / 완전 복구 후 데이터 무결성을 확인 할 필요가 있다.


    (b) 데이터파일 또는 데이터베이스 복구를 사용한 경우 복구되어진 파일이 마지막 백업 이후 NOLOGGING 동작인 데이터를 포함한다면 그 블록들은 손상으로 표시될 것이다. 어떤 경우에는 현재보다 더 나쁜 시나리오가 될 수 있다.

    데이터베이스 복구가 벌써 실행되어졌고 손상은 아직 존재한다면 모든 백업이 손상을 포함하거나 근본 결함이 아직 존재하거나 REDO를 통해 문제가 재현된 것이다.

    완전 복구 단계를 위한 "(5A) 완전 복구"를 참조한다.

    객체는 객체 자신으로부터 데이터를 추출할 필요 없이 삭제 또는 재생성 되어 질 수 있는가?

    객체를 잃거나 스크립트/최근 익스포트로 재생성 할 수 있다. 객체가 삭제되어진 다음 해당 객체의 블록은 "free"로 표시되고 그 블록이 새로운 객체에 할당되어졌을 때 다시 포맷되어질 것이다. 어떤 데이터도 필요하지 않다고 절대적으로 확신되지 않는다면 DROP보다는 RENAME하는 것이 좋다.


    파티션 테이블인 경우 영향을 받는 파티션만 삭제되어 질 수 있다.

    예: ALTER TABLE ... DROP PARTITION ...

    파티션 세그먼트 헤더나 파티션 헤더가 포함된 파일이 오프라인된 손상이라면 DROP PARTITION은 실패할 것이다. 이 경우에도 여전히 동일하게 정의된 테이블과 교환하여 파티션을 삭제할 수 있다.

    예: ALTER TABLE .. EXCHANGE PARTITION .. WITH TABLE ..;


    재 생성을 할 수 있는 대부분의 일반적인 객체는 인덱스다.
    항상 테이블의 인덱스 문제 이전에 테이블 손상을 먼저 해결한다.
    자세한 내용은 "(5B) 인덱스 재생성"를 참조한다.

    모든 세그먼트에서 절대 파일 번호와 손상 블록의 블록 번호를 알고 있을 때 객체의 DDL을 추출하는 가장 빠른 방법은 아래와 같다:

    set long 64000
    select dbms_metadata.get_ddl(segment_type, segment_name, owner)
    FROM dba_extents
    WHERE file_id=&AFN
    AND &BL BETWEEN block_id AND block_id + blocks -1;

     

    객체를 재생성 하기 전에 데이터를 살리는 것이 필요한가?

    정기적으로 변경되는 중요한 응용프로그램 테이블에서 문제가 발생한 경우에는 가능한 테이블로부터 많은 데이터를 살리는 것이 필요할 것이고 그런 다음 테이블을 재생성 한다.

    자세한 내용은 "(5C) 테이블에서 데이터 살리기"를 참조한다.

    이 순간을 위해 손상된 장소를 남겨 두는 것을 허용하는가?

    어떤 경우에는 가장 즉각적인 방법은 손상된 장소를 그대로 남겨 두는 것이고 응용프로그램의 접근을 허용하지 않도록 하는 것이다.

    자세한 내용은 "(5D) 손상된 위치를 남겨두기"를 참조한다.

    마지막 방법

    아래의 방법이 가능한가?

    데이터베이스나 테이블스페이스 시간 복구를 통하여 오래된 시점(시간 복구의 시점으로부터)으로 복구
    또는 손상 이전의 COLD 백업의 복원
    또는 존재하는 익스포트 파일을 사용하는 것

    자세한 내용은 "(5E) 마지막 방법"을 참조한다.

     

    (5A) 전체 복구

    데이터베이스가 ARCHIVELOG 모드이고 영향 받은 파일의 좋은 백업을 가지고 있다면 일반적으로 선호하는 방법이다.

    문제를 해결하는 것에 대해 보장하지 않지만 손상 이슈의 대부분에 효과적이다. 복구한 뒤 문제가 재현된다면 위의 방법 목록으로 돌아가서 다른 방법을 선택한다.

    오라클 9i(또는 이상)을 사용하는 경우 RMAN BLOCKRECOVER 명령을 사용하여 블록 수준의 복구를 수행할 수 있다.

    이전의 오라클 버전을 사용하는 경우 데이터파일 복구(데이터베이스의 나머지 부분은 여전히 실행되는 동안 완료될 수 있다.), 또는 데이터베이스 복구(데이터베이스가 중단되어야 한다.) 중 하나를 수행할 수 있다.

    오라클 11g (또는 이상)을 사용하는 경우 데이터 복구 관리자를 사용할 수 있다.

     

    블록 수준 복구

    오라클9i의 RMAN은 데이터베이스(데이터파일의 다른 블록 포함)의 나머지 부분에 평소처럼 조회를 하면서 개별적인 블록을 복구할 수 있다. 블록 레벨 복구는 단지 현재 시점으로 블록을 완전히 복구하는데 사용할 수 있다.

    개별 블록의 복구 방법을 사용하기 위하여 RMAN 백업을 사용할 필요는 없다.
    예:

    미디어 손상 문제로 인하여 파일 #6 블록 #30에 ORA-1578이 있고 '.../RESTORE/filename.dbf'에 복원되어지는 파일에 대한 좋은 COLD 백업 이미지가 있는지 고려한다. (기본 위치에) 존재하는 모든 아카이브로그를 제공한 다음 블록 수준의 복구를 수행하기 위해 다음과 같은 명령어를 사용하여 RMAN을 사용할 수 있다.

    rman nocatalog
      connect target
       catalog datafilecopy '.../RESTORE/filename.dbf';
          run {blockrecover datafile 6 block 30;}

    현재 시점에 단 하나의 문제 블록의 블록 복구를 수행하기 위해 등록된 데이터파일 백업 이미지와 필요한 ARCHIVELOG를 사용할 것이다.

    RMAN BLOCKRECOVER 명령어와 한계의 자세한 내용에 대해서 문서를 참조한다. Document 144911.1 문서의 예제를 참조한다.

    데이터파일 복구

    데이터파일 복구는 다음 단계를 포함한다. 여러 개의 파일인 경우 각 파일의 단계를 반복하거나 아래의 "데이터베이스 복구"를 참조한다. 데이터베이스가 OPEN이거나 MOUNT인 상태라면 이 단계들을 사용할 수 있다.

    영향 받은 데이터파일을 오프라인

    예: ALTER DATABASE DATAFILE 'name_of_file' OFFLINE;

    (정상적이지 못한 백업인 경우를 대비하여) 안전한 위치로 복사

    정상적인 디스크에 파일의 최신 백업을 복원

    확실한 손상을 위하여 DBVERIFY로 복원 된 파일을 확인한다.

    DBVERIFY 사용에 대한 자세한 내용은 Document 35512.1를 참조한다.

    복원 된 파일이 정상이라면 새로운 위치의 데이터파일의 이름을 변경한다. (이전 위치와 다른 경우)

    예: ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';

    데이터파일 복구

    예: RECOVER DATAFILE 'name_of_file';

    파일을 온라인

    예: ALTER DATABASE DATAFILE 'name_of_file' ONLINE;
    데이터베이스 복구

    데이터베이스 복구는 일반적으로 아래의 단계를 포함한다:

    Shutdown (Immediate or Abort)


    안전한 위치로 복구되어질 현재의 모든 파일을 복사

    정상적인 디스크 위치에 백업파일을 복원
    컨트롤 파일과 온라인 REDO 로그 파일은 복원하지 않는다.

    DBVERIFY를 사용하여 복원된 파일을 검사한다. DBVERIFY를 사용하는 자세한 방법은 Document 35512.1를 참조한다.

    Startup MOUNT

    변경된 파일의 이름을 변경한다.

    예: ALTER DATABASE RENAME FILE 'old_name' TO 'new_name';

    요구한 모든 파일이 온라인인지 확인한다.

    예: ALTER DATABASE DATAFILE 'name_of_file' ONLINE;

    데이터베이스 복구

    예: RECOVER DATABASE

    데이터베이스 오픈

    예: ALTER DATABASE OPEN;
    전체 복구 후

    전체 복구가 수행되었다면 데이터베이스를 사용할 수 있도록 하기 전에 아래와 같이 확인하는 것이 좋다:

    실행 :

    "ANALYZE <table_name> VALIDATE STRUCTURE CASCADE"

    테이블/인덱스의 불일치를 확인하기 위하여 각 문제 객체에 대해 수행한다.
    삭제된 UNDO가 있다면 재생성 되어야 할 인덱스에 대해 불일치가 발생할 수 있다.
    응용 프로그램에서 테이블 안의 데이터에 대한 논리적 무결성을 확인한다.

     

    (5B) 인덱스 재생성

    손상된 객체가 사용자의 인덱스인 경우에는 테이블이 손상되지 않았다는 전제하에 간단하게 삭제 및 재생성을 할 수 있다.

    기반 테이블이 손상된 경우에는 인덱스를 재생성 하기 전에 테이블을 정리하는 것이 좋다.

    수집된 정보에 외래키 제약조건이 있는 인덱스가 발견되는 경우에는 아래와 같이 수행해야 된다:

    • 각 외래키를 위하여
    ALTER TABLE <child_table> DISABLE CONSTRAINT <fk_constraint>;
    • 기본키를 재작성(rebuild)하기 한다.
    ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>;
    DROP INDEX <index_name>;
    CREATE INDEX <index_name> .. with appropriate storage clause
    ALTER TABLE <table> ENABLE CONSTRAINT <pk_constraint>;
    • 외래키 제약조건을 활성화 한다.
    ALTER TABLE <child_table> ENABLE CONSTRAINT <fk_constraint>;

    파티션 인덱스인 경우 아래와 같이 수행한다.

    ALTER INDEX ... REBUILD PARTITION ...;

     

    주의 :

    • 손상된 블록을 포함하고 있는 기존의 인덱스 세그먼트로부터 새로운 인덱스를 생성하도록 하기 때문에 "ALTER INDEX ..  REBUILD" 명령어를 를 사용하여 파티션이 아닌 손상된 인덱스를 재생성 하지 않는 것이 중요하다.
    "ALTER INDEX ... REBUILD ONLINE"와  "ALTER INDEX ... REBUILD PARTITION ..."

      이전 인덱스 세그먼트로부터 새로운 인덱스를 생성하지 않으며 이렇게는 사용되어 질 수 있다.

    • 새로운 인덱스가 기존의 인덱스 열의 하위 세트인 경우  인덱스 생성 작업은 기존의 인덱스의 데이터를 사용할 수 있다. 따라서 두 개의 손상된 인덱스가 있는 경우 재생성 하기 전에 둘 다 삭제한다.
    • 인덱스를 재생성 할 때 올바른 스토리지 정보를 사용하는지 확인한다.

     

    (5C) 테이블로부터 데이터를 살리기

    손상된 객체가 테이블이나 클러스터 또는 LOB 세그먼트인 경우에는 손상된 블록 안의 데이터는 유실 될 수 있다는 것을 이해해야 한다.

    데이터의 일부는 블록의 헥사 덤프(HEX dump)나 인덱스의 열로부터 살릴 수 있다.

    중요 :

    인덱스로부터 손상된 블록 안의 데이터를 살리는 요구가 있을 수 있기 때문에 요구되는 데이터를 추출하기 전까지 기존의 인덱스를 삭제하는 것은 좋지 않다.

    손상된 블록을 포함하는 테이블 외의 데이터를 얻는 방법에는 여러 가지가 있다. 아래에 설명된 것 중 가장 적절한 방법을 선택한다. 이러한 방법의 목적은 액세스 할 수 있는 테이블 블록에서 가능한 많은 데이터를 추출하는 것이다. 새로운 객체가 올바른 이름으로 생성될 수 있도록 손상된 테이블의 이름을 변경하는 것이 일반적으로 좋은 방법이다.

    예: RENAME <emp> TO <emp_corrupt>;

     

    손상된 블록 주변의 손상된 테이블에서 데이터를 추출하는 방법

    1. 오라클 8.0, 8.1, 및 9i를 포함한 오라클 7.2 이후부터 테이블에 손상된 블록을 건너 뛸 수(SKIP) 있다.

        이것은 데이터를 추출하는 가장 간단한 방법이고 아래에 설명되었다.

        DBMS_REPAIR.SKIP_CORRUPT_BLOCKS 또는 Event 10231  Document 33405.1를 사용하여 데이터를 추출

        IOT 오버플로우 세그먼트에 손상이 있는 경우 아래와 동일한 방법이지만, 인덱스 전체 스캔과 함께 10233 이벤트가 사용되어야 한다.

        "래퍼(wrapper)" 블록이 손상된 것으로 표시된 경우 이 방법만 사용할 수 있다. 예: 블록이 ORA-1578로 보고된 경우.

        문제가 ORA-600 또는 보고되지 않은 기타 오류와 ORA-1578인 경우 엑세스 할 때 ORA-1578이 발생하는 것과 같은 "소프트 손상(soft corrupt)"처럼 문제 블록을 표시하기 위하여 DBMS_REPAIR를 사용할 수 있고 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS을 사용하는 것이 허락된다.

        주의 : "FIX_CORRUPT_BLOCKS" 프로시져에 의해 손상으로 표시된 모든 블록들은 FIX_CORRUPT_BLOCKS의 시간을 통하여 복원 / 복구 작업으로 손상으로 표시될 수 있을 것이다.

        DBMS_REPAIR 사용에 대한 전체 내용은 문서에서 찾을 수 있지만 요약하면 다음의 단계와 같다.

    - 관리자 테이블을 생성하기 위하여 DBMS_REPAIR.ADMIN_TABLES를 사용한다.
    - 문제 블록을 찾기 위하여 DBMS_REPAIR.CHECK_OBJECT를 사용한다.
    - 블록들이 손상되기 이전의 문제 블록에서 좋은 데이터를 얻는다.
    - 손상과 같은 문제 블록을 표시하기 위하여 DBMS_REPAIR.FIX_CORRUPT_BLOCKS를 사용한 다음에는 ORA-1578 신호가 발생할 것이다.
    - 필요하다면 테이블의 손상 블록을 건너 뛰기 위하여 DBMS_REPAIR.SKIP_CORRUPT_BLOCKS를 사용한다.

    2. 오라클 7.1 이후부터 ROWID 범위 검색을 사용할 수 있다.

        이에 대한 구문은 조금 까다롭지만 ROWID 힌트를 사용하여 손상된 블록 주변을 조회 할 수 있다.

        Oracle7과 Oracle8 사이에 변경된 ROWID의 형식 때문에 이에 대한 두 개의 문서가 있다 :

         Using ROWID Range Scans to extract data in Oracle8 and higher Document 61685.1
         Using ROWID Range Scans to extract data in Oracle7 Document 34371.1

    3. 기본 키가 있는 경우 이 인덱스에서 테이블 데이터를 조회할 수 있다.

        또한 다른 인덱스에서 데이터의 일부를 조회할 수 있다.

        속도가 느리고 시간이 많이 걸리지만 일반적으로 오라클 7.0 버전에 필요한 것이다. 이 방법은 Document 34371.1에서 설명되어 있다.(또한 ROWID 범위 스캔을 설명한다.)

    4. 테이블에서 데이터를 살리기 위하여 사용할 수 있는 다양한 프로그램/PLSQL 스크립트가 있다. 설정하고 사용하는 시간이 위의 방법보다 오래 걸릴 수 있지만 ORA-1578 외의 손상 종류에 대해 다양한 방법으로 대처할 수 있다.

        이러한 방법을 지원받을 때 일반적으로 많은 조작이 필요하기 때문에 이 문서들 중 일부는 고객에게 보여지지 않을 수 있다.

        Pro*C 사용이 가능해야 하며 Pro*C 실행파일을 생성하는 방법을 이해해야 한다 :

        Oracle8.1의 SALVAGE.PC      Document 97357.1
        Oracle7의 SALVAGE.PC        Document 2077307.6


        수동적인 상호작업이 필요하다 :
        Oracle7/8의 SALVAGE.SQL    Document 2064553.4
        Oracle7/8의 SALVAGE.SQL    Note:  28308.1

        아래는 Oracle8i 및 9i에서만 가능하다. 목적은 손상된 블록을 표시하고 테이블 데이터를 추출하기 위해 SKIP_CORRUPT 테이블 속성을 를 사용하는 것이다.

        블록 손상을 표시하기 위한 DBMS_REPAIR 사용 Document 68013.1
        LONG 컬럼의 손상을 위해 : LONG 컬럼의 손상이 있는 테이블 재생성하기 Note: 876493.1

    손상된 LOB 세그먼트 블록이 있는 테이블에서 데이터를 추출하는 방법

    LOB 세그먼트에 DBMS_REPAIR를 사용할 수 없다.

    손상된 LOB 블록이 테이블에서 어떠한 행에 의해 참조되지 않는 경우 테이블을 CREATE TABLE as SELECT (CTAS) 또는 익스포트/삭제/임포트 할 수 있다.

    손상된 LOB 블록이 행에 의해 참조되는 경우 문제의 행을 제외하는 WHERE 술어와 함께 조회 또는 익스포트를 할 수 있다.

    경고 :
    문제의 행의 LOB 열 값을 NULL로 업데이트할 수 있고 그럴 경우 조회할 때 ORA-1578이 해결될 것이지만 손상된 블록은 복원되기를 기다릴 것이고 다른 행에 삽입 또는 갱신을 위하여 새로운 LOB를 획득하는 것을 시도하다가 결국 ORA-1578을 발생할 것이며 이는 알려진 행에 손상이 있는 것보다 더 나쁜 상황이 될 수 있다.
    따라서 즉시 테이블을 재생성 하고자 하는 경우에만 LOB 열을 NULL로 설정해야 한다.

     

    손상된 블록 자체에서 데이터를 추출

    손상된 블록 자체는 "손상"이기 때문에 그 블록으로부터 추출된 모든 데이터는 의심하면서 취급해야 한다. 손상된 블록 자체로부터 행을 얻기 위한 주요 방법은 다음과 같다 :

    • 테이블 블록에 대한 오라클 지원으로부터 블록의 내용을 해석하려고 시도하는 도구를 사용할 수 있다.

               HEX 또는 BLOCKDUMP를 읽을 수 있는 형식으로 변경 Note: 47419.1

    • 손상된 블록에 들어있는 ROWID의 위치로 인덱스에 포함된 열의 데이터를 추출하기 위해 테이블에 있는 기존의 인덱스를 사용한다. 이는 위에서 언급한 ROWID 범위 스캔 문서의 끝 부분에 설명되어 있다.

       Oracle8/8i은 Document 61685.1를 참조한다.
       Oracle7은 Document 34371.1를 참조한다.

    • 문제 블록에 데이터를 넣은 원래의 삽입/갱신 구문을 찾기 위해 REDO에 로그마이너를 사용할 수도 있다. 데이터가 블록 안에 실제로 들어갔을 때 주 요인이 여기에  있다.

       예; 행 2를 어제 삽입되었지만 행 1은 5년 전에 삽입되었을 수 있다.

     

    (5D) 손상된 위치를 남겨두기

    손상된 위치를 그대로 남겨 둘 수 있고 보고된 오류를 허용하거나 응용프로그램에서 문제의 행에 접근하는 것을 차단할 수 있다.
    예: 문제 블록 / 행이 자식 테이블인 경우 자식 행에 절대 접근하지 않도록 부모 행을 접근하는 방법을 통해 응용 프로그램에서 접근을 차단할 수 있다. (하지만 계단식 제약조건을 조심해야 한다)

    대량의 데이터에 접근하는 보고서와 기타 작업에 도움이 되지 않을 수 있으므로 조회할 때 블록 오류를 방지하기 위하여 위의 5C 안에 있는 DBMS_REPAIR 방법을 사용하는 것이 바람직할 수 있다. 이와 같이 손상을 표시하고 남겨두는 것은 전체 데이터를 살리거나 예정된 시스템 중단 기간에 시도되어질 복구, 또는 두 번째 (복제) 데이터베이스에 있는 다른 복구 방법을 확인하기 위한 시간을 확보하는 단기적인 해결책을 줄 수 있다. DBMS_REPAIR.FIX_CORRUPT_BLOCKS으로 손상된 블록을 표시하더라도 FIX_CORRUPT_BLOCKS이 실행된 시간을 통해 복구 후에 손상된 블록으로 표시될 수 있는 것을 유의한다. 

    손상된 위치를 그대로 남겨는 것은 빠르게 없어지거나 나중에 삭제될 데이터를 위해 합리적일 수 있다.(예: 오래된 파티션들은 어느 시점에 제거될 수 있는 날짜로 파티션 된 테이블에서)

    LOB 세그먼트에 손상을 남겨두기

    응용프로그램에서 테이블을 재생성 할 수 있는 시간까지 손상된 LOB 열에 위치를 그대로 남겨두는 것은 가능하다.

    위의 "경고" 시나리오를 발생하지 않게 하기 위한 방법 중 하나는 문제의 행을 보호하기 위해 WHERE 술어를 포함한 뷰를 통해 테이블에 접근할 수 있도록 보장하는 것이다.
    예: 테이블 MYTAB ( a number primary key, b clob )은 손상된 LOB 데이터를 가리키는 하나 이상의 행을 가지고 있음을 고려한다.

    ALTER TABLE MYTAB ADD ( BAD VARCHAR2(1) );
    CREATE VIEW MYVIEW AS SELECT a,b FROM MYTAB WHERE BAD is null;

    다른 문제의 행에는 BAD='Y'로 설정한다.

    MYVIEW로 MYTAB에 액세스하는 경우에는 문제 행은 표시되지 않을 것이고 이를 처리할 수 있을 때까지 격리된 손상된 항목은 갱신될 수 없다.

    분명히 이 예제는 해결책을 마련할 시간을 더 줄 수 있으나 일부 응용 프로그램은 이미 유사한 방법을 가지고 있을 수 있고 문제의 행을 숨기는 뷰를 통해서만(또는 RLS 정책을 통해) 데이터에 접근 할 수 있다.

     

    손상된 위치를 남겨 둘 때 경고

    손상된 위치는 남겨둘 수 있으며 RMAN 백업 경고 / 오류 등으로 DBVERIFY를 실행하는 동안 손상된 블록은 여전히 표시될 것임을 알아야 한다.

    이 도구들로부터 확인 될 것을 기대하는 손상, 특히 RMAN(예 : MAX_CORRUPT 설정됨)과 함께 건너 뛰는 것을 기대하는 블록에 대해 주의하여 기록하는 것이 중요하고, 손상이 해결되었을 때 에러의 "허용"을 반드시 삭제한다.

    예: 손상된 위치를 남겨 두고 응용 프로그램 수준에서 문제의 행을 회피한 것에 의해 처리되어 진 손상된 블록을 고려한다.
    RMAN은 백업 중에 손상을 허용하도록 구성 할 수 있다.
    일부 테이블은 재구성 하는 동안 나중에 재생성 된 테이블이다.
    RMAN은 현재 오류가 없어야 하는 것을 반영하기 위해 변경되지 않았다면 RMAN은 나중에 발생하는 다른 손상을 무시할 수 있다.

    테이블 세그먼트 주변의 손상된 블록을 남겨두는 것이 질의로부터 일치하지 않는 결과를 초래할 수 있다는 사실에 주의하는 것이 중요하다.
    예: 다른 결과는 인덱스 스캔인지 아니면 테이블 액세스인지에 따라 SKIP_CORRUPT 설정이 있는 테이블에서 발생할 수 있다.
    다른 보고는 단지 오류일 수 있다.

    손상된 위치를 남겨두지만 DBMS_REPAIR.FIX_CORRUPT_BLOCKS를 사용하면 블록이 손상된 것으로 REDO에 기록하고 이후의 복구 방법을 제한할 수 있는 것을 주의한다.

     

     (5E) 마지막 방법

    (물리적 또는 논리적으로) 대기 설정이 있을 경우 첫 번째를 선택합니다.
    문제 블록의 어떤 종류이든지 하나의 가능한 방법은 데이터베이스 또는 문제의 테이블스페이스를 손상이 발생하기 전의 시점으로 복구하는 것이다. 이 방법의 어려운 점은 처음 문제가 발생했을 때를 알 수 없는 것이다.

    DBVERIFY는 종종 손상으로 인해 복원된 파일을 확인하는 데 사용할 수 있다.
    DBVERIFY에 대한 자세한 내용은 Document 35512.1에서 설명되어 있다. 특히 START= / END= DBV 방법은 복원된 백업 이미지에서 문제의 블록 자체가 정상인지에 아닌지 빠르게 테스트를 하기 위하여 사용할 수 있다.


    이 섹션에서 복구 가능한 몇 가지 최종 방법을 설명한다.
    여기까지 온 경우는 다음 중 하나 이상의 일이 발생했을 것이다:

    • "중요한" 데이터파일을 분실(또는 그 곳에서 손상이 발생)하고 문제의 파일에 대한 좋은 백업이 없다(손상 없이).
    • 아카이브 로그 모드가 아니거나 모든 아카이브 파일이 없다.
    • 전체 복구로도 문제가 재현된다.

    마지막 기회:

    데이터파일의 모든 사본을 잃어버렸지만 여전히 파일이 처음 생성되었을 때부터 아카이브 로그가 존재하는 경우에는 파일을 복구해볼 수 있음을 유의한다.
    예:

    예:
    ALTER DATABASE CREATE DATAFILE '....' [as '...'] ;
    RECOVER DATAFILE '....'
    ALTER DATABASE DATAFILE '....' ONLINE;


    이 시나리오에 있는 경우 아래 내용을 계속하기 전에 이 단계들을 사용하여 데이터파일 복구를 시도한다.

    여기까지 온 경우 현재 시점으로 복구 할 남은 방법은 없다. 인스턴스를 종료를 권장하고 선택된 수행 과정이 실패할 경우를 대비하여 현재 위치로 되돌아 오기 위해 지금 현재의 데이터베이스를 백업한다.(예 : 백업이 비정상인 것을 확인한 경우).

    사용 가능한 일부 개요 방법은 다음과 같다.

    오래된 오프라인 백업으로 되돌리기
    - 예: 노아카이브 로그 모드 인 경우

    오프라인 백업으로 복제 데이터베이스를 구성하기
    - 문제 테이블을 추출(익스포트) 또는 문제의 테이블스페이스를 전송

    일관성이 있는 이전 시점으로 복구

    • 정상 백업과 필요한 모든 아카이브 로그가 필요하다.
    • 모든 파일들은 복원되어야 하고 전체 데이터베이스는  적당한 시점으로 돌아 간다.
    • 복제 데이터베이스에서 시점 복구를 하는 것이 가능할 수 있고 그런 다음 문제의 테이블스페이스를 문제의 데이터베이스로 전송하거나 복제된 데이터베이스로부터 문제의 테이블을 익스포트나 임포트를 한다.


    테이블스페이스에 대한 시간 복구
    - 영향 받는 테이블스페이스만 시간 복구를 수행하는 것이 가능할 수 있다. Document 223543.1와 같이 테이블스페이스 시간 복구에 대해 설명하는 많은 문서가 있다.

    논리적인 익스포트나 복사로 데이터베이스를 재구축하기
    - 데이터베이스의 좋은 논리적 백업이 필요하다.
    - 주의: 이 방법을 위해 데이터베이스는 재생성 해야 한다.
    - 다른 방법과 마찬가지로 재 구축은 복제 데이터베이스에서 문제 테이블의 좋은 이미지를 얻을 수 있다.


    좋은 백업이 있는 경우 DB_BLOCK_CHECKING=TRUE로 돌아가는 것은 잘못된 시작부분인 첫 번째 문제 시점을 찾는데 도움이 될 수 있다. 
    복구 방법을 조사하는 동안 문제의 데이터베이스를 정지하는 것은 일반적으로 필요가 없다.

    예: 다른 인스턴스에서 얼만큼의 시간이 돌아가야 되는지 조사하기 위해 완전히 다른 위치 또는 장비로 시스템 테이블스페이스와 문제 테이블스페이스의 데이터파일만 복원할 수 있다.

    오라클9i에서는 방법을 찾는 동안 백업을 복원하는 시간을 줄이기 위해 "평가 복구" 방법을 사용할 수 있다.


    반응형
    Posted by [PineTree]
    ORACLE/ADMIN2014. 3. 23. 22:45
    반응형

    04 커서공유


    (1) 커서란?

    공유 커서 (shared cursor) : 라이브러리 캐시에 공유돼 있는 Shared SQL Area
    세션 커서 (session cursor) : Private SQL AREA에 저장된 커서
    애플리케이션 커서 (application cursor) : 세션 커서를 가리키는 핸들

    그림 7

    라이브러리 캐시에 공유돼 있는 커서를 실행할 때는 우선 PGA 영역에 메모리를 할당
    Private SQL area 라고 하는데 , Persistent Area 와 Runtime Area로 나뉜다.
    Shared SQL Area를 읽어 커서를 실행하는 데 필요한 정보들을 Private SQL Area에 담고,
    공유 커서를 가리키는 포인터를 유지한다.그리고 커서의 상태정보도 관리한다.
    커서 를 실행하기 위한 이런 준비과정을 "커서를 오픈한다" 고 표현하고,
    PGA에 저장된 커서 정보(즉,파싱된 SQL문과 문장을 수행하능데 필요한 기타 정보)를 또
    한 '커서' 라고부른다.

    PGA에 있는 커서를 핸들링하려면 JAVA, VB, Pro*C, PL!SQL 같은 클라이언트 애플리케이션에도
    리소스를 할당

    (2) 커서 공유

    ######################
    커서 공유 테스트
    ######################
    
    -- sys유저 접속
    SQL> grant select_catalog_role to scott;
    Statement Processed.
    
    SQL> alter system flush shared_pool;
    Statement Processed.
    
    -- SCOTT유저 접속
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL> select sql_id, parse_calls, loads, executions, invalidations 
          , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
    from v$sql 
    where sql_text like '%cursor test%' 
    and sql_text not like '%v$sql%';
    
    SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
    ------------- ----------- --------- ---------- ------------- --------- 
    896pksq7c53f2           1         1          1             0         0
    
    1 rows selected.
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL> select sql_id, parse_calls, loads, executions, invalidations 
          , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
    from v$sql 
    where sql_text like '%cursor test%' 
    and sql_text not like '%v$sql%';
    
    SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
    ------------- ----------- --------- ---------- ------------- --------- 
    896pksq7c53f2           3         1          3             0         0
    
    1 rows selected.
    
    
    • parse_calls: 라이브러리 캐시에서 SQL 커서를찾으려는요청 횟수
    • loads: 하드파싱을 거친 SQL 실행계획을 라이브러리 캐시에 적재한 횟수
    • executions : SQL을 수행한 횟수
    • invalidations : 커서가 무효화된 횟수. 커서가 참조하고 있는 오브젝트에 중요한 변
      화가일어났음을의미함
    #####################################
    다른세션 접속후 커서공유 테스트
    #####################################
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL> select sql_id, parse_calls, loads, executions, invalidations 
          , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
    from v$sql 
    where sql_text like '%cursor test%' 
    and sql_text not like '%v$sql%';
    
    SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
    ------------- ----------- --------- ---------- ------------- --------- 
    896pksq7c53f2           5         1          5             0         0
    
    1 rows selected.
    
    

    다른 세션에서 같은 SQL을 수행할 때도 이전 세션에서 적재한 커서를 재사용했음을
    알수있다.

    ###################################
    통계 재생성후 커서공유 테스트
    ###################################
    
    SQL> execute DBMS_STATS.GATHER_TABLE_STATS  
    (ownname => USER, tabname => 'EMP' 
    ,no_invalidate => FALSE 
    );
    
    PL/SQL executed.
    SQL Execution Time > 00:00:05.367
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL Execution Time > 00:00:00.062
    Total Elapsed Time > 00:00:00.062
    
    SQL> select /* cursor test */ empno, ename, job, sal, deptno 
    from emp 
    where empno = 7788;
    
    EMPNO ENAME      JOB       SAL       DEPTNO 
    ----- ---------- --------- --------- ------ 
     7788 SCOTT      ANALYST        1000     20
    
    1 rows selected.
    
    SQL Execution Time > 00:00:00.062
    Total Elapsed Time > 00:00:00.062
    
    -------------------------[Start Time: 2014/03/04 18:39:12]-------------------------
    SQL> select sql_id, parse_calls, loads, executions, invalidations 
          , decode(sign(invalidations), 1, (loads-invalidations),0) reloads 
    from v$sql 
    where sql_text like '%cursor test%' 
    and sql_text not like '%v$sql%';
    
    SQL_ID        PARSE_CALLS LOADS     EXECUTIONS INVALIDATIONS RELOADS   
    ------------- ----------- --------- ---------- ------------- --------- 
    896pksq7c53f2           2         2          2             1         1
    
    1 rows selected.
    
    SQL Execution Time > 00:00:00.031
    Total Elapsed Time > 00:00:00.047
    
    

    쿼리를 다시 수행한 후에 v$sql을 다시 조회해 보면, 적재 횟수가 아래처럼 2로 증가한
    것을볼수있다.

    라이브러리 캐시에 있는 커서틀이 여러 세션에 의해 공유되면서 반복 재사용되는 것
    공유된 커서를 사용할 때는 최적화 및 Row-Source Generation 단계를 생략하고
    곧바로 실행 단계로 넘어가므로 보다 효율적이고 빠르게 SQL을 수행한다

    커서가 공유되려면 커서를 식별하는 키 값이 같아야 함
    -> 라이브러리 캐시에서 커서를 식별하기 위해 시용되는 키 값은 'SQL 문장 그 자체'
    -> SQL문을 구성하는 전체 문자열이 이름 역할을 한다는 뜻
    -> SQL_ID와 SQL FULLTEXT는 1:1로 대응
    SQL문 중간에 작은 공백문자 하나만 추가하더라도 서로 다른 SQL 문장으로 인식해 새로운
    SQL_ID를발급받게 된다. 즉 커서가 공유되지 않는다.

    (3) Child 커서를 공유하지 못하는 경우

    8QL마다 하나의 Parent 커서를 가지며, Child 커서는 여러 개일 수 있다.
    실제 수행에 필요한 정보는 Child 커서에 담기므로 적어도 한 개의 Child 커서를 갖는다.
    v$sqlarea는 Parent 커서 정보를 보여주고36) ' v$sql은 Child 커서 정보를 보여준다.
    아래는 SC0TT과 HR 스키마 각각에 EMP 테이블을 만들고 각 계정으로 로그인 해서
    select * from emp 쿼리를 수행한 후에 v$sqlarea와 v$sql을 쿼리했을 때의 결과를 보
    이고 있다.

    ##########################
    자식커서의 공유 테스트
    ##########################
    
    C:\WINDOWS\system32>sqlplus "/as sysdba"
    
    
    SQL> conn /as sysdba
    연결되었습니다.
    SQL> create table hr.emp as select * from scott.emp;
    
    테이블이 생성되었습니다.
    
    SQL> alter system flush shared_pool;
    
    시스템이 변경되었습니다.
    
    SQL> conn scott/tiger
    연결되었습니다.
    SQL> select * from emp where empno=7698;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
          7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
    
    SQL> conn hr/hr
    연결되었습니다.
    SQL> select * from emp where empno=7698;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
          7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
    
    
    == v$sqlarea는 부모커서를 확인
    SQL>  conn /as sysdba
    연결되었습니다.
    SQL> select sql_id, version_count, optimizer_mode, address, hash_value
      2  from v$sqlarea
      3  where sql_text like 'select * from emp where%'
      4  and sql_text  not like 'v$sql';
    
    SQL_ID        VERSION_COUNT OPTIMIZER_ ADDRESS  HASH_VALUE
    ------------- ------------- ---------- -------- ----------
    5tq0u8y4zd3ta             2 ALL_ROWS   3D9C5BFC 2314637098
    
    
    == v$sql는 자식커서를 확인
    SQL> select sql_id, child_number, optimizer_mode, address, hash_value, parsing_user_id
      2  from v$sql
      3  where sql_text like 'select * from emp where%'
      4   and sql_text  not like 'v$sql';
    
    SQL_ID        CHILD_NUMBER OPTIMIZER_ ADDRESS  HASH_VALUE PARSING_USER_ID
    ------------- ------------ ---------- -------- ---------- ---------------
    5tq0u8y4zd3ta            0 ALL_ROWS   3D9C5BFC 2314637098              84
    5tq0u8y4zd3ta            1 ALL_ROWS   3D9C5BFC 2314637098              85
    
    
    == v$sqlarea 에 동일문장의 버전이 몇개인지 볼수 있다.
    select * from v$sqlarea order by version_count desc;
    
    

    하나의 SQL문장이 여러개 Child 커서를 갖게 되는 대표적인 이유
    1. SQL에서 참조하는 오브젝트명이 같지만 SQL을 실행한 사용자에 따라 다른 오브젝트를 가리킬때
    2. 참조 오브젝트가 변경돼 커서가 무효화되면 이후 그 커서를 처음 사용하려는 세션에
    의해 다시 하드파싱돼야 하는데 특정 세션이 아직 기존 커서를 사용 중(Pin)일 때
    3. 옵티마이저 모드를 비롯해 옵티마이저 관련 파라미터가 다를 때
    4. 입력된 바인드 값의 길이가 크게 다를 때
    5. NLS 파라미터를 다르게 설정했을 때
    6. SQL 트레이스를활성화했을때

    해당 딕셔너리를 참조해라. ====> V$SQL_SHARED_CURSOR

    SQL> conn scott/tiger
    연결되었습니다.
    SQL> conn /as sysdba
    연결되었습니다.
    SQL> alter system flush shared_pool;
    
    시스템이 변경되었습니다.
    
    SQL> conn scott/tiger
    연결되었습니다.
    SQL> alter session set optimizer_mode=first_rows;
    
    세션이 변경되었습니다.
    
    SQL> select * from emp where empno=7698;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
          7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
    
    SQL> alter session set optimizer_mode=all_rows;
    
    세션이 변경되었습니다.
    
    SQL> select * from emp where empno=7698;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- -------- ---------- ---------- ----------
          7698 BLAKE      MANAGER         7839 81/05/01       2850                    30
    
    
    SQL> conn /as sysdba
    연결되었습니다.
    SQL> select sql_id, version_count, optimizer_mode, address, hash_value
      2  from v$sqlarea
      3  where sql_text like 'select * from emp where%'
      4  and sql_text  not like 'v$sql';
    
    SQL_ID        VERSION_COUNT OPTIMIZER_ ADDRESS  HASH_VALUE
    ------------- ------------- ---------- -------- ----------
    5tq0u8y4zd3ta             2 ALL_ROWS   3D9C5BFC 2314637098
    
    
    
    SQL> select child_number, child_address, optimizer_mode_mismatch, optimizer_mismatch
      2  from V$SQL_SHARED_CURSOR
      3  where SQL_ID = '5tq0u8y4zd3ta'
      4  and ADDRESS  = '3D9C5BFC';
    
    CHILD_NUMBER CHILD_AD O O
    ------------ -------- - -
               0 37DF4684 N N
               1 37FF5A94 Y N
    
    
    SQL> select *
      2  from V$SQL_SHARED_CURSOR
      3  where SQL_ID = '5tq0u8y4zd3ta'
      4  and ADDRESS  = '3D9C5BFC';
    
    SQL_ID        ADDRESS  CHILD_AD CHILD_NUMBER U S O O S L F E B P I S T A B D L T B I I R L I O E M U
     T N F A I T D L D B P C S C P T M B M R O P M F L P L A F L R L H P B
    ------------- -------- -------- ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    5tq0u8y4zd3ta 3D9C5BFC 37DF4684            0 N N N N N N N N N N N N N N N N N N N N N N N N N N N N
     N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
    5tq0u8y4zd3ta 3D9C5BFC 37FF5A94            1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N
     N N N N N N N N N N N N N N N N N N N N Y N N N N N N N N N N N N N N
    
    

    Version Count 수치가 높은 SQL 일수록 커서를 탐색하는 데 더 많은 시간을 소비하므
    로 library cache 래치에 대한 경합 발생 가능성을 증가시킨다.

    v$sql_shared_cursor 다이나믹 뷰는 새로운 Child 커서가 왜 기존 Child 커서와 공유
    못하는지 확인

    (4) Parent 커서를 공유하지 못하는 경우

    1. 공백 문자 또는 줄바꿈
    SELECT * FROM CUSTOMER;
    SELECT *   FROM CUSTOMER;
    2 . 대소문자구분
    SELECT * FROM CUSTOMER;
    SELECT * FROM Customer;
    3. 태이블 Owner 명시
    SELECT * FROM CUSTOMER;
    SELECT * FROM HR.CUSTOMER;
    4. 주석 (Comment)
    SELECT * FROM CUSTOMER;
    SELECT /* 주석문 */ * FROM CUSTOMER;
    5. 용티마이져 힌트 사용
    SELECT * FROM CUSTOMER;
    SELECT /*+ all_rows */ * FROM CUSTOMER;
    6. 조건 절 비교값
    SELECT * FROM CUSTOMER WHERE CUST_ID = '0000001';
    SELECT * FROM CUSTOMER WHERE CUST_ID = '0000002';
    이 외에도 더 다양한 케이스가 있을 것이다. 1. 2. 4번은 그 실행계획이 100% 같다.
    
    

    그럼에도 문자열을 조금 다르게 기술했다는 이유 때문에 서로 다른 SQL로서 각각
    하드파싱을 일으카고 서로 다른 공간을 차지하면서 Shared Pool을 낭비하게 된다. 이런
    비효율을 줄이고 공유 가능한 형태로 SQL을 작성하려면 개발 초기에 SQL 작성 표준을
    정해 이를 준수하도록 해야 한다.

    5번은 의도적으로 실행계획을 달리 가져가려는 것이므로 논외로 하고 라이브러리 캐시
    효율과 직접 관련이 큰 것은 6번 같은 패턴이다. 즉 조건절에 바인드 변수를 사용하지 않
    고 서로 다른 Literal 값으로 문자열을 대체하는 경우다.
    만약 OLTP성 업무를 처리하는 애플리케이션에서 6번과 같은 패턴으로 SQL을 개발한
    다변 결코 좋은 성능을 보장받을 수 없다. 개별 쿼리 성능으로 보면 잘 느끼지 못하지만
    동시 트랜잭션이 몰리는 peak 시간대에 시스템을 장애 상황으로 몰고 가는 주범이다.

    ==================================================================================================================
    공유풀은 힙(heap)으로 불리는 OS메모리 공간으로 구성됨.
    힙(heap)은 헤더와 하나이상의 메모리익스텐트로으로 구성됨.
    메모리익스텐트는 지속적으로 할당과 반납이 반복되며 여러개 작은조각으로 나누어짐.
    메모리 영역이 작은단위로 나누어 지는 것을 공유풀단편화(FRAGMENTATION)이라 함.
    단편화로 인해 쪼개진 영역은 청크라고 불리며 프리리스트에 의해 관리됨.
    한번 사용된 청크는 다시 프리리스트에 등록되기 전까지 공유풀 LRU리스트에서 관리됨
    LRU알고리즘을 이용하여 청크의 재사용률을 높이기 위해서임.

    공유풀에 메모리 할당과정
    1. 새로운 SQL에 대해 파스 수행하려면 힙영역 새로운 빈공간 할당받아야함.
    2. 프리리스트에서 필요한 크기의 프리청크 서칭
    3. 프리리스트 서칭후 있으면 힙영역 할당. 없으면 LRU리스트 사용가능 청크를 서칭
    4. LRU리스트에도 없으면 4031에러 발생후 SQL파스 실패

    예> SQL파스를 위해 256바이트가 필요할�
    1. 쉐어드풀 래치획득후 프리리스트로 부터 256바이트의 청크를 검색.

    • 이과정에서 래치를 획득하지 못하면 latch:shared pool 대기 이벤트를 발생시키며 획득가능할때까지 대기.
      2. 256바이트의 프리청크를 찾았다면 해당 청크를 익스텐트에 할당.
    • 이과정에서 256바이트의 프리청크가 없어서 찾지 못했다면 더큰크기의 프리청크를 검색
      3. 400바이트의 프리청크를 찾았다면 필요한 크기의 256바이트와 144바이트의 크기로 쪼갬.
      256바이트 청크를 익스텐트에 할당. 144바이트의 청크는 프리리스트에 등록
    • 이과정에서 256바이트 보다 더 큰 프리청크를 찾지 못했다면 공유풀 LRU리스트로 부터 핀이 해제된 청크중 256바이트 보다 큰 청크를 검색 후 프리리스트 등록
      4. 공유풀LRU리스트 검색시 필요한 크기의 청크를 확인 못할시 4031에러와 SQL파스 실패

    프리리스트에서 프리청크를 검색후 할당받기까지 모든단계에서 shared pool 래치를 할당 받아야 한다.
    청크의 할당 해제가 빈번히 발생 한다면 청크는 더욱 작게 쪼개져 관리되어야 할 청크의 수가 증가 한다.
    프리리스트를 검색하는 시간을 증가시키고 쉐어드풀 레치에 대한 경합을 증가시켜 성능저하를 유발 하며
    4031에러를 발생시킨다.
    ==================================================================================================================

    05 바인드 변수의 중요성

    바인드 변수 사용에 따른 효과는 아주 분명
    커서를 많이 생성하지 않고 하나를 반복 재사용하므로 메모리 사용량과 파싱 소요 시간을 불인다
    궁극적으로 시스템전반의 메모리와 CPU사용률을 낮춰 데이터베이스 성능과 확장성을 높이는데 기여
    특히 동시 사용자 접속이 많을 때는 그 영향력이 절대적이다

    #################################
    바인드 변수 사용의 필요성 테스트
    #################################
    
    SQL> create table t as select * from dba_objects;
    
    테이블이 생성되었습니다.
    
    SQL> update t set object_id = rownum;
    
    72471 행이 갱신되었습니다.
    
    SQL> commit;
    
    커밋이 완료되었습니다.
    
    SQL> create unique index t_idx on t (object_id);
    
    인덱스가 생성되었습니다.
    
    SQL> analyze table t compute statistics;
    
    테이블이 분석되었습니다.
    
    
    
    set timing on 
    declare 
      type rc is ref cursor; 
      l_rc rc;
      l_object_name t.object_name%type;
    begin 
      for i in 1..20000
      loop
       open l_rc for
        'select /* TEST1 */ object_name
         from t
         where object_id = :x' using i;
       fetch l_rc into l_object_name;
       close l_rc;
      end loop;
    end;
    /
    SQL> set timing on
    SQL> declare
      2    type rc is ref cursor;
      3    l_rc rc;
      4    l_object_name t.object_name%type;
      5  begin
      6    for i in 1..20000
      7    loop
      8     open l_rc for
      9      'select /* TEST1 */ object_name
     10       from t
     11       where object_id = :x' using i;
     12     fetch l_rc into l_object_name;
     13     close l_rc;
     14    end loop;
     15  end;
     16  /
    
    PL/SQL 처리가 정상적으로 완료되었습니다.
    
    경   과: 00:00:00.79
    SQL>
    
    SQL> col sql_text format a50
    SQL> select sql_text,loads,parse_calls,executions,fetches
      2  from v$sql
      3  where sql_text like '%TEST1%'
      4  and sql_text not like '%v$sql%'
      5  and sql_text not like 'declare%';
    
    SQL_TEXT                                                LOADS PARSE_CALLS EXECUTIONS    FETCHES
    -------------------------------------------------- ---------- ----------- ---------- ----------
    select /* TEST1 */ object_name      from t      wh          1       20000      20000      20000
    ere object_id = :x
    
    
    경   과: 00:00:00.03
    
    
    declare 
      type rc is ref cursor; 
      l_rc rc;
      l_object_name t.object_name%type;
    begin 
      for i in 1..20000
      loop
       open l_rc for
        'select /* TEST2 */ object_name
         from t
         where object_id = '||i ;
       fetch l_rc into l_object_name;
       close l_rc;
      end loop;
    end;
    /
    
    SQL> declare
      2    type rc is ref cursor;
      3    l_rc rc;
      4    l_object_name t.object_name%type;
      5  begin
      6    for i in 1..20000
      7    loop
      8     open l_rc for
      9      'select /* TEST2 */ object_name
     10       from t
     11       where object_id = '||i ;
     12     fetch l_rc into l_object_name;
     13     close l_rc;
     14    end loop;
     15  end;
     16  /
    
    PL/SQL 처리가 정상적으로 완료되었습니다.
    
    경   과: 00:00:07.54
    SQL>
    
    
    select sql_text,loads,parse_calls,executions,fetches
    from v$sql
    where sql_text like '%TEST2%'
    and sql_text not like '%v$sql%'
    and sql_text not like 'declare%';
    
    
    select /* TEST2 */ object_name      from t      wh          1           1          1          1
    ere object_id = 19110
    
    select /* TEST2 */ object_name      from t      wh          1           1          1          1
    ere object_id = 18922
    
    select /* TEST2 */ object_name      from t      wh          1           1          1          1
    ere object_id = 18476
    
    select /* TEST2 */ object_name      from t      wh          1           1          1          1
    ere object_id = 19948
    
    select /* TEST2 */ object_name      from t      wh          1           1          1          1
    ere object_id = 19051
    
    
    2091 개의 행이 선택되었습니다.
    
    경   과: 00:00:01.25
    
    

    바인드 변수 사용원칙을 잘 지커지 않으면 라이브러리캐시 경합때문에 시스템 정상가동이
    어려운 상황에 직면할 수 있다. cursor_sharing 파라미터를 변경 긴급처방

    06 바인드 변수의 부작용과 해법

    바인드 변수를 사용하면 최초 수행할 때 최적화를 거친 실행계획을 캐시에 적재하고,
    실행시점에는 그것을 그대로 가져와 값을 다르게 바인딩하면서 반복 재사용하게 된다.
    여기서, 변수를 바인딩하는 시점이 (최적화 시점보다 나중인) 실행시점이라는 사실을 아
    는 것이 중요하다. 즉, SQL을 최적화하는 시점에 조건절 컬럼의 데이터 분포도를 활용하
    지 못하는 문제점을 갖는다.

    (1) 바인드 변수 Peeking

    오라클은 9i부터 바인드 변수 Peeking 기능을 도입
    SQL이 첫 번째 수행되면서 하드파싱될 때 함께 딸려 온 바인드 변수 값을 살짝 훔쳐 보고
    그 값에 대한 컬럼 분포를 이용해 실행계획을 결정
    문제점
    잘못 수립된 실행계획 때문에 느린 애플리케이션도 문제지만 시스템 운영자 입장에서는
    자주 실행계획이 바뀌어 어제와 오늘의 수행속도가 급격히 달라지는 현상

    (2) 적응적 커서 공유(Adaptive Cursor Sharing)

    오라클 11g도입된 이 기능이 작동하려면 기본적으로 조건절 컬럼에 히스토그램이 생성돼 있어야 한다.
    그 상태에서,옵티마이저가 바인드 변수 값에 따라 실행계획을 달리 가져갈 필요가 있다고 판단면
    SQL커서에 대해서 이 기능이 활성화
    문제점
    새로운 실행계획을 만들지 않는다
    기존 커서의 실행계획을 그대로 사용해보고 성능이 나쁘다고 판단되면 모드를 전환

    (3) 입력 값에 따라 SQL 분리

    인텍스 액세스 경로(access Path)로서 중요하고 조건절 컬럼의 데이터 분포가 균일하지 않
    은 상황에서 바인드 변수 시용에 따른 부작용을 피하려면 바인딩 되는 값에 따라 실행계
    획을 아래와 같이 분리하는 방안을 고려해야 한다.

    select /*+ full(a) */ *
    from 아파트매물 a
    where :city in ('서울','경기')
    and 도시 = :city
    union all
    select /*+ index(a) */ *
    from 아파트매물 a
    where :city not in ('서울','경기')
    and 도시 = :city;
    

    문제점
    union all을 이용해 SQL을 길게 작성하면 Parse 단계의 CPU 사용률을 높임.
    -라이브러리 캐시는 문장을 저장함
    -Syntax를 체크함
    -파싱트리를 만들어 Semantic 체크도함
    union all을 이용해 SQL을 길게 작성하면 Execute단계에서도 CPU 사용률을 높임.
    -I/O를 일으키지 않을 뿐 실제실행은 일어나기 때문

    (4) 예외적으로,Literal 상수값 사용

    게다가 배치 프로그램이나 정보계 시스템에서 수행되는 SQL은 대부분 Long
    Running 쿼리이므로 파싱 소요시간이 쿼리 총 소요시간에서 차지하는 비중에 매우 낮
    고, 사용빈도도낮아하드파싱에 의한라이브러리 캐시 부하를크게 염려할펼요가없다.

    07 세션 커서 캐싱

    세션 커서 (session cursor)란
    Shared Pool에 위치한 공유 커서 (shared cursor)를 실행하려고 PGA로 인스턴스화한 것

    쿼리를 수행한 후에 커서를 닫으면,
    세션 커서를 위해 할당된 메모리는 물론 공유 커서를 가리키는 포인터까지바로 해제,
    그 다음에 같은 SQL을 수행하면 커서를 오픈하기 위한 라이브러리 캐시 탐색작업을 다시 해야 함.

    세션 커서 캐싱(Session Cursor Cache)란
    오라클은 자주 수행하는 SQL에 대한 세션 커서를 세션 커서 캐시 (Session cursor Cache)에 저장

    커서를 닫는 순간 해당 커서의 Parse Call 횟수를 확인해 보고 그 값이 3보다 크거나 같으면,
    세션 커서를 세션 커서 캐시로 옮긴다. 세션 커서 캐시에는 SQL 텍스트와 함께 공유 커서를
    가리키는 포인터를 저장
    커서는 닫힌 상태지만 공유 커서에 대한 참조를 유지하기 때문에 다음 수행 시 더 빨리
    커서를 오픈(자주 수행되는 SQL문에 의해 발생하는 라이브러리 캐시 부히를 경감)

    즉,
    SQL문을 파싱해서 구문을 분석하고,
    라이브러리 캐시에서 커서를 찾는 과정에서 소모되는 CPU 사용량을 줄일 수 있음은 물론,
    소프트 파싱 과정에 발생하는 래치 요청 횟수를 감소시키는 효과

    세션 커서 캐시 내에서도 LRU 알고리즘을 시용함으로써 새로운 엔트리를 위한 공간이 필요할 때마다
    기존 세션 커서 중 사용 빈도가 낮은것부터 밀어낸다.

    session_cached_cursors는 얼마나 많은 세션 커서를 캐싱할지를 지정하는 파라미터
    로서 , 이 값을 O보다 크게 설정하면 Parse Call이 발생할 때마다 라이브러리 캐시를 탐색
    하기 전에 세션 커서 캐시를 먼저 살펴본다.

    • users_opening: 공유 커서를 참조하고 있는 세션 커서의 수를 보여준다. 수행을 마
      쳐 커서 를 닫았더라도 참조를 버리지 않은 채 세션 커서 캐시로 옮겨진다면 여기에
      집계된다 .
    • users_executing : 해당 SQL을 현재 실행 중인, 즉 커서가 열려있는 세션 커서의
      수를 보여준다. DML일 때는 수행을 마칠 때 커서가 자동으로 닫히지만 select문은
      EOF(End of Fetch)에 도달했을 때 커서가 닫힌다
    SQL> alter session set session_cached_cursors = 10;
    
    세션이 변경되었습니다.
    
    SQL> alter system flush shared_pool;
    
    시스템이 변경되었습니다.
    
    SQL> select * from scott.emp where empno=7788 ;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
    ---------- ---------- --------- ---------- -------- ---------- ----------
        DEPTNO
    ----------
          7788 SCOTT      ANALYST         7566 87/04/19       3000
            20
    
    
    SQL> select parse_calls, users_opening, users_executing from v$sql
      2  where sql_text = 'select * from scott.emp where empno=7788 ';
    
    PARSE_CALLS USERS_OPENING USERS_EXECUTING
    ----------- ------------- ---------------
              1             0               0
    
    SQL> select * from scott.emp where empno=7788 ;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
    ---------- ---------- --------- ---------- -------- ---------- ----------
        DEPTNO
    ----------
          7788 SCOTT      ANALYST         7566 87/04/19       3000
            20
    
    
    SQL> select parse_calls, users_opening, users_executing from v$sql
      2  where sql_text = 'select * from scott.emp where empno=7788 ';
    
    PARSE_CALLS USERS_OPENING USERS_EXECUTING
    ----------- ------------- ---------------
              2             0               0
    
    SQL> select * from scott.emp where empno=7788 ;
    
         EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM
    ---------- ---------- --------- ---------- -------- ---------- ----------
        DEPTNO
    ----------
          7788 SCOTT      ANALYST         7566 87/04/19       3000
            20
    
    
    SQL> select parse_calls, users_opening, users_executing from v$sql
      2  where sql_text = 'select * from scott.emp where empno=7788 ';
    
    PARSE_CALLS USERS_OPENING USERS_EXECUTING
    ----------- ------------- ---------------
              3             1               0
    
    

    세번 일어나는 순간 users_opening값이 0에서 1로 바뀐 것 확인
    세번째 수행되기 전까지는 users_opening값이 0인것
    커서를 닫자마자 공유커서에 대한 참조까지 곧바로 해제

    users_opening에서 'open' 의 의미가 실제 커서가 열려 있음을 의미하는 것이 아님을
    기억할 필요가 있다. 커서는 닫힌 상태지만 공유 커서에 대한 참조를 유지하기 때문에 다
    음수행 시 더 빨리 커서를오픈할수있는것이다.

    create table t(x number);
    
    select a.name, b.value  
    from   v$statname a, v$mystat b 
    where  a.name in ('session cursor cache hits','parse count (total)')
    and    b.statistic# = a.statistic#; 
    
    
    alter session set session_cached_cursors=0;
    
    declare 
       i number; 
     begin 
       for i in 1..10000 
        loop 
        execute immediate 'insert into t values('||mod(i,100)||')'; 
        end loop; 
     
     commit; 
    end; 
    /  
    
    
    select a.name, b.value  
    from   v$statname a, v$mystat b 
    where  a.name in ('session cursor cache hits','parse count (total)')
    and    b.statistic# = a.statistic#; 
    
    alter session set session_cached_cursors=100;
    
    declare 
       i number; 
     begin 
       for i in 1..10000 
        loop 
        execute immediate 'insert into t values('||mod(i,100)||')'; 
        end loop; 
     
     commit; 
    end; 
    /  
    
    
    select a.name, b.value  
    from   v$statname a, v$mystat b 
    where  a.name in ('session cursor cache hits','parse count (total)')
    and    b.statistic# = a.statistic#; 
    
    출처: http://wiki.gurubee.net/pages/viewpage.action?pageId=28115145
    


    반응형
    Posted by [PineTree]
    ORACLE/ADMIN2013. 8. 6. 10:45
    반응형
    (로그 위치를 변경하지 않았다면)
    $ORACLE_HOME/network/log 디렉토리에 보면, 
    listener.log 가 꾸준히 또는 급격하게 사이즈가 증가할 경우가 있다.  

    이럴 경우, 

    lsnrctl  ->

    lsnrctl> set current_listener <리스너명> --구성된 리스너명이 Listener 가 아닌 경우, 지정해 줌.

    lsnrctl> set log_status off -- listener.log 파일에 로그를 기록하지 않는다.  

    lsnrctl> set log_status on -- listener.log 파일에 로그를 기록.

    set log_status off 로 변경하고, 파일 제거 또는 백업하고 listener.log 파일 생성 (생성하지 않아도 자동 생성) 
    출처 - http://jmkjb.tistory.com/entry/ListenerlogManage
     
    명령어는 lnsrctl start /stop/ status 사용
    서비스이름 확인후 tnsping service_name //host ip주소확인 상태확인
    반응형
    Posted by [PineTree]
    ORACLE/ADMIN2013. 7. 25. 07:33
    반응형

    오라클

    srvctl stop home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac1


    root로
    cd /app/11g/grid/crs/install
    ./rootcrs.pl -unlock

    oracle로

    /app/11g/grid/OPatch/opatch napply -oh /app/11g/grid/ -local /home/oracle/16459322/

    /app/11g/grid/OPatch/opatch apply -oh /app/11g/grid/ -local /home/oracle/16056267

    /home/oracle/16459322/custom/server/16459322/custom/scripts/prepatch.sh -dbhome /app/oracle/11g/db

    DB패치 oracle로
    opatch napply -oh /app/oracle/11g/db -local /home/oracle/16459322/custom/server/16459322

    opatch apply -oh /app/oracle/11g/db -local /home/oracle/16056267

    /home/oracle/16459322/custom/server/16459322/custom/scripts/postpatch.sh -dbhome /app/oracle/11g/db

    root로

    cd /app/11g/grid/rdbms/install/

    ./rootadd_rdbms.sh

    cd /app/11g/grid/crs/install

    ./rootcrs.pl -patch

    oracle로

    srvctl start home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac1

    ###########################################################################################################################

    ###########################################################################################################################

    2번 노드에서

     

    oracle유저로
    srvctl stop home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac2


    root로
    cd /app/11g/grid/crs/install
    ./rootcrs.pl -unlock

    oracle로

    /app/11g/grid/OPatch/opatch napply -oh /app/11g/grid/ -local /home/oracle/16459322/

    /app/11g/grid/OPatch/opatch apply -oh /app/11g/grid/ -local /home/oracle/16056267

    /home/oracle/16459322/custom/server/16459322/custom/scripts/prepatch.sh -dbhome /app/oracle/11g/db

    DB패치 oracle로
    opatch napply -oh /app/oracle/11g/db -local /home/oracle/16459322/custom/server/16459322

    opatch apply -oh /app/oracle/11g/db -local /home/oracle/16056267

    /home/oracle/16459322/custom/server/16459322/custom/scripts/postpatch.sh -dbhome /app/oracle/11g/db

    root로

    cd /app/11g/grid/rdbms/install/

    ./rootadd_rdbms.sh

    cd /app/11g/grid/crs/install

    ./rootcrs.pl -patch

    oracle로

    srvctl start home -o $ORACLE_HOME -s /app/oracle/state_file.state -n rac2

    반응형

    'ORACLE > ADMIN' 카테고리의 다른 글

    04 커서공유  (0) 2014.03.23
    [ORACLE]Listener.log 관리  (0) 2013.08.06
    shrink 대상 선정 및 shrink작업  (1) 2013.06.03
    (10gR2)Full UNDO tablespace_언두 메커니즘  (0) 2013.05.19
    10g SYSAUX tablespace 크기 줄이기  (0) 2013.03.04
    Posted by [PineTree]
    ORACLE/ADMIN2013. 6. 3. 17:09
    반응형

    SHRINK SPACE는 오라클10g부터 지원하는 기능으로,

    세그먼트의 데이터 조각모음(ONLINE Reorg. 효과) 기능.

     

    -----------------------------------------------------

    1. SHRINK 작업을 수행하기 위한 주요 환경 및 주의할 점
    -----------------------------------------------------

       1) 오라클 10g 이상(Init.ora parameter 'Compatible' must be >=10.0)
       2) 세그먼트 관리방식이 반드시 ASSM(Auto Segment Space Managed) Tablespace이어야 함
       3) 약 20여건씩 INSERT/DELETE하고 COMMIT하는 방식으로 SHRINK함
       4) 개별 ROW 또는 데이터 BLOCK에 대한 LOCK(ENQUEUE)이 사용
       5) FBI(Function-Based Index)를 SHRINK하는 경우
          오류 발생하므로 FBI를 DROP한 다음 작업하고
          SHRINK작업이 완료된 후 다시 생성
       6) DML TRIGGER를 발생시키지 않음(ROWID based TRIGGER는 작업 전에 DISABLED 필요)
       7) DML 작업은 세그먼트 SHRINK 중 수행 가능하나, parallel DML을 수행될 수 없음 
       8) 세그먼트를 SHRINK 시키는 특정 단계(HWM을 조정하는 단계)에서 세그먼트에

          exclusive 모드로 짧은 시간동안 LOCK(TM)이 걸림

     

    -----------------------------------------------------

    2. SHRINK 작업 방법 (순서 1]~6])
    -----------------------------------------------------

       1] SHRINK 대상 테이블 분석 및 조회
          (NUM_ROWS에 비해 사용하는 BLOCKS가 과다하면 SHRINK필요)
          SQL> connect / as sysdba

          SQL> EXECUTE DBMS_UTILITY.ANALYZE_SCHEMA('소유자', 'COMPUTE');

          SQL> SELECT OWNER,     TABLE_NAME,   NUM_ROWS,
                      BLOCKS,    EMPTY_BLOCKS, AVG_SPACE,
                      CHAIN_CNT, AVG_ROW_LEN
                 FROM DBA_TABLES
                WHERE OWNER = '소유자'
                  AND EMPTY_BLOCKS / (BLOCKS + EMPTY_BLOCKS) < 0.1
                  AND (BLOCKS + EMPTY_BLOCKS) > 0
                ORDER BY BLOCKS DESC;

     

          [참고] DBMS_SPACE.VERIFY_SHRINK_CANDIDATE

     

       2] 대상 테이블 및 관련 인덱스 NOLOGGING 설정

          SQL> connect 소유자/암호
          SQL> ALTER TABLE 테이블명 NOLOGGING;
          SQL> ALTER INDEX 인덱스명 NOLOGGING;

     

       3] 대상 테이블의 ROW MOVEMENT 기능 활성화
          (데이터의 조각모음으로 ROWID가 변경되므로 ENABLE ROW MOVEMENT)
          SQL> ALTER TABLE 테이블명 ENABLE ROW MOVEMENT;

     

       4] 필요한 작업을 선택적으로 작업
          4-1) 테이블만 SHRINK하고 HWM(High Water Mark)는 SHRINK하지 않음
               SQL> ALTER TABLE 테이블명 SHRINK SPACE COMPACT;

     

          4-2) 테이블과 HWM(High Water Mark)를 SHRINK
               (HWM SHRINK 시 TM 락 발생)
               SQL> ALTER TABLE 테이블명 SHRINK SPACE;

     

          4-3) 테이블과 테이블의 HWM을 SHRINK
               SQL> ALTER TABLE 테이블명 SHRINK SPACE COMPACT;
               SQL> ALTER TABLE 테이블명 SHRINK SPACE;

     

          4-4) 인덱스와 인덱스의 HWM을 SHRINK
               (ROWID가 변경되지 않으므로 ENABLE ROW MOVEMENT 불필요)
               SQL> ALTER INDEX 인덱스명 SHRINK SPACE COMPACT;
               SQL> ALTER INDEX 인덱스명 SHRINK SPACE;

     

          4-5) 테이블 및 관련된 인덱스를 모두 SHRINK
               SQL> ALTER TABLE 테이블명 SHRINK SPACE CASCADE COMPACT;
               SQL> ALTER TABLE 테이블명 SHRINK SPACE CASCADE;

     

       5] Row movement 비활성화
          SQL> ALTER TABLE 테이블명 DISABLE ROW MOVEMENT;

     

       6] 대상 테이블 및 관련 인덱스 LOGGING 설정
          SQL> ALTER TABLE 테이블명 LOGGING;
          SQL> ALTER INDEX 인덱스명 LOGGING;

     

       ※ M-View 형태의 테이블을 SHRINK
          on-commit materialized view와 연관된 세그먼트는 SHRINK 시킬 수 없음
          rowid에 기반을 둔 materialized view에 대해서는 refresh 또는 rebuild를 수행 필요
          SQL> ALTER TABLE M-View명 SHRINK SPACE COMPACT;
          SQL> ALTER TABLE M-View명 SHRINK SPACE;


     

    1) Chaining이 있는 테이블 select

     

    select owner, table_name, num_rows, blocks, empty_blocks, chain_cnt,
    to_char(100*(chain_cnt/num_rows),'999')||'%' as chain_pct from dba_tables
    where owner not in ('SYS','SYSTEM','TRACESVR','DBSNMP','SCOTT')
      and num_rows !=0 and chain_cnt !=0;

     

     

    반응형

    'ORACLE > ADMIN' 카테고리의 다른 글

    [ORACLE]Listener.log 관리  (0) 2013.08.06
    psu 패치  (0) 2013.07.25
    (10gR2)Full UNDO tablespace_언두 메커니즘  (0) 2013.05.19
    10g SYSAUX tablespace 크기 줄이기  (0) 2013.03.04
    Sizing Redo Log Files  (0) 2012.10.12
    Posted by [PineTree]
    ORACLE/ADMIN2013. 5. 19. 22:10
    반응형

    (10gR2)Full UNDO tablespace                                                                       

                                                                                                                               게시일: 2008. 2. 25 오후 9:54



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

    PURPOSE


    10gR2 에서 UNDO tablespace 을 NO AUTOEXTEND로 생성한 경우 ,
    transaction 이 실행중인 database 에서는 UNDO tablespace 가
    FULL인 현상을 보게 됩니다.
    이는 10gR2 에서 max retention 을 보장하는 undo retention 의
    메카니즘이 소개되어 autoextend off 인 경우의 UNDO tablespace
    에서 나타나는 현상입니다.
    dba_undo_extents 에서 많은 UNEXPIRED undo segment 가 보이는 것이
    확인되고 UNDO tablespace 가 100% full 인것처럼 나타나는 현상을 볼 수
    있으며 그럼에도 불구하고 ORA-1555 나 ORA-30036 에러는 발생하지 않습니다.

    Explanation


    다음과 같이 많은 UNEXPIRED undo segment 가 조회됩니다.

    SQL> select count(status) from dba_undo_extents where status = 'UNEXPIRED';

    COUNT(STATUS)

    463

    SQL> select count(status) from dba_undo_extents where status = 'EXPIRED';

    COUNT(STATUS)

    20

    SQL> select count(status) from dba_undo_extents where status = 'ACTIVE';

    COUNT(STATUS)

    21

    dba_free_space 을 조회 결과 UNDO tablespace 의 free space 가 존재합니다.

    SUM(BYTES)/(1024*1024) TABLESPACE_NAME


    ---------------------
    3 UNDOTBS1
    58.4375 SYSAUX
    3 USERS3
    4.3125 SYSTEM
    103.9375 USERS04

    Transaction 이 실행되면 UNDO tablespace 에 free space 가 조회되지 않는
    FULL 인것처럼 보입니다.

    SUM(BYTES)/(1024*1024) TABLESPACE_NAME
    ----------------
    58.25 SYSAUX
    98 USERS3
    4.3125 SYSTEM
    87.9375 USERS04


    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    다음은 AUM 에서의 Undo Block 할당 알고리즘은 다음과 같습니다.

    1. current extent 에 free block 이 있으면 다음 free block 이
    할당됩니다.
    2. 그러나, free block 이 없으면, next extent 가 expired 되었다면 next extent 을
    warp 한후 그 next extent 의 처음 block 을 return 합니다.
    3. 만약 next extent 가 expired 되지 않았다면 UNDO tablespace 로부터 먼저
    space 을 찾습니다. 이때 free extent 가 존재한다면 이를 transaction table 에
    할당하고 해당 next extent 의 첫번째 block 을 return 합니다.
    4. 만약 UNDO tablespace 에 free extent 가 없다면 offline 된 transaction table
    에서 steal 합니다.
    offline 된 transaction table 에서 extent 을 deallocate 한후 이를
    current transaction table 에 add한후 그 add 한 extent 의 첫번째 free block 을
    return 합니다.
    5. offline 된 transaction table 에서 찾을수 없으면 , online 되어 있는
    transaction table 에서 steal 합니다. offline 된 transaction table 에서 extent 을
    deallocate 한후 이를 current transaction table 에 add한후 , 그 add 한 extent 의
    첫번째 free block 을 return 합니다.
    6. 1번~5번 까지 하여도 free block 을 얻지 못하면 이제 UNDO tablespace 의 file 을
    extend 합니다.
    file 이 extend 된다면 이후 current transaction table 에 extent 을 add 한후 ,
    그 extent 의 첫번째 free block 을 return 합니다.
    7. 6번 에서 UNDO tablespace 의 file 을 extend 하지 못했다면 , 자기의 transaction table
    에서 unexpired 된 extent 을 재사용합니다. 그런데 이때 모든 extent 가 busy 하다면
    즉 모두 uncommitted 된 정보라면 8번으로 갑니다. 아니라면 wrap 하여 unexpired 된
    extent 을 사용합니다.
    8. offline 된 transaction table 에서 unexpired 된 extent 을 steal 합니다. 이것이
    실패한다면 online 된 transaction table 에서 unexpired 된 extent 을 steal 합니다.
    9. 8 번까지 수행하고도 free block 을 얻지 못하면 이때서야 오라클에서는
    "ORA-30036 unable to extend segment by %s in undo tablespace '%s' " 에러를
    뿌리며 실패합니다.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    fixed size UNDO tablespace 라 함은 autoextend 가 off 라 datafile 을 자동으로
    더 이상 확장할 수 없음을 말합니다.
    autoextend 가 off 인 경우 10.2 부터는 max retention 이 36 시간 입니다.
    undo_retention 을 900 초(15 분) 으로 설정을 한다고 해도 10gR2 에서는
    max retention 이 36 시간이라 이에 해당하는 undo extent 을 UNEXPIRED 으로 만듭니다.
    그러나 이것이 가용한 undo extent 가 없다는 것이 아니고 , transaction 이 실행되게 되면
    UNEXPIRED undo segment 을 재사용하게 됩니다.

    References


    < Note 413732.1 - Full UNDO Tablespace In 10gR2 >

    반응형

    'ORACLE > ADMIN' 카테고리의 다른 글

    psu 패치  (0) 2013.07.25
    shrink 대상 선정 및 shrink작업  (1) 2013.06.03
    10g SYSAUX tablespace 크기 줄이기  (0) 2013.03.04
    Sizing Redo Log Files  (0) 2012.10.12
    Dynamic Intimate Shared Memory  (0) 2012.08.23
    Posted by [PineTree]
    ORACLE/ADMIN2013. 3. 4. 16:10
    반응형

    0g SYSAUX tablespace 크기 줄이기
    오라클 2009/01/14 16:42
    sysaux tablespace는 10g에서 새로 추가된 system default tablespace의 하나로 기존에 system tablespace에
    저장되던 각종 ORACLE OPTION들의 schema가 저장되며 10g의 new feature인 AWR(auto workload repository) 데이터들이 저장되는 tablespace 입니다.
     
    awr정보는 default로 1시간에 한번씩 data를 gathering하고 그 정보를 7일동안 저장하게 되어 있습니다.
    7일이 지나면 가장 오래된 awr정보를 자동으로 삭제하게끔 되어 있습니다.
    awr정보는 7일간 저장되지만 주기적으로 실행하는 table analyze 정보는 default로 31일 동안 저장이 됩니다.

    <해결책>

    1. select dbms_stats.get_stats_history_retention from dual;
    (기본 31일입니다.)

    2. exec dbms_stats.alter_stats_history_retention(7);
    => 일주일 주기로 바꿈
     
    3.exec dbms_stats.purge_stats(to_timestamp_tz('10-10-2008 00:00:00 Asia/Seoul','DD-MM-YYYY HH24:MI:SS TZR'));
    => AWR(auto workload repository) 데이터 저장 값입니다. 디폴드 주기 31일 이지만
    2008년 10월10일 이전 데이터 삭제 => 날짜 조정 해주시면 됩니다.
    oracle 사용 내부 통계 정보로 자동 삭제 주기를 줄인 다음 값을 삭제 하는겁니다.

    4.alter table wri$_optstat_histgrm_history enable row movement;

    5.alter table wri$_optstat_histgrm_history shrink space;
    5번 실행 해서 에러 없을 경우 진행
    SQL> alter table wri$_optstat_histgrm_history shrink space;
    alter table wri$_optstat_histgrm_history shrink space
    *
    1행에 오류:
    ORA-10631: SHRINK clause should not be specified for this object
    => 에러 날 경우 6번 진행

    6. 5번에서 에러 날 경우[index 생성 쿼리 추출 구문 실행]
    set long 1000
    select dbms_metadata.get_ddl('INDEX','I_WRI$_OPTSTAT_H_OBJ#_ICOL#_ST','SYS') from dual;

    =>결과
    CREATE INDEX "SYS"."I_WRI$_OPTSTAT_H_OBJ#_ICOL#_ST"
    ON "SYS"."WRI$_OPTSTAT_HISTGRM_HISTORY"("OBJ#","INTCOL#",SYS_EXTRACT_UTC("SAVTIME"))
    PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "SYSAUX" nologging;


    select dbms_metadata.get_ddl('INDEX','I_WRI$_OPTSTAT_H_ST','SYS') from dual;

    => 결과
     CREATE INDEX "SYS"."I_WRI$_OPTSTAT_H_ST"
     ON "SYS"."WRI$_OPTSTAT_HISTGRM_HISTORY"(SYS_EXTRACT_UTC("SAVTIME")) PCTFREE 10 INITRANS 2 MAXTRANS 255
     COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1
     MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "SYSAUX" nologging;

    7. INDEX 삭제 아래 적용 후 재 생성
    drop INDEX "SYS"."I_WRI$_OPTSTAT_H_OBJ#_ICOL#_ST";

    drop INDEX "SYS"."I_WRI$_OPTSTAT_H_ST";
    =============================================

    8. alter table WRI$_OPTSTAT_HISTGRM_HISTORY enable row movement;

    9. alter table WRI$_OPTSTAT_HISTGRM_HISTORY shrink space;

    10. alter table WRI$_OPTSTAT_HISTGRM_HISTORY disable row movement;

    11. alter session set workarea_size_policy=manual;

    12. alter session set sort_area_size=104857600;

    13. 위에서 삭제한 index 생성 쿼리 실행
    13-1.
    CREATE INDEX "SYS"."I_WRI$_OPTSTAT_H_ST"
     ON "SYS"."WRI$_OPTSTAT_HISTGRM_HISTORY"(SYS_EXTRACT_UTC("SAVTIME")) PCTFREE 10 INITRANS 2 MAXTRANS 255
     COMPUTE STATISTICS STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1
     MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "SYSAUX" nologging;
    13-2.
    CREATE INDEX "SYS"."I_WRI$_OPTSTAT_H_OBJ#_ICOL#_ST"
    ON "SYS"."WRI$_OPTSTAT_HISTGRM_HISTORY"("OBJ#","INTCOL#",SYS_EXTRACT_UTC("SAVTIME"))
    PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
    STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
    PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "SYSAUX" nologging;

    14.결과 조회
    14-1
    select occupant_name,space_usage_kbytes/1024 "MB"
    from v$sysaux_occupants
    order by space_usage_kbytes
    /
    적용 전
    OCCUPANT_NAME                                         MB
    --------------------------------------------- ----------

    SM/OPTSTAT                                        4.8125
    SM/AWR
    적용 후

    SM/OPTSTAT                                           3.5
    SM/AWR

    15. SYSAUX Tablespace 사용량 체크

    select tablespace_name,sum(bytes/1024/1024) "Free(M)"
    from dba_free_space
    where tablespace_name = 'SYSAUX'
    group by tablespace_name;

    반응형
    Posted by [PineTree]