'분류 전체보기'에 해당되는 글 2491건

  1. 2009.06.27 오라클 힌트 사용
  2. 2009.06.27 오라클 에러코드 정리
  3. 2009.06.27 오라클 에러코드 한글 번역
  4. 2009.06.27 오라클 팁...!!(시스템테이블)
  5. 2009.06.27 Linux Oracle 설치와 활용(Ⅰ)
  6. 2009.06.27 Oracle Database 10g (10.1.0.2) Installation On Fedora Core 2 (FC2)
  7. 2009.06.27 oracle 에러(상세설명)
  8. 2009.06.27 oracle 에러(상세설명)
  9. 2009.06.27 오라클9i의 향상된 RMAN
  10. 2009.06.27 RMAN-00554: initialization of internal recovery manager package failed
  11. 2009.06.27 rman을 이용한 백업(backup 명령어)
  12. 2009.06.27 [오라클 11g] 보안
  13. 2009.06.27 웹 접근성을 위한 웹 개발자 3가지 수칙
  14. 2009.06.27 gpedit.msc - 제어판 사용 못하게 하기 또는 사용 하게 하기
  15. 2009.06.27 OCX 인증서 만들기
  16. 2009.06.27 [javascript] 입력 문자 한글 체크
  17. 2009.06.27 메일(첨부자료 3개) 보내기 .. 한글도 잘됨
  18. 2009.06.27 Tomcat 5.5.x Common-DBCP 설정하기 [JNID 이용]
  19. 2009.06.27 Tomcat 5.5.x Common-DBCP 설정하기 [ ContextName.xml..
  20. 2009.06.27 Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용
  21. 2009.06.27 Apache 2 + Tomcat 5.x mod_jk 1.2 연동시 한글 문제
  22. 2009.06.27 [Tomcat4,5]DBCP configure
  23. 2009.06.27 DBCP의 POOL 상태를 모니터링 하는 페이지 1
  24. 2009.06.27 [Tomcat5.5] DBCP configure
  25. 2009.06.27 Java 튜닝 (반복문 최적화 #1)
  26. 2009.06.27 연봉테이블.xls
  27. 2009.06.27 2004년도 정도에 만든던 바이오 디젤 사업계획서...
  28. 2009.06.27 roi template.xls
  29. 2009.06.26 Oracle9i Admin.pdf
  30. 2009.06.26 자바 튜닝 자료
02.Oracle/DataBase2009. 6. 27. 11:29
반응형

<Optimization Approaches and Goals - Optimization  접근과 목적>                    
/*+ ALL_ROWS */                                                                    
        explicitly chooses the cost-based approach to optimize a statement         
        block with a goal of best throughput (that is, minimum                     
        total resource consumption)                                                
        가장 좋은 단위 처리량의 목표로 문 블록을 최적화하기 위해 cost-based        
        접근 방법을 선택합니다. (즉, 전체적인 최소의 자원 소비)                    
/*+ CHOOSE */                                                                      
        causes the optimizer to choose between the rule-based                      
        approach and the cost-based approach for a SQL statement                   
        based on the presence of statistics for the tables accessed by             
        the statement                                                              
        최적자(optimizer)가 그 문에 의해 접근된 테이블을 위해 통계의 존재에        
        근거를 두는 SQL 문을 위해 rule-based 접근 방법과 cot-based 접근 방법       
        사이에 선택하게 합니다.                                                    
/*+ FIRST_ROWS */                                                                  
        explicitly chooses the cost-based approach to optimize a statement         
        block with a goal of best response time (minimum                           
        resource usage to return first row)                                        
        가장 좋은 응답 시간의 목표로 문 블록을 최적화하기 위해 cost-based 접근     
        방법을 선택합니다. (첫 번째 행을 되돌려 주는 최소의 자원 사용)             
/*+ RULE */                                                                        
        explicitly chooses rule-based optimization for a statement block           
        rule-based 최적화를 고르는 접근방법을 선택합니다.                          
                                                                                   
<Access Methods - 접근 방법>                                                       
/*+ AND_EQUAL(table index) */                                                      
        explicitly chooses an execution plan that uses an access path              
        that merges the scans on several single-column indexes                     
        그만큼 실행 계획을 선택합니다. 그리고 여럿의 single-column 색인에          
        그 scan을 합병하는 접근 경로를 사용합니다.                                 
/*+ CLUSTER(table) */                                                              
        explicitly chooses a cluster scan to access the specified table            
        선택합니다. 그리고, 클러스터는 그 명시된 테이블을 접근하기 위해 살핍니다.  
/*+ FULL(table) */                                                                 
        explicitly chooses a full table scan for the specified table               
        그 명시된 테이블을 위하여, 전체 테이블 scan을 고르는                       
/*+ HASH(table) */                                                                 
        explicitly chooses a hash scan to access the specified table               
        선택합니다. 그리고, 해쉬는 그 명시된 테이블을 접근하기 위해 운율을         
         살핍니다.                                                                 
/*+ HASH_AJ(table) */                                                              
        transforms a NOT IN subquery into a hash antijoin to access                
        the specified table                                                        
        변환, 그 명시된 테이블을 접근하는 해쉬 antijoin으로의 NOT IN 부속 조회     
/*+ HASH_SJ (table) */                                                             
        transforms a NOT IN subquery into a hash anti-join to access               
        the specified table                                                        
        변환, 그 명시된 테이블을 접근하는 해쉬 anti-join으로의 NOT IN 부속 조회    
/*+ INDEX(table index) */                                                          
        explicitly chooses an index scan for the specified table                   
        그 명시된 테이블을 위하여, 색인 scan을 고르는                              
/*+ INDEX_ASC(table index) */                                                      
        explicitly chooses an ascending-range index scan for the specified         
        table 그 명시된 테이블을 위하여, ascending-range 색인 scan을 고르는        
/*+ INDEX_COMBINE(table index) */                                                  
        If no indexes are given as arguments for the INDEX_COMBINE                 
        hint, the optimizer uses whatever Boolean combination                      
        of bitmap indexes has the best cost estimate. If particular                
        indexes are given as arguments, the optimizer tries to use                 
        some Boolean combination of those particular bitmap indexes.               
        어떤 색인도 INDEX_COMBINE 암시를 위해 인수로서 주어지지 않는다면,          
        bitmap 색인의 결합이 어떤 부울의를 가장 좋은 수행 난이도 평가를 가지고     
        있든지 최적자는 이용합니다.                                                
        특별한 색인이 인수로서 주어진다면, 최적자는 그 특별한 bitmap 색인의        
        몇몇의 부울의 결합을 사용하려고 노력합니다.                                
/*+ INDEX_DESC(table index) */                                                     
        explicitly chooses a descending-range index scan for the specified         
        table                                                                      
        그 명시된 테이블을 위하여, descending-range 색인 scan을 고르는             
/*+ INDEX_FFS(table index) */                                                      
        causes a fast full index scan to be performed rather than a full           
        table scan                                                                 
        빠른 전체 색인 scan이 전체 테이블 scan이라기보다는 수행되게 합니다.        
/*+ MERGE_AJ (table) */                                                            
        transforms a NOT IN subquery into a merge anti-join to access              
        the specified table                                                        
        변환, NOT IN 부속 조회, 그 명시된 테이블을 접근하기 위해 anti-join을       
        합병합니다.                                                                
/*+ MERGE_SJ (table) */                                                            
        transforms a correlated EXISTS subquery into a merge semi-join             
        to access the specified table                                              
        변환, 관련된 EXISTS 부속 조회, 접근으로 semi-join을 합병합니다,            
        그 명시된 테이블                                                           
/*+ ROWID(table) */                                                                
        explicitly chooses a table scan by ROWID for the specified                 
        table                                                                      
        그 명시된 테이블을 위하여, ROWID에 의해 테이블 scan을 고르는               
/*+ USE_CONCAT */                                                                  
        forces combined OR conditions in the WHERE clause of a                     
        query to be transformed into a compound query using the                    
        UNION ALL set operator                                                     
        질의의 WHERE 문절에 있는 UNION ALL 집합 연산자를 사용하는 합성의           
        질의로 변형되는 OR 조건을 합쳤습니다.                                      
                                                                                   
<Join Orders>                                                                      
/*+ LEADING(테이블) */                                                             
      Driving 테이블 결정, 힌트에 명시된 테이블이 먼저 Driving됨                   
/*+ ORDERED */                                                                     
        causes Oracle to join tables in the order in which they appear             
        in the FROM clause                                                         
        오라클이 From 절 순서로 테이블을 결합시키게 합니다.                        
/*+ STAR */                                                                        
        forces the large table to be joined last using a nested-loops join         
        on the index                                                               
        큰 테이블이 최종 사용/회전율에 nested-loops를 결합시킨                     
        그 색인에 결합합니다.                                                      
                                                                                   
                                                                                   
<Join Operations>                                                                  
/*+ DRIVING_SITE (table) */                                                        
        forces query execution to be done at a different site from that            
        selected by Oracle                                                         
        오라클에 의해 선택된 사이트에 되는 실행을 질의합니다.                      
/*+ USE_HASH (table) */                                                            
        causes Oracle to join each specified table with another row                
        source with a hash join                                                    
        오라클이 테이블이 다른 행 자원으로 해시 접합으로 명시되면서 각자와         
        합치게 합니다.                                                             
/*+ USE_MERGE (table) */                                                           
        causes Oracle to join each specified table with another row                
        source with a sort-merge join                                              
        오라클이 테이블이 다른 행 자원으로 sort-merge 접합으로 명시되면서 각자와   
        합치게 합니다.                                                             
/*+ USE_NL (table) */                                                              
        causes Oracle to join each specified table to another row                  
        source with a nested-loops join using the specified table as the           
        inner table                                                                
        오라클이 그 명시된 테이블을 그 안의 테이블로 사용하는 nested-loops 집합과  
        각자와 다른 행 자원에 대한 명시된 테이블을 합치게 합니다.                  
                                                                                   
<Parallel Execution>                                                               
/*+ APPEND */ , /*+ NOAPPEND */                                                    
        specifies that data is simply appended (or not) to a table; existing       
        free space is not used. Use these hints only following the                 
        INSERT keyword.                                                            
        데이터가 테이블로 단순히 덧붙여진다는 (or not)것을 명시합니다;             
        현존하는 영역은 사용되지 않습니다.                                         
        단지 그 삽입 키 핵심어를 따르는 이 암시를 사용하시오.                      
/*+ NOPARALLEL(table) */                                                           
        disables parallel scanning of a table, even if the table was created       
        with a PARALLEL clause                                                     
        그 테이블이 PARALLEL 문절로 새로 만들어졌다면 테이블의 평행의 순차 검색을  
        무능하게 만듭니다.                                                         
/*+ PARALLEL(table, instances) */                                                  
        allows you to specify the desired number of concurrent slave               
        processes that can be used for the operation.                              
        DELETE, INSERT, and UPDATE operations are considered for                   
        parallelization only if the session is in a PARALLEL DML                   
        enabled mode. (Use ALTER SESSION PARALLEL DML to                           
        enter this mode.)                                                          
        당신이 그 연산을 위해 사용될 수 있는 동시의 슬레이브(slave) 프로세스의     
        요구된 수를 명시하는 것을 허락합니다.                                      
        그 세션이 가능하게 된 PARALLEL DML에 모드를 있다면, DELETE, INSERT, UPDATE 
        연산은 단지 parallelization에 대해 고려됩니다. (사용은 이 모드에 들어가기  
        위해 평행의 세션 DML을 변경합니다.)                                        
/*+ PARALLEL_INDEX                                                                 
        allows you to parallelize fast full index scan for partitioned             
        and nonpartitioned indexes that have the PARALLEL attribute                
        parallelize에 당신에게 빠른 가득한 색인 scan을 허락합니다. 그런데,         
        그것은 PARALLEL 속성을 가지고 있는 색인을 분할했고 nonpartitioned했습니다. 
/*+ NOPARALLEL_INDEX */                                                            
        overrides a PARALLEL attribute setting on an index                         
        병렬이 색인을 나아가는 것을 속하게 하는 대체                               
                                                                                   
<Other Hints>                                                                      
/*+ CACHE */                                                                       
        specifies that the blocks retrieved for the table in the hint are          
        placed at the most recently used end of the LRU list in the                
        buffer cache when a full table scan is performed                           
        그 블록이 찾아서 가져왔다는 것을 명시합니다. 그리고 그 테이블을 위해       
        그 암시에 놓여집니다. 그런데, 그것은 가장 요즈음 사용된 언제 그 버퍼       
        캐시, 가득한 테이블 scan에 있는 LRU 리스트의 끝입니다. 수행됩니다.         
/*+ NOCACHE */                                                                     
        specifies that the blocks retrieved for this table are placed at           
        the least recently used end of the LRU list in the buffer cache            
        when a full table scan is performed                                        
        그 명시합니다. 그리고, 그 블록은 이 테이블을 위해 검색되면서 요즈음 사용   
        된 언제 그 버퍼 캐시, 가득한 테이블 scan에 있는 LRU 리스트의 가장 작은     
        끝에 놓여집니다. 수행됩니다.                                               
/*+ MERGE (table) */                                                               
        causes Oracle to evaluate complex views or subqueries before               
        the surrounding query                                                      
        오라클이 그 둘러싸는 질의 전에 복잡한 뷰나 부속 조회를 평가하게 합니다.    
/*+ NO_MERGE (table) */                                                            
        causes Oracle not to merge mergeable views                                 
        오라클이 mergeable 뷰를 합병하지 않게 하지 않습니다                        
/*+ PUSH_JOIN_PRED (table) */                                                      
        causes the optimizer to evaluate, on a cost basis, whether or              
        not to push individual join predicates into the view                       
        개개 접합을 미는 것이 그 뷰 안으로 단정 하든 간에 비용 방식으로 최적자가   
        평가하게 합니다.                                                           
/*+ NO_PUSH_JOIN_PRED (table) */                                                   
        Prevents pushing of a join predicate into the view                         
        접합 술부 중에서 그 뷰로 밀면서, 막는                                      
/*+ PUSH_SUBQ */                                                                   
        causes nonmerged subqueries to be evaluated at the earliest                
        possible place in the execution plan                                       
        원인은 그 실행 계획에서의 가장 이른 가능한 장소에 평가되는 부속 조회를     
        nonmerged 했습니다.                                                        
/*+ STAR_TRANSFORMATION */                                                         
        makes the optimizer use the best plan in which the transformation          
        has been used.                                                             
        최적자가 그 변형이 사용된 가장 좋은 계획을 사용하는 제작    

출처 : Tong - atc17cjh님의 oracle통

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:28
반응형

oerr ora n

-----
현상 : Oracle Stored Procedure 호출이 제대로 되지 않음
원인 : Stored Procedure에 입출력되는 VARCHAR 변수의 초기화가 되지 않음
조치 : Stored Procedure 입력, 출력 VARCHAR 변수의 Length를 반드시 설정
(TMS에 문제를 일으키는 것으로 보임)
-----
현상 : exec TMS_ORACLE7 -A: Failed.
원인 : ORACLE에서 DB 사용자에게 GRANT(사용허가권)가 없어서 발생하는 문제임.
ORACLE LIB에서 문제가 생길 수도 있다.
조치 : ORACLE의 VIEW중에 V$XATRANS$라는 VIEW를 GRANT시켜주면 조치됨.
ORACLE의 DBA권한에서 실행가능함.
방법: grant all on V$XATRANS$ TO SCRJPCS
여기서 SCRJPCS는 DB USER-ID임.
-----
현상 : DataBase에 연결하지 못한다.
원인 : 1.해당 DataBase에 필요한 환경 설정이 잘못되어 있다.(INVAL Error발생)
2.환경 파일에 환경 설정이 잘못되어 있다.(INVAL Error)
3.DataBase에 권한이 없다.
4.DataBase가 기동되지 않았다.
조치 : 1.set 명령으로 필요한 환경변수 설정을 확인한다.
- Oracle : ORACLE_HOME, ORACLE_SID, ORA_NLS
- Informix : INFORMIXDIR, INFORMIXSERVER
2.구성파일에 설정되어 있는 ENVFILE을 확인한다.
3.해당 User에게 DataBase 권한을 부여한다.
- ORACLE : "v$xatrans$"라는 VIEW에 대하여 해당 User에게 권한을 부여한다.
- INFORMIN : 해당 DB를 사용할 수 있는 권한을 User에게 부여한다.
4.DataBase를 기동하고 Server를 새로 띄운다.
-----
현상 : LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PLS-00801: Message 801 not found; product=PLSQL; facility=PCM
22/9 PL/SQL: SQL Statement ignored
28/17 PLS-00201: identifier 'JWONRYO.JWONMAS' must be declared
62/9 PL/SQL: SQL Statement ignored
원인 : 현 Database의 Domain 밖에 있는 Table을 Handling하는 경우에 권한이 없는
경우에 발생
조치 : 접근할 수 있는 권한을 부여한다.
-----
현상 : LINE/COL ERROR
-------- -----------------------------------------------------------------
135/5 PL/SQL: Statement ignored
135/9 PLS-00365: 'AVSQLCODE' is an OUT parameter and cannot be read
원인 : OUT parameter를 IN parameter로 사용하고 그 값을 읽은 경우.
조치 : OUT parameter를 IN OUT parameter로 선언.
-----
현상 : ORA-0020
원인 : 프로세스 수를 프로세스를 초과한 경우.
조치 : 프로세스 수를 들여줌.
-----
현상 : ORA-00023: session references process's private memory; cannot detach session
원인 : XA library를 사용하는데 Oracle이 dedicator server로 설치된 경우 발생
조치 : XA library를 사용할려면 Oracle을 MTS mode로 설치되어야 한다.
-----
현상 : 1.ORA-0054 resource busy and acquire with NOWAIT specified
2.ORA-0054 WHEN DROP A TABLE(SESSION KILL)
원인 : 1.Oracle 사용자가 어떤 Row을 Lock를 했는데, 다른 Oracle 사용자가 NOWAIT문을 이용하여
동일한 Row를 Lock를 한 경우에 발생
2.TABLE에 LOCK이 걸려 DML 및 DDL 명령 사용시
조치 : LOCK을 걸고있는 SESSION들을 KILL
-----
현상 : ORA-0059
원인 : DB_FILES 값에 도달한 경우
조치 : init.ora 의 DB_FILES 를 늘려주고 DB 를 Restartup 하면 해결
-----
현상 : ORA-00210: cannot open control file '/dev/vx/rdsk/oracle/v_ctl1'
ORA-07368: sfofi: open error, unable to open database file.
원인 : Sequent Symmetry or NUMA-Q platform이 very large file (O/S에서 2GB
이상의 file system 지원)을 지원하기 위해 VLFS patch를 적용했거나
VLFS를 이미 지원하는 O/S Version일 경우 오라클 master node가 정상적으로
startup 되고 나서 다른 node가 startup parallel이 될 때 먼저 startup 된
master node가 shared disk 의 모든 오라클 관련 file을
none-shared mode로 open 하기 때문에 위의 현상이 발생됨.
조치 : 1.PTX/Cluster V1.3.2일 경우
* Oracle V7.3.x : O/S상에서 VLFS patch적용하지 않았을 경우는 관계
없으나, 이미 적용되었다면 추가적으로 O/S patch FP#23373
적용하여야 함
2.PTX/Cluster running DYNIX/PTX 4.4.x 일 경우
* Oracle V7.3.3 : 현재 fix된 patch는 없으며 다음과 같은
workaround 방법으로 해결이 가능함.

Workaround)
--- $ORACLE_HOME/rdbms/lib/ins_rdbms.mk file에 아래의 추가된 부분만
삽입하여 오라클 kernel relink 실시
(예:make -f ins_rdbms ioracle)
oracle: $(ORALIBD) $(CORELIBD) $(NETLIBD) $(KSMS) $(CONFIG)
$(PSOLIBLIST) opimai.o @$(ECHO) $(LINK) -o $@ $(LDFLAGS)
$(LDFLAGS_ORA) opimai.o $(CONFIG) \
-llkseqora \ ---> 추가된 부분
$(LLIBSERVER) $(LLIBORA) $(LLIBKNLOPT) $(LLIBSLAX)
$(LLIBPLSQL) \
$(LLIBSICX) $(LLIBSOWSUTL) \
$(LLIBSICX) $(LLIBSOWSUTL) \

...........
...........

* Oracle V7.3.4 :
Oracle V7.3.4 일 경우는 문제가 없으나 patchset을 적용할 경우
V7.3.4.2에서는 V7.3.3과 같은 방법으로 oracle kernel을 relink하면
문제가 해결됨.
-----
현상 : ORA-0376 : file %s cannot be read at this time
원인 : DBF가 파손됨.
조치 : Check the state of the file. Bring it online
-----
현상 : ORA-00376: file 29 cannot be read at this time
ORA-01110: data file 29: '/db/GICORP_4/axix01.dbf'
원인 : datafile의 size가 os에서 허용하는 filesize를 초과해서 발생.
조치 : unix의 ulimit filesize를 확인해 보시기 바랍니다.
그리고 datafile size 보다 크도록 수정해 주어야 합니다.
1.unix ulimit filesize를 증가 시킨다
C shell인 경우
% limit filesize <number>
Bourne 이나 Korn shell 인 경우
$ ulimit -f <number>
2.archivelog mode인지 확인합니다
SVRMGR> select * from v$database;

NAME CREATED LOG_MODE CHECKPOINT ARCHIVE_CH
--------- -------------------- ------------ ---------- ----------
GICORP 05/17/00 13:44:56 ARCHIVELOG 36290290 36284249
1 row selected.
3.media recovery가 필요한 datafiles를 찾습니다
SVRMGR> select * from v$recover_file;

FILE# ONLINE ERROR CHANGE# TIME
---------- ------- ------------------ ---------- --------------------
9 OFFLINE 36287415 12/20/00 23:30:55
23 OFFLINE 36289350 12/21/00 08:40:54
28 OFFLINE 36287415 12/20/00 23:30:55
29 OFFLINE 36287415 12/20/00 23:30:55
37 OFFLINE 36287415 12/20/00 23:30:55
5 rows selected.
4.각각의 datafile에 대해서 다음을 실행해 줍니다
SVRMGR> recover datafile '/db/GICORP_4/axix01.dbf';

Media recovery complete.

SVRMGR> alter database datafile '/db/GICORP_4/axix01.dbf' ONLINE;
Statement processed.

5.database를 restart합니다

SVRMGR> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SVRMGR> startup
ORACLE instance started.
Total System Global Area 54578916 bytes
Fixed Size 69348 bytes
Variable Size 20783104 bytes
Database Buffers 33554432 bytes
Redo Buffers 172032 bytes
Database mounted.
Database opened.
SVRMGR>
-----
현상 : ORA-0312,0313 에러(ONLINE LOG CRASH)
원인 : 1.데이타베이스 STARTUP 시 발생
조치 : [ ONLINE LOG 가 손상되었을때 DB에 OPERATION 이 없었던 경우는 다음과 같은 절차로 DB을
OPEN 할수있다 - 확률 70% ]

1.CONTROLFILE 생성
-. 손상된 online log 는 포함시키지 않는다.
-.resetlogs option 으로 생성한다.
-.reuse option 은 생략하고 기존 controlfile 은 다른이름으로 move 시킴.

<V7 에서 CONTROLFILE 생성하는 방법 >
sqldba> startup mount
sqldba> alter database backup controlfile to trace;

위와 같이 명령을 입력하면 ORACLE_HOME/rdbms/log 디렉토리에 트레이스 화일이
생긴다. 그 트레이스 화일에서 create controlfile 명령부분을 남기고 삭제한다.
콘트롤화일 생성 문장 예 - <cnt.sql> : GROUP 1 이 ONLINE LOG 라고 가정
---------------------------------------------------------------------
CREATE CONTROLFILE DATABASE "RC722" RESETLOGS NOARCHIVELOG
MAXLOGFILES 32 ********
MAXLOGMEMBERS 2
MAXDATAFILES 30
MAXINSTANCES 8
MAXLOGHISTORY 800
LOGFILE
GROUP 2 '/oracle/oracle/dbs/log2RC722.dbf' SIZE 5M,
GROUP 3 '/oracle/oracle/dbs/log3RC722.dbf' SIZE 5M
DATAFILE
'/oracle/oracle/dbs/systRC722.dbf',
'/oracle/oracle/dbs/rbsRC722.dbf',
'/oracle/oracle/dbs/toolRC722.dbf',
'/oracle/oracle/dbs/usrRC722.dbf',
'/oracle/oracle/dbs/tempRC722.dbf',
'/oracle/oracle/rcdata.dbf'
;
2.절차
$ sqldba lmode=y
SQLDBA> connect internal
SQLDBA> shutdown abort
SQLDBA> startup nomount
statement processed
SQLDBA> @cnt
SQLDBA> recover database using backup controlfile until cancel;
....
...
CANCEL (Return)
Recovery canceled
SQLDBA> alter database open resetlogs;

: 만일 정상적으로 open 되면 log file 추가
SQLDBA> alter database add logfile '?/dbs/log1ORA722.dbf' size 1M;
: 정상적으로 open 안되면 RC에 다시 연락
-----
현상 : ORA-0439
원인 : BITMAP INDEXES 생성 시 option 이 인스톨되지 않아서 발생
조치 : 반드시 Oracle 8 Enterprise Edition 에서만 사용이 가능하다.
Oracle 8i 에서도 동일하게 적용된다.
-----
현상 : ORA-0600[3339] DATA BLOCK CORRUPTION DETECTION
[3339] [arg1] [arg2] [] [] [] []
ORA-1578 : Data block corrupted in file # block #
원인 : 1.ORACLE이 직접 버퍼로 데이타를 읽어들일 때 읽은 블럭의 DBA(Data Block Address)가 잘못
되었음(INVALID)을 의미
2.ORACLE의 문제가 아니라 OS나 HW의 문제인 경우가 많다.
-----
현상 : ORA-0604: error occurred at recursive SQL level %s
원인 : 1.내부적으로 SQL명령이 실행될 때 발생(현재 할당된 익스텐트가 가득 차서 다음 익스텐트를
할당 받으려고 할 때 오라클이 다음 익스텐트의 크기와 위치를 결정하기 위하여 SELECT
명령을 내리게 되는 것과 같은 경우)
2.init.ora 화일의 파라미터 가운데 DC_FREE_EXTENTS 나 ROW_CACHE_ENQUEUES 의 값이 너무
작게 설정
3.테이블 스페이스가 가득 차거나 Extent 갯수의 최대 허용값을 초과해서 에러가 발생하는
경우 ORA-604 에러가 함께 발생
조치 : 1.?/dbs/init<SID>.ora 화일에 지정된 open_cursors 의 크기를 알아보는 것이다. 이 값이
설정이 안되어 있으면 Default가 50이므로
open_cursors=255
----------------
2.DC_FREE_EXTENTS 나 ROW_CACHE_ENQUEUES들의 값을 크게 설정
3.에러의 원인을 찾기 위해서 init.ora 화일에 다음과 같은 라인을 추가한다.
events = "604 trace name errorstack"
이렇게 init.ora를 변경하고 DB를 Shutdown 하고 Startup 하면 ORA-0604 에러가 발생하는
경우에 자세한 정보를 Trace 화일에 기록해 주므로 이 화일을 검사하여 에러의 원인을
찾을 수 있다.
-----
현상 : ORA-0901 invalid CREATE command
원인 : CREATE 뒤에 오는 KeyWord를 식별하지 못한 경우
-----
현상 : ORA-0902 invalid dadatype
원인 : Oracle에서 제공되지 않은 datatype를 사용한 경우
-----
현상 : ORA-0903 invalid table name
원인 : 테이블의 이름이 Oracle object 명명에 대한 필요조건을 만족시키지 못한 경우
-----
현상 : ORA-0904 열명이 부적합합니다.
원인 : 컬럼이 테이블에 존재하지 컬럼을 사용한 경우
-----
현상 : 083147.gold!stmkdjc.22031: LIBTUX_CAT:522: INFO: Default tpsvrdone() function
used
ORA-0904 : invalid column name
ORA-1003 : no statement parsed
원인 : 1.해당 Table에 존재하지 않은 Field를 사용한 경우
2.Host Variable 앞에 ":"를 덧붙지지 않은 경우
3.해당 Table를 변경하고 관련된 프로그램을 컴파일하지 않은 경우
조치 : 1.해당 Table에 Column이 존재하는지 확인
2.Host Variable 앞에 ":"를 덧붙인다.
3.해당 Table에 관련된 프로그램를 컴파일한다.
-----
현상 : ORA-0906 missing left parenthesis
원인 : 왼쪽 괄호를 찾지 못한 경우에 발생
-----
현상 : ORA-0907 missing right parenthesis
원인 : 오른쪽 괄호를 찾지 못한 경우에 발생
-----
현상 : ORA-0910 specified legth too long for its datatype
원인 : 특정 datatype의 길이가 허용 최대 길이를 초과한 경우
-----
현상 : ORA-0911 invalid character
원인 : Oracle이 뮤효 문자라고 간주하는 것을 만날 때 발생한 에러로 실제문제는 없어진 문자때문
-----
현상 : ORA-0913 too many value
원인 : INSERT문에서 지정된 열의 수보다 열 값의 수가 적으면 발생
-----
현상 : ORA-0917 missing comma
원인 : 1.Comma를 기대하고 있는 SQL문에 comma가 없는 경우
2.오른쪽 괄호가 없는 경우에도 발생
-----
현상 : ORA-0918 column ambiguously defined
원인 : 1.둘 이상의 테이블이 한 SQL문에서 참조될 때 발생
2.한개 이상의 지정된 테이블에 존재하는 어떤 열이 해당 테이블로 한정받지 못한 경우
-----
현상 : ORA-0920 invalid relational operator
원인 : 관계 연산자를 식별하지 못한 경우
-----
현상 : ORA-0921 unexpected end of SQL command
원인 : 불완전한 SQL문일 경우에 발생
-----
현상 : ORA-0922 missing or invalid option
원인 : option에 임의의 문자가 삽입됨(예:NOT NULL --> NOT_NULL)
-----
현상 : ORA-0932 inconsistent datatype
원인 : 1.어떤 연산자를 어떤 열에 적용시키려고 하는데 그것의 datatype을 연산자와 함께 사용한 경우
2.ORA-0997 illegal use of LONG datatype을 복귀시킬 가능성
-----
현상 : ORA-00933: SQL command not properly ended
원인:
-----
현상 : ORA-0934 group function is not allowed here
원인 : SQL문의 WHERE구나 GROUP BY구에서 Group function를 사용한 경우
-----
현상 : ORA-0936 missing expression
원인 : 1.Comma 기술 뒤에 열이나 표현식이 존재하지 않은 경우에 발생
2.ORA-0917 missing comma을 복귀시킬 가능성
-----
현상 : ORA-0937 not a single-group group function
원인 : 어떤 SQL문의 선택 list는 어떤 열이 GROUP BY구에서 참조되지 않으면 그열과 Group function를
포함할 수 없다.
-----
현상 : ORA-0938 not enough arguments for function
원인 : SQL문이 불충분한 수의 인수로 함수를 호출한 경우에 발생
-----
현상 : ORA-0942 : table or view does not exist(테이블 또는 뷰가 존재하지 않습니다.)
원인 : Oracle은 테이블이나 뷰가 존재하지만 사용자가 테이블이나 뷰를 위한 오브젝트 특권(Grant)을 부여하지 않음
조치 : Table 생성 및 권한부여
-----
현상 : ORA-0947 not enough values
원인 : INSERT문에서 지정된 열의 수가 열 값의 수보다 클때 발생
-----
현상 : ORA-0979 not GROUP BY expression
원인 : 어떤 query의 선택 list 안의 한 열이 GROUP BY구에 들어있고 다른 열은 들어있지 않은 경우에 발생
-----
현상 : ORA-0997 illegal use of LONG datatype
원인 : 1.어떤 기능들은 datatype이 LONG인 열에서 수행되지 않는다.
2.Long column은 2G까지 지원을 하지만,
SQL*Plus에서 insert into 문장을 이용하여 long column에 넣을 문자열을
single quote(') 안에 기술 시, 2000 characters가 넘으면 ora-1704 에러가 난다.
조치 : 1.TABLE의 COPY는 가능하지 않으므로,LONG COLUMN을 가진 테이블을 COPY하고자 할 때,
32KBytes 이하의 size라면 다음의 PL/SQL을 사용하면 가능하다.
2.PL/SQL을 이용해야 하며, 경우에 따라 Pro*C, SQL*Loader 등을 이용하여 insert해야만 한다.
-----
현상 : ORA-1001 Invalid Cursor
원인 : Typing 에러, 잘못된 메모리 관리 등의 여러가지 원인에 의해서 발생.
조치 : 1.환경에서 조치할 사항
- PRECOMPILE 옵션 가운데 MAXOPENCURSORS 를 늘려준다.
- init<SID>.ora 화일에서 OPEN_CURSORS 파라미터 값을 늘려준다.
- 사용되지 않는 CURSOR는 OPEN 상태로 두지 말고 CLOSE 시켜준다.
- 지금은 거의 사용되지 않지만 ORACLE V6 를 사용한다면 PRECOMPILE 옵션 가운데
AREASIZE를 512K 정도로 크게 늘려주도록 한다. 그리고 init<SID>.ora 에서
CONTEXT_AREA 값도 늘려준다 .
- TRACE FILE을 이용하면 문제의 원인을 찾는데 있어 유용할 때가 있다.
2.그 밖의 경우
- OPEN 되지 않은 CURSOR 에 대해서 작업을 할 때
- 존재하지 않는 OBJECT에 대해서 SQL 명령을 실행할 때
- CURSOR CACHE로부터 삭제된 경우
- CURSOR CACHE로부터 삭제된 또다른 경우
PRECOMPILE 옵션 가운데에서 MAXOPENCUSORS 를 늘려주거나
HOLD_CURSOR=YES, RELEASE_CURSOR=NO 로 설정
- XA/TUXEDO 환경에서 ORA-1001 에러가 발생하는 경우(일부 ORACLE 버젼에서 발생)
-----
현상 : ORA-1002 FETCH OUT OF SEQUENCE IN PRO*C(stop[<fltmsjaud>]:리스너를 중단합니다.
원인 : 1.user가 더이상 유효하지 않은 cursor로부터 fetch를 하려고 하기 때문
2.ORA-1403 등과 같이 NO DATA FOUND를 return하는 fetch작업을 수행할때
3.SELECT FOR UPDATE를 가진 cursor 의 fetch작업내에 commit이 있는 경우
조치 : 3.commit을 fetch loop의 바깥쪽으로 빼거나 select for update문을 사용하지 않아야 한다.
-----
현상 : ORA-1012 Error( not logged on )가 발생
원인 : 1.tpbegin()이 되어 있지 않음
2.PC쪽에서 NOTRAN Mode로 Service를 호출
조치 : 1.Program을 확인한다.
2.flag를 0으로 Setting한다.(TRAN Mode로 Service 호출)
3.Service절에 Default에 AUTOTRAN을 "Y"로 설정하고 해당 Service명을 기술한다.
-----
현상 : ORA-1027 bind variables not allowed for data definition operations
원인 : WHERE에 BIND_VAR 를 이용한 CREATE VIEW 는 불가능
조치 : 이 경우 EXEC SQL CREATE TABLE IMAGE
(EMPNO NUMBER(4) NOT NULL, BITMAP LONG RAW)
END-EXEC.
이 처럼 create 해야 한다.
-----
현상 : ORA-1031 insufficient privileges
원인 : 사용자가 테이블이나 뷰와 연관된 적어도 한 개의 object 특권을 부여받았지만 SQL문에서 지정된
특권을 부여받지 않았을 때 발생
1.ORACLE의 SYSTEM 유저에 POWERBUILDER의 BASE TABLE 5개가 생성이 되어 있지
않은 경우
2.SYSTEM 유저로 접속한 후에도 일반 유저가 접속이 되지 않을 경우
조치 : 1.5개 base table(pbcatcol, pbcattbl, pbcatfmt, pbcatvld, pbcatedt)을
drop한 다음 system 유저로 접속을 하고, 다시 일반 유저로 접속하는 방법.
2.system 유저로 들어가서 5개 base table에 대한 사용 권한을
일반 유저에게 주는 방법.
$sqlplus system/manager

SQL>grant all on pbcatcol to public;
SQL>grant all on pbcatedt to public;
SQL>grant all on pbcatfmt to public;
SQL>grant all on pbcattbl to public;
SQL>grant all on pbcatvld to public;
-----
현상 : ORA-1034, "ORACLE not available"
ORA-7320, "smsget: shmat error when trying to attach sga."
ORA-7429, "smsgsg: shmget() failed to get segment."
원인 : ORACLE DBA 사용자만 데이타베이스를 ACESS할수 있고 다른 사용자는 SQL*PLUS 등을 통하여
CONNECT를 하려고 할때 다음 에러가 발생 할경우
-----
현상 : TPFAILED ......................
sqlca.sqlcode ==> -1036
ORACLE에서 단독으로 실행하면 문제가 발생되지 않고 OUTPUT을 정확하게 출력하지만
TP/M와 함께 실행이 되면 SQL SELECT문을 수행하지 못하고 sqlca.sqlcode ==> -1036의
MESSAGE를 뿌리고 실행을 멈춘다.
원인 : ORACLE에서 Version간의 Segment 정의부분이 다르기 때문
조치 : makefile 혹은 proc.mk file에서
sqlcheck=semantic userid=scrjpcs/scrjpcs를 포함시킨다.
-----
현상 : ORA-1039: insufficient privileges on underlying objects of the view.
원인 : SYS user가 아닌 다른 user로 SQL Analyze에 로그인하여 SQL statement에 대한 explain plan 옵션을 사용할 때 다음과 같은 에러가 발생
조치 : 1.dictionary table/view들을 validate시켜 놓으려면 dba가 read 권한만 SQL Analyze를 수행하는 user에게 grant하면 충분하다.
2.SYS user로서 SQL explaining을 수행하는 것이다.
-----
현상 : ORA-9992 scumnt: failed to open <FILENAME>
ORA-9993 scumnt: failed to lock <FILENAME>
ORA-1102 cannot mount database in exclusive mode
원인 : 서로 독립적인 두개의 instance가 동일한 database file들을 동기화 (synchronisation)없이 access할 수 있기 때문에 database corruption을 유발시킬 수 있었다.
조치 : database의 db_name이 변경되면 각각의 lk<DB_NAME> file을 생성.
-----
현상 : ORA-01118: cannot add any more database files: limit of XXX exceeded
원인 : 데이타 화일의 갯수가 MAXDATAFILES 값에 도달한 경우 발생
조치 : MAXDATAFILES를 늘리기 위해서는 DB를 새로 만들어야 하며 그 이후 버젼을 사용중이라면 콘트롤
화일을 새로 만들어서 MAXDATAFILES를 늘릴 수 있다
-----
현상 : ORA-1157 : cannot identify data file 11 - file not found
ORA-1110 : data file 11 : '/user1/oracle7/dbs/user2.dbf'
원인 : OS 명령으로 DATA FILE 을 삭제한 경우
조치 : DATABASE STARTUP시 STARTUP MOUNT 단계까지 실행한 후, 문제의 데이타 화일을 OFFLINE 시킨다.
데이타베이스를 오픈한다. 단 데이타베이스 오픈이 정상적으로 수행되면 문제가 발생한 데이타
화일을 포함하고 있는 TABLESPACE를 DROP하지 않을 경우에는 DATABASE STARTUP시 항상 데이타
화일의 오픈 단계에서 에러가 발생된다. 따라서, 문제의 데이타 화일의 OFFLINE과 TABLESPACE의
DROP전에 반드시 해당 TABLESPACE를 사용하고 있는 USER의 데이타 백업을 수행해야 한다.

데이타 화일의 OFFLINE과 관련된 명령은 다음과 같다.
SQLDBA를 COMMAND LINE MODE로 기동시킨다.

$ sqldba lmode=y
SQLDBA> CONNECT INTERNAL;
SQLDBA> STARTUP MOUNT;
ORACLE instance started.
Database mounted.
SQLDBA> ALTER DATABASE DATAFILE '/user1/oracle7/dbs/user2.dbf'
OFFLINE DROP;
Statement processed.
SQLDBA> ALTER DATABASE OPEN;
Statement processed.
SQLDBA> DROP TABLESPACE tablespace_name INCLUDING CONTENTS;
Statement
-----
현상 : ORA-01237 cannot extend datafile %s
원인 : O/S 레벨에서는 file size를 1TB 이상 지원한다고 하는데, oracle datafile을 2G 이상으로 resize하려고 한다거나 tablespace에 datafile을 추가하거나 생성할 때, 2G 이상 주면 file size limit에 걸리는 현상 발생
조치 : 화일 시스템에서 large file을 사용하기 위해서는 화일 시스템을 'largefiles' option으로 mount해야 한다.
-----
현상 : ORA-1400 primary key or mandatory(NOT NULL) column is missing or NULL during insert
원인 : 어떤 필수적인 열을 위한 값을 공급하지 않은 경우
-----
현상 : ORA-1401 inserted value too large for column(열에 입력한 값이 너무 큽니다.)
원인 : 문자열을 할당하고자 할때 길이가 최대치를 초과한 경우
-----
현상 : ORA-1403 no dada found
원인 : 사실상 전혀 Error가 아니다.
-----
현상 : ORA-1405 fetched column value is NULL
원인 : ERROR 가 아니고 WARNING MESSAGE 이다.
조치 : dbms=v6 를 PRECOMPILER OPTION 에 추가해준다. dbms=v6 로 SETTING 할경우는 HOST 변수에
NULL 이 RETURN 되더라도 sqlca.sqlcode 는 0 이 된다.
-----
현상 : ORA-1407 cannot update mandatory(NOT NULL) column to NULL
원인 : 필수적인 열의 값을 NULL에 설정한 경우에 발생
-----
현상 : ORA-1408 such column list already indexed
원인 : 이미 동일한 열 List에 기초한 Index를 갖고 있는 Table에서 Index를 작성하고자 하는 경우에 발생
-----
현상 : ORA-1410 invalid ROWID
원인 : 1.적절한 Format으로 ROWID를 상술하지 않은 경우에 발생
2.지정된 ROWID가 존재하지 않은 경우에 발생
-----
현상 : ORA-01438: 지정한 정도를 초과한 값이 열에 지정되었습니다.
원인 : 지정한 자릿수를 초과한 Column이 존재한 경우에 발생
-----
현상 : ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "SYS.STANDARD", line 648
ORA-06512: at "BETH.BETH", line 6
ORA-06512: at line 1
원인 : SELECT 문에서 조건에 해당하는 row가 2건 이상
return되었을 때 발생하는 TOO_MANY_ROWS 에러와 동일한 에러이다.
조치 : 확인한 결과 DUAL table에서는 비록 2개의 ROWID를 볼 수는 없지만,
실제 2개의 row가 DUAL table에 존재하는 상황이다.
따라서, 다음 명령을 이용하여 여분의 필요없는 row를 delete해야 한다.
-----
현상 : ORA-1449 column contains NULL values; cannot alter to NOT NULL
원인 : 어떤 열을 필수적인 것으로 변경하고자 하나 적어도 테이블 내의 한 행이 그 열을 위한 NULL값을
가질 때 발생
-----
현상 : ORA-1452 cannot CREATE UNIQUE INDEX; duplicate keys found
원인 : 값이 독특하지 않은 일련의 열에서 독특한 인덱스를 작성한 경우에 발생
-----
현상 : ORA-1453 SET TRANSACTION must be first statement of transaction
원인 : 모종의 다른 SQL문 이후에 SET TRANSACTION문을 기동할 때 발생
-----
현상 : ORA-01458 Invalid length inside variable character string
원인 : DB Table field의 길이와 Host Variable의 길이 차이가 있을때 발생한다.
그러므로 Table field의 길이와 Host Variable의 길이를 비교해 본다. 혹은 Stored
Procedure의 Input Parameter가 Null 값으로 넘겨질 때도 발생한다.
조치 : DB Table field와 Host Variable의 길이를 조정한다.
Stored Procedure의 Input Parameter에 Null값을 0의 값을 채워서 넘긴다.
주의 : Stored Procedure에서 Cursor를 사용할 때
FOR ... LOOP를 사용할 때 주의를 해야한다.
FOR i IN 1..batch_size LOOP
FETCH get_emp
INTO
emp_name( i )
,job( i )
,sql( i )
;

IF get_emp%NOTFOUND THEN -- if no row was found
CLOSE get_emp;
done_fetch := 100; -- indicate all none
EXIT;
ELSE
done_fetch := 900; -- indicate all none
found := found + 1; -- count row
END IF;
END LOOP;
에서 Fetch Array의 0번째에 Data를 저장할 때 문제가 생긴다.
그러므로, emp_name( 0 )이라고 하면 Error를 발생한다.
-----
현상 : ORA-01476: divisor is equal to zero
원인 : Zero값으로 임의의 수를 나누었을때 발생
-----
현상 : ORA-01480: trailing null missing from STR bind value
원인 : 1.해당 Column의 Size 보다 더 큰 값이 들어온 경우에 발생
2.Character Type(CHAR, VARCHAR)의 Host variable인 경우 변수 선언시 Table의 Column size 만큼의 변수길이를 선언한 경우 발생
조치 : 1.해당 Column의 Size와 해당값을 확인
2.Character Type(CHAR, VARCHAR)의 Host variable인 경우 변수 선언시 Table의 Column size에 1를 더해 주어야 한다.
(데이터의 마지막에 NULL 문자를 포함해야 하기 때문에)
-----
현상 : ORA-1481 invalid number format model
원인 : 어떤 숫자 Format Model이 미정의 문자를 포함한 경우에 발생
-----
현상 : ORA-1547 : Failed to allocate extent of size 'num' in tablespace 'TOOLS
원인 : TABLESPACE가 에러에 명시된 ORACLE block 수 만큼의 요청된 EXTENT를 할당할 충분한 FREE
SPACE를 갖고있지 못할 경우에 발생
조치 : 1.해당 TABLESPACE내에서 연속된 영역의 ORACLE block 할당할 수 있도록 데이타 화일을 추가
2.TABLE의 STORAGE PARAMETER에서 INITIAL EXTENT, NEXT EXTENT의 크기를 조정하여 TABLE을
재구축
3.다음의 방법으로는 관련 TABLESPACE를 재구성하는 것
-----
현상 : ORA-1552 (CANNOT USE SYSTEM ROLLBACK SEGMENT FOR NON-SYSTEM TABLESPACE '%S')
원인 : SYSTEM TABLESPACE 이외의 TABLESPACE를 포함한 OPERATION을 위하여 SYSTEM TABLESPACE의
ROLLBACK SEGMENT를 사용할 경우에 발생
조치 : SYSTEM TABLESPACE에 하나 이상의 ROLLBACK SEGMENT를 추가한 다음, 데이타베이스 오브젝트를
생성
-----
현상 : ORA-1555 Snapshot Too Old
원인 : 1.데이타의 변경이 심한 데이타베이스에서 롤백 세그먼트의 갯수와 크기가 작을 경우에 발생
2.롤백 세그먼트가 손상되어 읽을 수 없게 된 경우
3.Fetch Across Commit(테이블에 대하여 Query가 커서를 열고 루프 내에서 데이타를 Fetch
하고 변경하고 커밋하는 과정에서 발생)
4.Delayed Block Clean Out(데이타 블럭이 변경되고 커밋되면 오라클은 롤백세그먼트 헤더에
그 트랜잭션이 커밋되었다고 기록하지만 데이타 블럭을 바로 변경하지는 않는다 (Fast
Commit). 그리고 다음 트랜잭션이 변경된 블럭을 요구할 때야 비로소 변경 시키는것
조치 : 1.커서가 Open된 상태에서는 커밋을 자주하지 않고 롤백 세그먼트 크기를 키워 나가도록
2.커서를 사용하기 전에 Full Table Scan을 해주면 예방이 가능
-----
현상 : ORA-1562(Failed to extend rollback segment(id = %s))
원인 : 1.사용중인 ACTIVE 상태의 ROLLBACK SEGMENT가 다음 EXTENT를 할당하고자 할 경우
2.해당 ROLLBACK SEGMENT에 대하여 발생 가능한 최대 EXTENT 수를 초과할때 발생
조치 : ROLLBACK SEGMENT의 재생성
-----
현상 : ORA-01578: ORACLE data block corrupted (file # 6, block # 3)
ORA-01110: data file 6: '/tmp/ts_corrupt.dbf'
원인 :
조치 : 해당 objects를 drop하고 recreate하여 처리
-----
현상 : ORA-01578
원인 : data block 에 corruption 이 생긴 경우에 발생.
조치 : 1.최선의 해결책은 backup 받아둔 file 을 restore 한 후 recover 작업을 하는 것이다.
2.backup datafile 을 restore 하고 recover 하지 않을 것이라면 우선, 어떤 object 에서 corruption 이 발생하였는지 확인해야 한다.
3.해당 segment 가 non-data dictionary index 라면, 해당 index 를 drop 한 후 재생성한다.
4.해당 segment 가 table 이라면, corruption 이 발생한 block 의 data 는 소실된 것이다.
5.만약 해당 table 에 대한 최근의 export dump file 이 존재한다면, 해당 table 을 drop 한 후 import 함으로써 복구할 수 있다.
6.corruption 이 발생한 non-clustered table 에서 corrupted block 을
access 하지 않고 나머지 data 들을 select 할 수 있도록 ROWID 를 이용할
수 있다.
7.만약 data dictionary 에 속하는 table, index 또는 rollback segment에
corrupted block 이 발생하였다면 Oracle Support 의 지원을 받는다.
8.일반적으로, ORA-1578 은 hardware 의 문제때문에 유발된다. 하지만 만약에
ORA-600[3374] 가 발생한다면 memory 상에서 corruption 이 발생한
경우이다. 이 경우 database 를 restartup 하면 문제가 해결될 수 있다.
-----
현상 : ORA-1591(Pending Transaction의 처리)
원인 : 분산 트랜잭션의 경우 2 phase commit수행 단계중에 fail이 발생하게 되면 관여된 일부 database에서는 rollback 혹은 commit이 되고, 일부는 distributed lock이 걸린 상태로 계속 지속될 수 있다.
이렇게 pending된 transaction에 대해서는 기본적으로 Oracle의 background process인 RECO process가 자동으로 정리하여 주나, 경우에 따라 자동으로 정리가 되지 못하는 상황이 발생
조치 : STEP 1: alert.log file을 check한다.
STEP 2: network 환경을 확인한다.
STEP 3: RECO process가 떠 있는지 확인한다.
STEP 4: DBA_2PC_PENDING을 조회해 본다.
STEP 5: DBA_2PC_NEIGHBORS view를 조회해 본다.
STEP 6: commit point site를 확인한다.
STEP 7: DBA_2PC_PENDING의 MIXED column을 확인한다.
STEP 8: DBA_2PC_PENDING의 STATE column의 값을 확인한다.
STEP 9: 불일치 사항을 파악하고 DBA_2PC_PENDING을 정리한다.

2PC에서 1st phase commit(xa_prepare)이 정상적으로 종료되면 Oracle의 dba_pending_transaction에 해당
Transaction에 대한 정보가 나타난다.

formatid 40
globalid 636861656A750000000000000000000000000000000000
5B5103A6BEC9900000DE8
branchid 0000006600000065

이 상태에서 일정한 시간 내에 2nd phase commit(xa_commit)에 끝나지 않으면 dba_2pc_pending에도 이
Transaction이 나타난다.

local_tran_id 4.24.3026
global_tran_id 40.636861656A750000000000000000000000000000000000
5B5103A6BEC9900000DE8
state prepared
mixed no
advice
tran_comment
fail_time
force_time
retry_time
os_user jun
os_termina
host chaeju
db_user
commit# 5332231

위에서 "일정한 시간"이란 용어를 사용했는데 Oracle의 문서에는 이에 관한 정확한 언급은 없다.
다만, 다른 Transaction에서 해당 레코드를 참조하려고 할 때 이미 lock이 걸려 있으므로 대기하는
시간에 대해서는 init.ora에서 지정하는 distributed_lock_timeout에 대해서만 언급하고 있다. 그런데
oracle 8.1.7에서는 distributed_lock_timeout을 설정하면 obsolete로 나온다.

이 시간 동안에 해당 레코드에 대한 lock이 풀리지 않으면 아래와 같은 에러를 만난다.

ORA-02049: time-out: distributed transaction waiting for lock

위의 에러가 발생한 이후에 이 레코드를 참조하려고 하면 1591 에러가 나타난다.

ORA-01591: lock held by in-doubt distributed transaction '4.24.3026'

보는 것처럼 ORA-01591 에러 메시지에는 local_tran_id가 있다. 이를 이용하여 dba_2pc_pending에서
global_tran_id를 조회하고, 이 데이터는 dba_pending_transaction의 formatid와 globalid로 이루어져
있으므로 이를 이용하여 dba_pending_transaction에서 branchid도 얻을 수 있다.

이들로 부타 아래와 같이 XID를 얻을 수 있다.

xid.formatid = dba_pending_transactions.formatid
xid.gtrid_length = len(dba_pending_transactions.globalid)
xid.bqual_length = len(dba_pending_transactions.branchid)
xid.data = dba_pending_transactions.globalid + dba_pending_transactions.branchid

여기까지는 Oracle로 부터 XID를 얻는 과정이다.

tpconvert(str, (char *)&xid, TPTOSTRING | TPCONVXID)를 이용하여 XID의 string 표현을 얻을 수 있고
이값을 이용하여 .TMIB 서비스를 호출하면 아래와 같은 정보를 얻을 수 있다.

TA_ERROR 0
TA_MORE 0
TA_OCCURS 1
TA_GRPCOUNT 2
TA_GRPINDEX 0
TA_GRPNO 102
TA_GRPNO 101
TA_TIMEOUT 9
TA_COORDGRPNO 102
TA_CLASS T_TRANSACTION
TA_STATE READY
TA_COORDLMID SITE1
TA_GSTATE READY
TA_GSTATE READY
TA_TPTRANID 0x0 0x3a6bec99 0xde8 0x28 0x0 0x0
TA_XID 0x0 0x3a6bec99 0xde8 0x28 0x66
TA_COORDSRVGRP APPGRP2
TA_LMID SITE1
TA_SRVGRP APPGRP2
TA_SRVGRP APPGRP1

위의 경우에는 아직 Tuxedo가 transaction에 대한 정보를 가지고 있기 때문에 별다른 조치가 필요없다.
하지만, Oracle의 dba_2pc_pending에는 있는데 Tuxedo에서 해당 Transaction에 대한 정보를 가지고
있지 않은 경우에는 Oracle에서 rollback force나 commit force를 이용하여 pending transaction을
정리해 주어야만 lock이 풀린다.
-----
현상 : ORA-1628, 00000, "max # extents (%s) reached for rollback segment %s"
ORA-1630, 00000, "max # extents (%s) reached in temp segment in tablespace %s"
ORA-1631, 00000, "max # extents (%s) reached in table %s.%s"
ORA-1632, 00000, "max # extents (%s) reached in index %s.%s"
원인 : 오브젝트의 익스텐트가 MAX # 에 도달 했기 때문에 발생되며 오브젝트의 MAXEXTENTS는
STORAGE 의 MAXEXTENTS 파라미터에 의해 결정
조치 : ALTER TABLE .. STORAGE (MAXEXTENTS n)를 사용하여 최대 MAXEXTENTS 값보다 작은 수로
MAXEXTENTS를 늘려준다.
-----
현상 : ORA-1652, 00000, "unable to extend temp segment by 6144 in tablespace "VESSEL"
원인 : 테이블이나 인덱스 등을 만들 때 자신의 TEMP TABLESPACE 가 아닌 곳에서 ORA-1652(temp
tablespace가 부족함) 에러가 발생
조치 : 에러메시지에서 보여주는 대로 해당 테이블스페이스에 Temporary Segment 가 생성될 만한
연속된 공간을 마련하여 주는 것
-----
현상 : ORA-1653
원인 : 특정 tablespace 에 space 가 부족해서 table의 extent가 일어나지 못해서 발생
조치 : user의 default tablespace 를 변환한 후, 이 default tablespace
안에 create table을 다시 한 후 sql*loader 를 실행한다
-----
현상 : ORA-1654 ERROR ON INDEX SEGMENT
원인 : tablespace가 적어 extent 영역을 할당할 수 없어서 발생
조치 : datafile을 추가 시 이전값 이상의 사이즈를 추가해야 함.
-----
현상 : ORA-1722 invalid number
원인 : 수치값이 불법일 경우
-----
현상 : ORA-1747 열명을 올바르게 지정해 주십시요.
원인 : 열명이 다른 경우(SQL문장 기술시 첫번째 열명 앞에 Comma를 삽입한 경우)
-----
현상 : tb_ra315 insert error ORA-02291: integrity constraint (SCRJAPPR.A315_E007_FK)
violated - parent ....
원인 : Table과 관련된 Reference 관계로 parent table의 data가 없는 관계로 data 입력불가
조치 : Reference 관계를 끈어주든지 아니면 관계된 Table에 Data를 모두 입력하는 방법.
-----
현상 : ORA-02303: cannot drop or replace a type with type or table dependents
원인 : Type이나 table의 dependency가 있는 type을 drop하거나 replace하고자 할 때 발생.
조치 : SQL Reference guide에 의하면 DROP TYPE FORCE 옵션은 recommend하지 않는다.
왜냐하면 이 옵션을 쓰게 되면 복구가 불가능하고 dependency가 있던 table들은
access하지 못하는 결과를 초래한다.
-----
현상 : ORA-03113: end-of-file on communication channel
원인 : 1.이전에 작동했던 해당 instance의 shared memory segment들이 아직 system에 남아있어서 발생.
2.서버의 Oracle 쉐도 프로세스가 예기치 않게 종료된 경우 발생.
3.SQL*NET 드라이버가 Unix의 ORACLE 실행 파일과 연결되지 않아 발생한 경우.
4.서버쪽의 기계 손상이나 네트워크 고장인 경우.
5.네트워크에서 두 서버가 같은 노드 이름을 가질 때에도 이 오류가 발생.
6.모든 원인은 결국 클라이언트가 서버로부터 어떤 정보를 읽으러 갔다가 거기서 더 이상 연결이 없음을 발견했다는 뜻임.
7.Oracle XA를 사용하는 AP 서버 혹은 TMS 서버가 떠 있는 상황에서 연결된 DB를 재기동 시키거나 혹은 다른 문제로 인해서 데이터베이스와의 연결이 끊어진 경우에 발생
조치 : shared memory를 check하여 oracle이 소유하고 있는 shared memory segment를 삭제하여 문제를 해결.
자동으로 재접속을 하기 위해서는 TUXWA4ORACLE(WorkAround For Oracle) 환경변수를 1로 설정하면 해당 서버가 오라클에 접근하여 3113 에러가 발생하는 순간에 재접속이 이루어진다.
(XA 서버에만 해당되며 Non-XA 서버의 경우는 사용자 coding에 의해서 동일한 기능을 구현할 수 있다.)
-----
현상 : ORA-3114 Error( not connected to ORACLE )가 발생
원인 : ORACLE이 Shutdown 되었다.
조치 : ORACLE이 떠 있는지 확인하고, Server를 새로 기동한다.
-----
현상 : ORA-3121
원인 : SQL*NET V2를 통해 연결하려 할 때 연결 스트링에 'tns:'net접두어를 사용하지 않은 경우
조치 : 구버전인 SQL*NET V1의 net 접두어 (SQL*Net TCP/IP에 대한 "t:"등)를 사용하지 않도록 주의
하십시요.
-----
현상 : ORA-4068 existing state of packages%s%s%s has been discarded
원인 : 응용프로그램 실행 중에 사용하고 있는 Stored Procedure를 Compile하는 경우에 발생
조치 : 응용프로그램을 재기동시킨다.
-----
현상 : ORA-4091 table name is mutating, trigger/function may not see it
원인 : DataBase Trigger가 Transaction 내에서 변경된 테이블에 대하여 Query를 기동할 때 발생
조치 : 1.PL/SQL table을 생성한다.
2.BEFORE STATEMENT trigger를 생성한다.
3.AFTER ROW trigger를 생성한다.
4.AFTER STATEMENT trigger를 생성한다.
5.data insert 및 확인
-----
현상 : ORA-4092 cannot COMMIT or ROLLBACK in a trigger
원인 : 1.Trigger가 COMMIT or ROLLBACK을 실행하고자 할 때 발생
2.Trigger가 내장 프로시저, COMMIT나 ROLLBACK될 함수, 패캐지 서브프로그램을 호출한 경우
-----
현상 : ORA-6106,ORA-6120 NETTCP : socket creation failure
원인 : WIN V1.X용 SQL*NET TCP/IP는 SQLTCP.DLL과 SQLTCP1.DLL들은 ORACLE용 연결 스트링이 TCP/IP
프로토콜 스트링으로 변환되면 OCI DLL에 의해 작업 진행중에 올려집니다. ORACLE INTERFACE
DLL은 SQLTCP.DLL을 먼저 올리려고 합니다. 이것이 실패하면 DOS TSR 버전의 드라이버를
찾습니다. 두 가지 모두 실패하면 ORA-3121 메세지가 나옵니다.
-----
현상 : ORA-6108
원인 : 1.부적절한 machine, 또는 machine는 맞지만 틀린 포트를 지정할 때 발생
2.TCP/IP 레이어는 모든 연결 요구를 Listener의 소켓 큐에 넣을 수 없을 경우 발생
3.네트워크가 아주 혼잡하고 호스트에 도달하려는 중에 시간이 종료할 경우
조치 : 1.클라이언트에서 호스트 Machine에 대해 ping을 실행하십시요. 대부분의 PC TCP/IP업체는
"ping" 유틸리티를 제공합니다. 클라이언트 Machine에서 다음을 입력하십시요
ping <host IP address>
이 방법으로 잘 되지 않으면 아마도 호스트 machine이 down된 것입니다. IP 주소를 사용
하여 호스트에 대해 ping을 성공적으로 실행할 수 없으면, 서버의 호스트 이름을 사용하여
ping을 실행해 보십시요.
ping <hostname>
호스트 이름을 사용하여 ping을 실할 수 없으면 TCP/IP 구성을 점검하십시요. 호스트 이름
을 가지고 ping을 실행할 수 없으면, 연결 스트링에 호스트 이름을 사용하여 SQL*NET와
연결할 수 없습니다.
2.SQL*NET TCP/IP Listener가 해당 서버에서 실행중인지 점검하십시요. 서버의 UNIX프롬프트
에서 다음을 입력하면 됩니다.
ps -al|grep "orasrv"
이 때 최소한 한 행이 표시되어야 합니다. 그렇지 않으면 UNIX 프롬프트에서 "orasrv"
또는 "tcpctl start"를 입력하여 수화자를 띄우십시요. SYSADMIN 특권을 가지고 해당 기계
에 로그인해야 합니다.
3.서버쪽에서 루프백을 할 수 있는 지, 다시 말해서 PC 클라이언트에서 지정한 것과 같은
연결 스트링을 사용하여 서버의 툴을 연결할 수 있는지 점검하십시요. 예를 들면, 서버의
SQLPLUS 또는 SQLDBA를 호출하고 서버의 SQLPLUS 또는 SQLDBA 프롬프트에서 다음을 입력
하십시요.
CONNECT USERNAME/PASSWORD@t:<servername>/<portnum>:<sid>
4.루프백 성사되면 호스트 서버의 ORASRV 포트 번호를 확인하십시요. (대부분의 기계에서
SERVICE 파일은 /etc 디렉토리에 있습니다.) 또한 "tcpctl" 유틸리티를 사용하면 대부분의
UNIX 기계에서 ORACLE Listener를 시작하거나 멈출 수 있습니다. "tcpctl stop"로 Listener
를 종료하십시요. "tcpctl start"으로 다시 시작하십시요. 이때 시작 포트에 관한 정보가
표시됩니다.
5.이것이 성공하면 포트를 지정하지 말고 포트를 연결해 보십시요.
t:<servername>:<sid>
연결되지 않으면 클라이언트에서 SERVICE 파일을 정확하게 설정하 않았기 때문입니다.
a)WINDOWS\WIN.INI를 점검하여 [Oracle] 부분의 ORA_CONFIG 매개 변수가 어떤 구성 파일을
지시하고 는지 알아보십시요. 이폴트는 다음과 같습니다.
[Oracle]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
b)ORACLE.INI 파일을 보고 TCP_SERVICES_FILE 매개변수가 설정되었고 SERVICES 파일을 지시
하고 있는 지 확인하십시요.
c)SERVICES 파일을 보고 다음 항목이 있는 지 확인하십시요.
orasrv 1525/tcp oracle
6.또한 서버가 SQL*NET V2가 아니라 SQL*NET V1을 실행중인지 확인하십시요.
7.결 스트링의 재시도 매개변수를 증가시켜 보십시요. 재시도 횟수를 지정하는 구문은 다음과
같습니다.
t:host[/service]:SID[,buffer-size][:conn-retries]
conn-retries의 디폴트는 1입니다.
8.VAX에 연결할 경우에는 VAX config.ora 파일에 다음행이 있는지 확인하십시요.
SQLNET USERNAMEMAP*=*
이것은 VAX account가 없는 PC가 디폴트 사용자 account을 사용하여 연결 할 수 있게 해
줍니다.
-----
현상 : ORA-6110 "NETTCP: message send failure"
원인 : Windows 클라이언트의 TCP/IP사이에 버퍼 조정문제가 있을 때 발생
조치 : 1.버퍼 크기를 연결 스트링에 포함시켜 일정한 크기로 고정하는 것
t:<servername>:<sid>,<buffersize>
연결 스트링에 버퍼 크기를 포함시킨 후에도 여전히 ORA-6110이 발생하면 더 작은 값을
사용해 보십시요. WINDOWS용 SQL*NET TCP/IP의 기본 버퍼 크기는 4096입니다. 이것을
1024로 사용하면 대개 ORA-6110에러가 없어집니다.
2.서버쪽
1)서버에서 루프백을 수행할 수 있습니까? 다시 말해서 PC 클라이언트에서 지정한 것과
같은 연결 스트링을 사용하여 서버의 툴을 연결할 수 있습니까? 예를 들어 서버에서
SQLPLUS 또는 SQLDBA를 호출하고 에러가 없어집니다.
CONNECT USERNAME/PASSWORD@t:<servername><portnum>:<sid>
루프백을 실행하면 실제 문제를 더 잘 보여주는 다른 에러가 나타나는 수도 있습니다.
2)ORA-6110은 Oracle실행 파일에 사용 권한이 정확하게 설정 되어 있지 않으면 Unix 서버에
연결할 때도 발생할 수 있습니다. Oracle과 orasrv의 사용권한은 다음과 같이 설정되어야
합니다.
>chmod 6755 oracle
>chmod 6755 orasrv
이 때, Permission는 다음과 같이 설정됩니다.
-rwsr-xr-x 1 oracle dba ...size ...date oracle
-rwsr-xr-x 1 root dba ...size ...date oracle

3)ORA-6110과 틀린 네트워크 주소
TCP/IP 네트워크에서 중복 IP주소가 살아 있으면 ORA6110이 발생할 수 있습니다. 네트
워크의 모든 IP주소가 고유의 것인지 확인하십시요.
-----
현상 : ORA-6122 "NETTCP: setup failure
원인 : SQL*NET 구성이 적절하게 설정되지 않은 상태에서 WINDOWS용 SQL*NET TCP/IP를 가지고 연결
하려 할 때 발생
조치 : 1.WINDOWS\WIN.INI를 조사해 보십시요. ORA_CONFIG 매개 변수를 정의하는 ORACLE 부분이
있어야 합니다
[Oracle]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
2.ORACLE.INI(또는 ORA_CONFIG 매개변수가 지시하는 파일)을 보십시요. ORACLE_HOME이
WINDOWS용 SQL*NET TCP/IP와 다른 Oracle Windows 응용 프로그램이 설 된 디렉토리를
지시하는 지 확인하십시요. 디폴트는 다음과 같습니다.
ORACLE_HOME=\ORAWIN
3.또한 ORACLE.INI에 TCP_VENDOR를 정확하게 설정했는지도 확인하십시요.
4.경로에 C:\ORAWIN\BIN(또한 ORACLE_HOME을 설정한 BIN 디렉토리)이 있는지 확인하십시요.
DOS프롬프트에서 SET을 입력하고 <return>을 누르면 됩니다. 이명령은 경로를 보여줍니다.
5.ORAWIN\BIN 디렉토리에 SQLTCP.DLL과 SQLTCP1.DLL이 모두 있는지 확인하십시요.
6.경로의 다른 어떤 디렉토리에도 SQLTCP.DLL이 없는 것을 확인하십시요.
7.ORAWIN\BIN 디렉토리와 경로의 다른 디렉토리에 MSOCKLIB.DLL이 있는 지 확인하십시요.
또한 파일의 두 복사본을 가지고 있지 않도록 하십시요. 복사본이 둘일 경우, 이전 복사본
의 이름을 바 면 문제가 줄어들 수 있습니다.
8.WINDOWS 디렉토리에 VSL.INI 파일이 있는지 확인하십시요. 만약 없으면 ORACLE INSTALLER
를 통해 SQL*NET를 다시 입력하십시요.
-----
현상 : ORA-6136, 00000, "NETTCP: error during connection handshake"
원인 : 1.Client and Server 환경에서 간혹 SQL*NET으로 Server에 접속하려고 할 경우
2.Unix Server에서 $tcpctl stop 으로 orasrv의 Process를 정지시키려고 해도 아무런 반응
없이 Holding되는 경우가 발생
조치 : 1.TCPCTL Utility를 이용하여 다음의 Option을 부여하여 Start하는 방법.
$tcpctl start listen=30 timeout=30 forkon listen=<queue size>이며, 청취자 열의
크기를 지정.
timeout=<seconds>이며, 지정된 시간에 orasrv와의 응답 확인 시간을 나타냄.
forkon SQL*net이 orasrv process에 접근하는 방법을 나타냄.
System에 따라서 forkon option이 적용 않되는 경우도 있음.
2.Client에서 접속을 하여 사용 다가 비정상 종료(Session이 맺어진 상태에서 Client의
Power Off)를 하여 Server에 Processor가 남아 있고, orasrv를 통해 접속할 수 있는
Session의 수가 점점 줄어들 경우가 있는 데 이러한 경우에는 orasrv를(tcpctl stop or
UNIX kill command를 이용)강제로 종료 시고 다음과 같이 Start 시켜 주십시오.

#nohup tcpctl start ( Client의 비정상 종료가 Orasrv에는 영향을 미치지 않음)
또는
#orasrv (ORACLE_HOME\bin directory에서 직접 orasrv processor를 띄운다)
-----
현상 : ORA-06502 : PL/SQL : 값(수치) 오류입니다.
원인 : DB Column과 Host variableㅇ의 길이가 맞지 않은 경우.
조치 : DB Column과 Host variableㅇ의 길이를 확인하고 길이를 동일하게 한다.
-----
현상 : ORA-06533: Subscript beyond count
원인 : VARRAY는 default 로 3개의 element 이상을 가져 올수 없기 때문.
조치 : EXTEND method를 이용하여 해결할 수 있다.
-----
현상 : ORA-06571
원인 : SQL문 안에서 Stored function을 call하여 사용하는 경우 발생.
조치 : 기본적으로 stored function이나 procedure, package에서의
DML 문장의 사용은 보장이 되는 기능이나, sql list에서의 stored function의
사용은 몇 가지 제약 조건을 가지고 수행이 가능합니다.
-----
현상 : ORA-1119: error in creating database file
ORA-7515: sfccf UIC GROUP <= MAXSYSGROUP - file operations not allowed
원인 : VMS에서만 발생하는 에러로 DATAFILE을 생성하려는 Directory의 Owner가 DBA user가 아닐때 발생.
조치 : Datafile을 생성하려는 Directory의 Owner를 Oracle DBA user로 변경시켜 주어야 한다.
-----
현상 : ORA-9241, ORA-9301
원인 : 개발툴이 해당 툴 또는 SQL*NET에 필요한 메세지 화일을 찾을 수 없을 때 발생
조치 : ORACLE.INI 파일에 LOCAL = <V2 service name>을 추가한다. 만일 ORACLE.INI 파일에 LOCAL
파라미터를 추가한 후에도 계속 ora-9301 에러가 계속 발생한다면 autoexec.bat 파일에 SET
CONFIG = <PATH> \ORACLE.INI를 추가한다.
[주의 1]CONFIG가 ORACLE.INI를 지시하도록 설정하면 나중에 다시 설치할 문제가 발생할 수
있다. 그럴 때는 AUTOEXEC.BAT 에서 SET CONFIG 행을 삭제하고 다시 Booting 한후
설치를 시작한다.
[주의 2]MS ACCESS를 이용하여 ORACLE의 데이타를 질의할 경우는 환경변수를 다음과 같이
설정한다.
SET CONFIG_FILES = <path> \ORACLE.INI
[주의 3]SET 다음의 CONFIG 나 CONFIG_FILES 은 반드시 대문자 이어야 한다.
-----
현상 : ORA-9352
원인 : nt 에서 service 의 problem 발생.
조치 : 1.background services and processes 를 띄우기
dos>oradim80 -startup -sid SID -starttype srvc,inst -usrpwd password -pfile filename
2.여러 개의 instance 를 띄우고자 하는 경우
- ORACLE_SID 를 setting 한다.
c:\> set oracle_sid =sid
- server manager 실행
c:\>svrmgr30
svrmgr>connect internal/passwd
-----
현상 : ORA-12004/ORA-12034
원인 : master table의 snapshot log가 있는 table에 대해서, snapshot이 추가로
생성되고 나면 snapshot을 생성하기 시작한 시간과, 기존의 snapshot이 log를
refresh해간 시간을 비교하여 새로운 snapshot 생성시작 시간이 더 빠르면
ora-12004가 발생
조치 : 생성하고자 하는 snapshot에 대한 master table의 다른 snapshot들을 refresh하지 못하도록 하거나, refresh하지 않는 시간에 새로운 snapshot을 생성하여야 한다.
refresh 못하도록 막는 방법으로는 일시적으로 snapshot job을 broken시킨 후 snapshot이 생성된 후 다시 broken을 false로 하면 된다.
-----
현상 : ORA-12154
원인 : tnsnames.ora 파일의 Alias처럼 정의된 Connect String으로 사용하는 db_alias를 찾지 못할 경우 발생
-----
현상 : TNS-12203 "TNS:unable to connect to destination"
원인 : 1.WINDOWS용 TCP/IP 어댑터를 설치하지 않은 상태에서 연결하려 할
2.TNS-12203 에러는 WINDOWS용 ORACLE SQL*NET소프트웨어가 ORACLE 홈 디 렉토리를 찾을 수
없다는 의미일 수 있습니다.
3.TNSNAMES.ORA가 ORACLE 홈 디렉토리 아래의 NETWORK\ADMIN에 있는지 확인하십시요.
4.서버쪽에서 실행중인 SQL*NET V2 TCP/IP Listener가 없어도 TNS-12203이 발생
5.연결할 SERVICES 이름에 대해 CONNECT DESCRIPTOR에 정확한 ADDRESS 매개변수를 지정했는지
확인하십시요.
6.JSB VSL 소켓이 초기화되지 않으면 TNS-12203 이 발생할 수 있습니다.
7.TNS-12203에 이어 실제 문제가 무엇인지 더 자세하게 나타내 주는 또 다른 에러가 발생할 수
있습니다.
조치 : 1.SQL*NET TCP/IP V2는 SQL*NET V2와 V2 TCP/IP 어댑터 등 두가지 제품으로 구성됩니다.
이들은 별도의 두 키트로 되어 있는데, 반드시 두 키트를 모두 설치해야 합니다.
2.WIN.INI파일의 ORACLE 부분에 다음 항목이 있는지 확인하십시요.
[ORACLE]
ORA_CONFIG=C:\WINDOWS\ORACLE.INI
WINDOWS디렉토리가 C:\WINDOWS가 아니면, 위 행의 C:\WINDOWS 부분을 그 이름으로 바꾸십시요
그런 다음, ORACLE 소프트웨어를 다시 설치하십시요. ORACLE.INI 파일이 있으면 ORACLE.INI
파일에 다음 행이 있는지 확인하십시요.
ORACLE_HOME=C:\ORAWIN
ORACLE 홈 디렉토리가 C:\ORAWIN이 아니면 위 행의 C:\ORAWIN 부분을 이름으로 바꾸십시요.
3.ORACLE 홈 디렉토리는 ORACLE.INI(또는 WIN.INI의 ORA_CONFIG매개변수가 지시하는 파일)의
ORACLE_HOME 에 의해 정의됩니다.
4.서버쪽에서 실행중인 SQL*NET V2가 있는지 확인하십시요. 서버쪽에서 Listener Control 유틸
리티(LSNRCTL)를 사용하면 서버의 V2 Listener가 실행중인지 확인할 수 있습니다. 서버에서
"LSNRCTL STATUS"명령을 실행하십시요. Listener Control이 유틸리티 대해서는 SQL*NET
Administrator's Guide를 참조하십시요.
5.정확한 ADDRESS 매개변수를 사용중인지 확인하는 방법은, WINDOWS 클라이언트에서 사용 할 것
과 같은 ADDRESS 매개 변수를 가진 TNSNAMES.ORA를 사용하여 서버에서 루프백을 해 보는 것
입니다. 루프백을 수행한다는 것은 데이타베이스와 같은 기계에서 SQL*DBA 등을 호출하고
연결 스트링을 지정함으로써 SQL*NET V2를 통해 연결한다는 뜻입니다.
6.문제를 해결하려면 다음 사항을 점검하여 JSB VSL 레이어가 정확하게 초기화되었는지 확인
하십시요.
1)ORACLE.INI 파일(또는 WIN.INI의 ORA_CONFIG 매개변수가 지시하는 파일)의 업체키 매개
변수 TCP_VENDOR가 정확하게 설정되었는 지 확인하십시요
2)ORACLE_HOME\BIN 디렉토리에 MSOCKLIB.DLL이 있는지 확인하십시요.
3)ORACLE_HOME\BIN 디렉토리에 선택된 JSB 업체 특유의 DLL이 있는지, 또는그 JSB 업체 특유
의 TSR 파일이 실행되는 지 확인하십시요.
4)WINDOWS 홈 디렉토리에 VSL.INI 파일이 있는 지 확인하십시요.
7.화면에서 다른 에러가 보이지 않으면 ORACLE_HOME\NETWORK\LOG 디렉토리의 SQLNET.LOG 파일을
점검하십시요.
-----
현상 : TNS-12533

출처 : Tong - atc17cjh님의 oracle통

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:26
반응형

ERROR_CODE,DESCRIPTION
ORA-00000   

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:24
반응형

쿼리를 통해 오라클 데이터베이스의 정보를 조회할때 사용하세요.

구분 테이블명 설명
오브젝트 USER_OBJECTS (OBJ) 모든 오브젝트에 대한 정보를 지원 오즈젝트 유형, 작성시간, 오브젝트에 사용된 최종 DDL 명령, alter, grant 및 revoke 등
테이블 USER_TABLES (TABS) 테이블에 대한 정보
USER_TAB_COLUMNS (COLS) 컬럼에 대한 정보
USER_VIEWS 뷰에 대한 정보
동의어 USER_SYNONYMS (SYN)
시퀀스 USER_SEQUENCES (SEQ)
제약조건 USER_CONSTARINTS  
제약조건열 USER_CONS_COLUMNS 제약 조건을 가진 열에 대한 정보
제약조건의 예외사항 EXCEPTIONS 제약조건을 활성화시 에러사항에 대한 정보
테이블 주석 USER_TAB_COMMENTS 테이블/뷰에 대한 주석
열 주석 USER_COL_COMMENTS 열에 대한 주석
인덱스 USER_INDEXES (IND) ( 인덱스에 관한 정보)
인덱스 열 USER_IND_COLUMNS 인덱스열에 대한 정보
클러스터 USER_CLUSTERS (CLU) 클러스터와 관련된 정보
데이터베이스 링크 USER_DB_LINKS 링크에 관련된 정보
스냅샷 USER_SNAPSHOTS  
스냅샷 로그 USER_SNAPSHOT_LOGS  
트리거 USER_TRIGGERS  
프로시저, 함수 및 패키지 USER_SOURCE  
코드 오류 USER_ERRORS  
테이블스페이스 USER_TABLESPACES  
영역 할당량 USER_TS_QUOTAS 테이블스레이스 단위로 사용자가 이용할 수 있는 영역의 최대크기와 할당된 영역의 크기 파악에 대한 정보
세그먼트와 익스텐트 USER_SEGMENTS
USER_EXTENTS
 
여유 영역 USER_FREE_SPACE 현재 여유로 표시된 영역이 얼마인지에 대한 정보
사용자 USER_USERS  
자원 제한량 USER_RESOURCE_LIMITS  
테이블 권한 USER_TAB_PRIVS  
열 권한 USER_COL_PRIVS  
시스템 권한 USER_SYS_PRIVS  

EX)

그럼 SEQUENCE정보를 알고 싶을때는 어떻하면 될까요?

SELECT * FROM USER_SEQUENCES

 

참고)  

DICTIONARY(DICT) 뷰

     - 데이터 사전 및 동적 성능 뷰에 대한 정보를 알고 싶으면 DICTIONARY 뷰나

         DICT_COLUMNS 뷰를 조회하면 됩니다.

 

      - 조회 할 수 있는 모든 데이터사전의 테이블이름과 설명을 조회 할 수 있습니다.

         물론 설명은 영문으로 되어 있습니다.

 

      - 동의어인 DICT를 이용해서도 똑같은 정보를 조회 할 수 있습니다.

 

     SQL> SELECT * FROM DICTIONARY WHERE table_name LIKE '%INDEX%';

     SQL> SELECT * FROM DICT WHERE table_name LIKE '%INDEX%';

 

 

DICT_COLUMNS 뷰

       - 뷰를 질의하면 해당 데이터사전의 컬럼에대한 정보를 조회 할 수 있습니다.

        SQL> SELECT * FROM DICT_COLUMNS WHERE TABLE_NAME LIKE '%INDEX%';

        SQL>SELECT * FROM dict WHERE table_name LIKE UPPER('%&데이타사전%');

출처 : Tong - atc17cjh님의 oracle통

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:14
반응형

Linux Oracle 설치와 활용(Ⅰ)



서  론

    인터넷 서버로서의 많은 가능성을 보여주고 있는 Linux는 사실상 미묘한 문제가 있었다. Apache는 웹서버로서의 더할 나위 없는 정상의 고지에 있었고, Samba는 많은 작업들을 MS WINDOWS로부터 해방시켜 주었으며 X WINDOW는 MS의 그것과 못지 않은 많은 윈도우 매니저들로 치장되었다. 문제는 좀더 신뢰성 있는 서비스들이었고 그것은 대체로 D/B 시스템과의 밀접한 관계를 가진다. 물론 Linux에서도 아주 훌륭한(그것도 공개의) D/B 들이 존재하는데 MiniSQL이나 Postgresql등이 그것이고 MySQL같은 조금 특별한(반 공개/반 상용) 것들도 있다. 하지만, 이것들이 아무리 훌륭하다고 해도 사용자의 입장에서는 누구하나 책임져주지도, 기술지원 해주지도 않는 이러한 D/B 시스템들에 자신의 귀중한, 혹은 상업적인 목적의 자료를 담아두고 맘 편해 하는 이는 별로 없을 것이다. 그러나 지금은 여러 우여 곡절 끝에 Linux는 Oracle 을 위시한 대형 D/B시스템 업체들로부터 지원을 받게 되었다. 대형 상용 D/B시스템 업체들의 지원과 엔터프라이즈급 성능을 갖춘 커널 2.2의 발표로 인터넷 서버 시장을 넘어 이제는 국내에서도 엔터프라이즈 플랫폼으로 Linux 가 강력하게 등장하고 있다.

 

목  적

    이 글의 목적은 간단하다. 여러 D/B벤더들의 제품중에서 유독 한국에서 초강세를 보이고 있는 Oracle (server for Linux 8.0.5)를 Linux상에서 설치하는 방법과 운용 방법, 그리고 간단한 pro-c 사용법, 그리고 한참 주가를 올리고 있는 php3와의 연동을 약 3회분에 걸쳐 살펴본다. Test에 사용된 Oracle server는 정품이 아니고 Oracle Home Page에 가면 쉽게 구할 수 있는 개발자 버전임을 알려둔다.

    ◎ 시스템 요구사항

    메모리 : 활용의 목적이 아닐 경우 32메가도 가능

    스왑영역 : 일반적으로 RAM의 3배 크기의 스왑영역이 권장. 1GB이상의 RAM을 가진
                   시스템에서는 2배 크기의 스왑영역이 권장된다.

    디스크 : 최소한 4개(At least four devices) : Oracle 소프트웨어 설치를 위해 하나, 나머지
                세개는 OFA호환 데이터베이스를 생성하기 위해 사용된다.
                - 활용의 목적이 아닐 경우 한 개의 디스크라도 상관없다.
                - 활용의 목적이라면 최소 2개의 물리적 디스크 추천 (리눅스, 오라클 )
                - 다운로드 받은 파일과 압축을 풀고 설치할 용량으로 최소 1기가 이상이 필요하다.

    Operating System : Linux 2.0.34
    - 오라클의 리눅스 팀은 실제 2.0.33 이상이라고 한다.
    - 필자는 참고로 국내에서 유명한 알짜 리눅스 5.2를 사용하였으며 커널은 2.0.36을
       사용하였다.

    System Libraries : GNU C Library, version 2.0.7
    - 문서상에서는 2.0.7이상을 요구하고 있으나 오라클의 리눅스 개발 팀으로부터의 설명으로는
       실제 2.0.6이상이면 된다고 한다.
       GLIBC 2.1.x 용으로는 패치 파일이 따로 나와 있다. 아직 테스트는 해보지 못했다.

    Window Manager : 어떤 X 윈도우 시스템도 가능
    -솔라리스에서는 X-window 상에서 관리할 수 있는 svrmgrm 이 있지만 Linux에서는 현재
      커맨드 라인 모드에서만 작동하는svrmgrl 만이 존재한다.

 

가. root 로 하여야 할일

    1. 다운로드 http://technet.oracle.com에서 오라클 리눅스를 다운 받는다.

    2. /usr/src 에 다운로드 받은 805ship.tgz 파일을 옮긴 후 /usr/src/ora에서 압축을 푼다.
       /usr/src/ora 상에 다음과 같은 파일과 디렉토리가 생성되었을 것이다.

        # ls
        DST.LST          network/           plsql/
        nlsrtl/              precomp/          RELDESC.TXT
        ocommon/       rdbms/             bin/
        oemagent/       slax/                oracore/
        sqlplus/           jdbc/                orainst/
        svrmgr/           lib/                   ord/
        unix.prd          otrace/              unixdoc/

    3. Create Mount Points
        이제 오라클을 설치할 위치를 정하는 단계이다. 여기서는 /home/oracle에 오라클을 설치
        하는 것으로 가정하겠다. 이 위치에 오라클을 설치할 하드 디스크 파티션을 마운트 시켜야
        한다.
    - 대부분의 사용자가 하나의 파티션에 리눅스를 설치할 것이다. 그렇지만 만일 두개 이상의
       하드디스크 파티션을 이용할 것이라면 /etc/fstab의 내용을 적합하게 고쳐야 한다.
       각 파티션의 내용을 다음에 설명하도록 하겠다.

    4. DBA group 생성
       /etc/group 파일에 dba라는 그룹을 생성한다.

       # groupadd dba
       혹은 직접 vi edit로 /etc/group을 편집할 수도 있다.

    5. 리눅스 커널 설정
        오라클8 서버의 SGA 구조를 수용하기 위해 리눅스 커널의 Interprocess Communication
        (IPC) 파라메터들을 설정해야 한다. 시스템이 SGA를 수용하기에 충분한 shared 메모리를
        가지지 않았다면 데이터베이스를 실행할 수 없을 것이다.

    다음에 상응하는 커널 파라메터를 설정한다.

    maximum size of a shared memory segment(SHMMAX)
    maximum number of shared memory segments in the system(SHMMNI)
    maximum number of shared memory segments a user process can attatch(SHMSEG)
    maximum amount of shared memory that can be allocated system-wide(SHMMNS)
    SHMMAX*SHMSEG에 의해 허용되는 전체 shred 메모리 크기가 결정된다.

    ㄱ) SHMMAX = 4294967295 : 단일 공유 메모리 세그먼트의 최대크기(바이트단위)
    ㄴ) SHMMIN = 1 : 단일 공유메모리 세그먼트의 최소크기(바이트)
    ㄷ) SHMIMNI = 100 : 공유메모리 지시자(identifiers)의 갯수
    ㄹ) SHMSEG = 10 : 각 프로세스에 부여될 수 있는 공유메모리 세그먼드의 최대 갯수
    ㅁ) SEMMNS = 200 : 시스템 내의 세마포어 갯수
    ㅂ) SEMMNI = 70 : 세마포어 지시자(identifiers)의 갯수. SEMMNI은  동시에 생성될 수 있는
                               세마포어 갯수를 결정한다.
    ㅅ) SEMMSL = PROCESSES 초기화 파라메터의 값과 같거나 크도록, 하나의 세마포어 안에
                                            존재할 수 있는 세마포어들의 최대 갯수.
                                            오라클 프로세스들의 최대 갯수와 같아야 한다.

    솔라리스의 경우에는 다음의 값들을 /etc/system 파일에서 설정해 주어야 하지만, 설정을 하지 않아 문제가 발생한적은 없었다. 기본 커널 상태로 놓고 인스톨하여도 무방하다. (레드헷의 디폴트 커널이든 다시 컴파일한 커널이든)

    6. 오라클 관리자 계정 생성
        adduser 혹은 useradd 로 dba그룹에 속하는 유저 oracle을 생성한다.

      ㄱ) adduser 명령으로 oracle user를 생성한다.
           # adduser oracle
      ㄴ) vi /etc/passwd 명령을 사용하여 oracle user 의 설정 값을 위에서
          설명한 것대로 바꾼다. - dba gid와 같아야 한다.

    7. oratab 파일 생성
       오라클 인스턴스에 대한 정보는 oracle 소유의 oratab 파일에 저장된다.
       하지만 이 스크립트를 root로 실행해서 /etc 디렉토리에 oratab 파일이 생성되도록 한다.

       실제 인스톨과정에서 oratab.sh을 실행하면 ORACLE_OWNER환경변수가 설정되어 있는지
       묻고 있다. 따라서 ORACLE_OWNER을 다음과 같이 설정한다.

      #export ORACLE_OWNER=oracle

 

나. oracle user 로 할 일

    1. ~/.bash_profile의 수정
       ( sh을 사용할 경우 .profile을 수정한다. redhat 리눅스를 기준으로 설명한다.)
       oracle로 접속하여 다음과 같이 .profile을 만든다. RedHat에서는 .bash profile 이다.

      export
      ORACLE_HOME=/home/oracle/app/oracle/product/8.0.5
      export
      LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORACLE_HOME/jdbc/lib
      export ORACLE_SID=linux
      export ORACLE_TERM=386
      export
      ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
      export PATH=$PATH:$ORACLE_HOME/bin
      export TMPDIR=/tmp
      export
      CLASSPATH=$ORACLE_HOME/jdbc/lib/classes111.zip
      umask 022
      (위에서 export 다음의 줄을 export 뒤에 나와야 한다.)

    위의 경우는 “root 작업 4”의 “Create Mount Points”에서 이야기한 오라클을 설치할 경로로 /home/oracle인 경우이다.

각 설정에 대한 설명

    ORACLE_HOME :
    오라클을 /home/oracle에 설치하기로 하였으므로 /home/oracle/app/oracle/product/8.0.5로 지정된다.

    LD_LIBRARY_PATH :
    오라클의 동적/정적  라이브러리의 경로를 나타내는 환경변수로 Pro*C나 PHP등을 사용할 때 중요하게 적용된다.

    ORACLE_SID :
    오라클 인스턴스의 이름이다. 영문자로 3-4글자로 정해준다. 필자는 인스턴트의 이름을 linux 라고 지었다.

    그 외의 환경변수는 예제에 나와 있는 데로 하면 된다.

    지역언어설정 환경변수 NLS_LANG은 모든 인스톨이 끝나고 설명하도록 하겠다.

환경변수 갱신

    위와 같이 .profile내용을 변경하였다면

      # . .bash_profile 혹은
      # source .bash_profile 하여 환경변수 내용을 업데이트한다. 또는 oracle계정으로 다시 로그인한다.

 

다. 실제적인 Oracle 의 설치

    1. 인스톨러 실행

      ㄱ) oracle로 로그인 한다. - 절대 root로 인스톨로를 실행하면 안된다.
      ㄴ) oracle 설치 디렉토리로 이동
           # cd /usr/src/ora/orainst
      ㄷ) orainst를 실행한다.
           # ./orainst 를 실행한다.

    화면에서 [TAB]키, 화살표키, 스페이스 바를 이용하여 항목을 선택할 수 있다.

    2. 검은 배경의 설치화면이 나오면 Custom Install을 선택한다.

    3. 처음 설치하는 것이므로, (o) Install, Upgrade, or De-Install Software을 선택한다.

    4. 새롭게 인스톨 할 것이므로  Install New Product - Create DB Objects을 선택한다.

    5. Mount Point를 설정한다. root user로 할 일 5. 번에서 설정한 것처럼 mount point를
        /home/oracle로 설정한다.

    6. .bash_profile에서 설정한 것처럼 $ORACLE_HOME 디렉토리를 설정한다.

    7. ORACLE_BASE 와 ORACLE_HOME을 설정한다.

    8. log 파일이 남을 위치를 설정한다.

    9. Install from CD-ROM을 선택하여야 한다.

    10. ORACLE_SID를 .bash_profile에서 설정한 것과 같이 linux로 선택한다.

    11. NLS 의 설정 - 여기에서는 일단 ALL language를 선택한다.

    12. install 이 끝이 난 후 root.sh을 실행하라는 메시지가 출력된다. 반드시 install 후에는
         root.sh을 실행하여야 한다.

    13. Software Asset Manager에서 설치한 부분을 선택한다.여기에서는 모든 부분을 설치
         한다고 가정을 한다.

    14. 13)에서처럼 Install을 선택한 후 몇 가지 사항에 대하여 OK를 한 후 OSOPER group (dba)
          를 설정한다.

    15. 생성할 DB Object를 선택한다. - Filesystem-Based Database을 선택한다.

    16. Database Mount Points를 정한다. 설치도중에 3개의 mount points를 기입하라고 하는데
         물리적으로 분리된 하드가 3개 존재하면 가장 좋지만 실제 PC에서는 힘든 일이다.
         이렇게 3곳으로 데이터를 분리하는 이유는 데이터베이스가 하드 디스크로의 읽기/쓰기를
         하는 과정에서 경합을 줄이고 에러 및 문제의 발생시 자연스런 복구를 위한 것이다.
         하지만 오라클 프로그램과 동일한 하드디스에 밖에 인스톨 할 공간이 없다면 여기에 모두
         동일한 경로를 적어주면 된다.

         필자도 오라클을 설치할 때  /home/oracle에 오라클 프로그램을 설치하고 데이터 파일을
         위한 3개의 마운트 포인트도 /home/oracle로 설정하였다.

    17. Character Set 설정 - 한글을 쓰기 위해서KO16KSC5601로 설정한다.

    18. National Character Set 설정

    19. System password 의 설정 (보통 manager라고 password를 입력한다. )

    20. sys password 의 설정 ( manager로 password를 설정. )

    21. dba password 의 설정 ( no라고 설정한다. )

    22. TNS Listener Password 의 설정

    23. Configure MTS and start SQL*Net listener 설정은 no로 한다.

    24. Control files 의 위치 확인.

    25. 기본적인 데이터베이스 관련 파일의 위치와 용량의 확인

    26.  JDBC 셋의 선택 (default로 선택을한다.)

    27. CTX Temporary Tablespace을 선택한다.

    28. CTX demo table을 설치할 것을 선택한 후에, Oracle Document를 설치할 것에 대하여
         셋팅한다. 디렉토리를 설정한 후 pdf, html, both 어떤 형식으로 설치할 것인지 묻는데
         그때에는 자신이 원하는 항목 중에서 한가지를 선택하면 된다.

    29. 이제 인스톨이 시작되기 시작하고 그래프가 올라가기 시작한다. 하염없이 기다리자 -_-;

    30. 설치완료 화면.

    31. 설치 검증
         설치가 모두 끝났다면 $ORACLE_HOME/orainst 디렉토리에 생성된 root.sh을 root 계정
         으로 실행 시킨다.

       ㄱ) root로 로그인한다.
       ㄴ) cd $ORACLE_HOME/orainst
       ㄷ) ./root.sh

      # ./root.sh
      - /etc/oratab 아래에 다음과 같은 내용이 추가되었다.

      *:/home/oracle//app/oracle/product/8.0.5:N
      linux:/home/oracle/app/oracle/product/8.0.5:N

 

라. Oracle Database 의 구동

    1. oracle user로 login.

    2. svrmgrl을 실행시킨 후 database를 가동한다.

      $ svrmgrl   - svrmgrl 의 실행

      SVRMGR> connect internal - internal 접속
      Connected.
      Oracle Server Manager Release 3.0.5.0.0 - Production

      (c) Copyright 1997, Oracle Corporation. All Rights  
           Reserved.

      Oracle8 Release 8.0.5.0.0 - Production
      PL/SQL Release 8.0.5.1.0 - Production

      SVRMGR> connect internal - internal 접속
      Connected.

      SVRMGR> startup;
      ORACLE instance started.
      Total System Global Area    4754704 bytes
      Fixed Size                         48400 bytes
      Variable Size                     4222976 bytes
      Database Buffers               409600 bytes
      Redo Buffers                     73728 bytes
      Database mounted.
      Database opened.

      SVRMGR> exit - svrmgrl 의 종료
      Server Manager complete.

    3. lsnrctl 명령을 이용하여 Oracle listener을 가동시킨다.
        - lsnrctl start : Oracle listener 의 가동
        - lsnrctl stop  : Oracle listener 의 멈춤
       $ lsnrctl start

    LSNRCTL for Linux: Version 8.0.5.0.0 - Production on 26-APR-99 21:56:51
    (c) Copyright 1997 Oracle Corporation.  All rights reserved.

    Starting /home/oracle/app/oracle/product/8.0.5/bin/tnslsnr: please wait...

    TNSLSNR for Linux: Version 8.0.5.0.0 - Production
    System paramete rfile is
    /home/oracle/app/oracle/product/8.0.5/network/admin/
    listener.ora
    Log messages written to
    /home/oracle/app/oracle/product/8.0.5/network/log/
    listener.log
    Listening on:
    (ADDRESS=(PROTOCOL=ipc)(DEV=6)(KEY=linux))
    Listening on:
    (ADDRESS=(PROTOCOL=ipc)(DEV=10)(KEY=PNPKEY))
    Listening on:
    (ADDRESS=(PROTOCOL=tcp)(DEV=11)(HOST=192.168.1.1)(PORT=1521))

    Connecting to
    (ADDRESS=(PROTOCOL=IPC)(KEY=linux))
    STATUS of the LISTENER
    ------------------------
    Alias                       LISTENER
    Version                   TNSLSNR for Linux: Version 8.0.5.0.0 - Production
    Start Date                26-APR-99 21:56:56
    Uptime                    0 days 0 hr. 0 min. 1 sec
    Trace Level              off
    Security                   OFF
    SNMP                      OFF
    Listener Parameter File  
    /home/oracle/app/oracle/product/8.0.5/network/admin/
    listener.ora
    Listener Log File        
    /home/oracle/app/oracle/product/8.0.5/network/log/
    listener.log
    Services Summary...
    extproc               has 1 service handler(s)
    linux         has 1 service handler(s)
    The command completed successfully

    - 오라클 리스너가 제대로 실행이 되지 않을 경우 listener.ora, tnsnames.ora을 알맞게
       편집한다.
     (/home/oracle/app/oracle/product/8.0.5/network/admin 위치하여 있다.)

    다음은 tcp/ip 프로토콜을 기준으로 하여서 listener.ora를 알맞게 편집한 것이다.

    #
    # Installation Generated Net8 Configuration
    # Version Date: Jun-17-97
    # Filename: Listener.ora
    #
    LISTENER =
    (ADDRESS_LIST =
    (ADDRESS= (PROTOCOL= IPC)(KEY= linux))
    (ADDRESS= (PROTOCOL= IPC)(KEY= PNPKEY))
    (ADDRESS= (PROTOCOL= TCP)(Host= 192.168.1.1)
    (Port= 1521))
    - database 가 설치되어 있는 ip를 적어준다.
    )
    SID_LIST_LISTENER =
    (SID_LIST =
    (SID_DESC =
    (GLOBAL_DBNAME= 192.168.1.1.)
    - database 가 설치되어 있는 ip를 적어준다.
    (ORACLE_HOME=
    /home/oracle/app/oracle/product/8.0.5)
    (SID_NAME = linux)
    - linux sid , 설치도중 적어준 sid를 적어준다.
    )
    (SID_DESC =
    (SID_NAME = extproc)
    (ORACLE_HOME =
    /home/oracle/app/oracle/product/8.0.5)


    (PROGRAM = extproc)
    )
    )
    STARTUP_WAIT_TIME_LISTENER = 0
    CONNECT_TIMEOUT_LISTENER = 10
    TRACE_LEVEL_LISTENER = OFF

    #
    # Installation Generated Net8 Configuration
    # Version Date: Oct-27-97
    # Filename: Tnsnames.ora
    #  
    extproc_connection_data =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = IPC)(KEY = linux))
    (CONNECT_DATA = (SID = extproc))
    )
    linux =
    - oracle alias
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL= TCP)(Host= 192.168.1.1)
    (Port= 1521))
    - database 가 설치되어있는 database 의 ip
      (CONNECT_DATA = (SID = linux))
    - oracle sid
    )

    linux_BEQ =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = BEQ)(PROGRAM =
    /home/oracle/app/oracle/product/8.0.5)
    (argv0 = oraclelinux)
    (args = ‘(DESCRIPTION =
    (LOCAL=YES)(ADDRESS=(PROTOCOL=BEQ)))’)
    (envs =
    ‘ORACLE_HOME=/home/oracle/app/oracle/product/8.0.5,ORACLE_SID=linux’)
    )
    )

    4. 이제 다시 lsnrctl start 명령으로 실행하여 Oracle listener을 실행한다.
        이제 sqlplus을 실행하여 접속이 되나 확인을 하자. test 용으로 id : scott password : tiger
        가 제공됨을 알 수 있다. 이미 설치 중에 system과 sys의 password는 직접 입력하였으므
        로, system 혹은 sys로 접속이 가능한지 확인할 수 있다.

    5. sqlplus로 접속이 확인되었으면 이제 listener을 종료한 후 database를 종료시켜 보자.

    - listener 의 종료
    $ lsnrctl stop

    LSNRCTL for Linux: Version 8.0.5.0.0 - Production on 26-APR-99 22:18:35

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

    Connecting to
    (ADDRESS=(PROTOCOL=IPC)(KEY=linux))
    The command completed successfully

    - oracle database 의 shutdown
    $ svrmgrl
    Oracle Server Manager Release 3.0.5.0.0 - Production

    (c) Copyright 1997, Oracle Corporation.  All Rights Reserved.

    Oracle8 Release 8.0.5.0.0 - Production
    PL/SQL Release 8.0.5.0.0 - Production

    SVRMGR> connect internal
    Connected.
    SVRMGR> shutdown
    Database closed.
    Database dismounted.
    ORACLE instance shut down.
    SVRMGR> exit
    Server Manager complete.

    $

 

마. Oracle Database 의 사용자 등록

    system/manager라는 Oracle 사용자 계정은 UNIX시스템에서의 root를 사용하는 것과 유사하기 때문에 우리는 문제를 발생시키는 것을 최소화하기 위해 되도록 적은 권한을 갖는 사용자를 생성할 필요가 있다.

    SQL*PLUS에 연결하고 사용자를 생성한다.

    $ sqlplus system/manager

    SQL*Plus: Release 8.0.5.1.0 - Production

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

    Connected to:
    Oracle8 Server Release 8.0.5.0.0 - Production Release
    PL/SQL Release 8.0.5.0.0 - Production

    SQL> create user <user> identified by <psw>
    2  default tablespace users
    3  temporary tablespace temp;

    User created.
    SQL> grant connect, resource to <user>

    Grant succeeded.

    SQL> exit

    Disconnected from Oracle8 Server Release 8.0.5.0.0 -
    Production Release
    PL/SQL Release 8.0.5.0.0 - Production

    시스템에 새로운 사용자계정을 생성하였기 때문에 새로운 계정을 가지고 시스템에 로그인 할수 있다. Oracle 데이터베이스에 로그인 하기 위해서는 다음과 같다.

    $ sqlplus <user>/<password>

    이 부분이 에러 메시지 없이 수행된다면, 성공적으로 Oracle 데이터베이스를 설치한 것이다.

 

바. Oracle 데이터 베이스의 자동 실행

    Oracle 데이터베이스의 자동 시작과 중지는 Oracle에서 제공하는 파일인 dbstart와 dbstop를 이용하여 설정할 수 있다. 이러한 파일들은 etc/oratab 파일의 존재여부에 의존한다.

    /etc/oratab 파일의 형식은 다음과 같다.

    SID:ORACLE_HOME:AUTO

설정  예

    #
    # This file is used by ORACLE utilities.  It is created by root.sh
    # and updated by the Oracle8 and SQL*Net install procedures.
    #
    # A colon, ‘:’, is used as the field terminator.  A new line terminates
    # the entry.  Lines beginning with a pound sign, ‘#’, are comments.
    #
    # Entries are of the form:
    # $ORACLE_SID:$ORACLE_HOME:<N|Y>:
    #
    # The first and second fields are the system identifier and home
    # directory of the database respectively.  The third field indicates
    # to the dbstart utility that the database should, “Y”, or should not,
    # “N”, be brought up at system boot time.
    #
    # Multiple entries with the same $ORACLE_SID are not allowed.
    #
    #
    linux:/oracle8/app/oracle/product/8.0.5:Y

    init.d & rc.d

    리눅스 시스템의 시작과정이나 종료과정을 변형하여 데이타베이스를 시작시키고 종료 시킬 수 있다. 이것은 매우 쉽지만, 어떠한 Linux(slackware, debian, redhat, etc)시스템을 사용하느냐에 따라  변경될 수 있다는 것을 필자는 지적한다. 이 문서에서는 Redhat Linux 5.2 에서 동작하는 예를 보여줄 것이다. 자신의 Linux 시스템에 따라 수정하기 위해서는 자신의 Linux 시스템 문서 자료를 참고한다. 우선, 우리는 /etc/rc.d/init.d 디렉토리에 있는 dbshut와 dbstart를 실행할 스크립트를 생성할 필요가 있다.

    #!/bin/sh
    #
    # /etc/rc.d/init.d/oracle
    # Description: Starts and stops the Oracle database and listeners
    # See how we were called.

    case “$1” in
    start)
     echo -n “Starting Oracle Databases: “
     echo “----------------------------------------” >> /var/log/oracle
     date +”! %T %a %D : Starting Oracle Databases as part of system up.”  >> /var/log/oracle
     echo “--------------------------------------------” >> /var/log/oracle
     su - oracle -c dbstart >> /var/log/oracle
     echo “Done.”
     echo -n “Starting Oracle Listeners: “
     su - oracle -c “lsnrctl start” >> /var/log/oracle
     echo “Done.”
     echo “”
     echo “--------------------------------------------” >> /var/log/oracle
     date +”! %T %a %D : Finished.” >> /var/log/oracle
     echo “--------------------------------------------” >> /var/log/oracle
     touch /var/lock/subsys/oracle
     ;;
    stop)
     echo -n “Shutting Down Oracle Listeners: “
     echo “-----------

    ---------------------------------” >> /var/log/oracle
     date +”! %T %a %D : ShutDown Oracle Databases as part of system down.” >> /var/log/oracle
     echo “--------------------------------------------” >> /var/log/oracle
     echo “Done.”
     rm -f /var/lock/subsys/oracle
     echo -n “Shutting Down Oracle Databases: “
     su - oracle -c dbshut >> /var/log/oracle
     echo “Done.”
     echo “”
     echo “--------------------------------------------” >> /var/log/oracle
     date +”! %T %a %D : Finished.” >> /var/log/oracle
     echo “-------------------------------------------” >> /var/log/oracle
     ;;

    restart)
     echo -n “Restarting Oracle Databases: “
     echo “-------------------------------------------” >> /var/log/oracle
     date +”! %T %a %D : Restarting Oracle Databases as part of system up.” >> /var/log/oracle
     echo “-------------------------------------------” >> /var/log/oracle
     su - oracle -c dbstop >> /var/log/oracle
     su - oracle -c dbstart >> /var/log/oracle
     echo “Done.”
     echo -n “Restarting Oracle Listeners: “
     su - oracle -c “lsnrctl stop” >> /var/log/oracle
     su - oracle -c “lsnrctl start” >> /var/log/oracle
     echo “Done.”
     echo “”
     echo “--------------------------------------------” >> /var/log/oracle
     date +”! %T %a %D : Finished.” >> /var/log/oracle
     echo “-------------------------------------------” >> /var/log/oracle
     touch /var/lock/subsys/oracle
     ;;

    *)

    echo “Usage: oracle {start|stop|restart}”
    exit 1
    esac

    이 파일이 실제적으로 정확히 당신의 시스템에서  데이터베이스를 중지하고 실행시키는지를 확인해야 한다. 에러메세지를 위한 /var/log/oracle인 log 파일을 확인하라.
    다음 명령들은 실행수준 2,3,4에 해당하는 데이테베이스를 실행시는 것을 확인 시켜줄 것이다.

    $ ln -s ../init.d/oracle /etc/rc.d/rc2.d/S99oracle
    $ ln -s ../init.d/oracle /etc/rc.d/rc3.d/S99oracle
    $ ln -s ../init.d/oracle /etc/rc.d/rc4.d/S99oracle

    시스템을 재 부팅하거나, 재 실행 시킬 때에 데이터베이스를 중지시키기 위해서 우리는 다음과 같은 연결(link)이 필요한다.

    $ ln -s ../init.d/oracle /etc/rc.d/rc0.d/K01oracle          # Halting
    $ ln -s ../init.d/oracle /etc/rc.d/rc6.d/K01oracle          # Rebooting

 

마치는 글

    이상으로 간략하게나마 Linux 상에서의 Oracle 데이터베이스 설치와 구동법에 대해서 알아보았다.
    그림과 함께 좀 더 명확한 설치법을 소개해 줄 수도 있었지만, 이제 간단한 설치법 정도는 기타 책이나 오라클사 세미나에 가면 쉽게 구할 수 있으므로 기본 설치법에 사용자 등록, 자동 시작/종료를 추가해 첫 글을 마친다. 다음에는 간단한 sqlplus 사용법, Oracle SQL, pro-c 에대해서 알아보고 마지막으로 PHP3와 연동하는 것으로 이 글을 마칠까 한다.

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:05
반응형

Oracle Database 10g (10.1.0.2)

Installation On Fedora Core 2 (FC2)

In this article I'll describe the installation of Oracle Database 10g (10.1.0.2) on Fedora Core 2. The article is based on a Fedora Core 2 Server Installation with a minimum of 2G swap and the following package groups installed:
  • X Window System
  • GNOME Desktop Environment
  • KDE Desktop Environment
  • Editors
  • Graphical Internet
  • Text-based Internet
  • Server Configuration Tools
  • Windows File Server
  • Network Servers
  • Development Tools
  • Kernel Development
  • Administration Tools
  • System Tools

Alternative installations may require additional packages to be loaded in addition to the ones listed below.

Download Software

Download the following software:

Unpack Files

First unzip the files:
gunzip ship.db.cpio.gz
Next unpack the contents of the files:
cpio -idmv < ship.db.cpio
You should now have a single directory (Disk1) containing installation files.

Hosts File

The /etc/hosts file must contain a fully qualified name for the server:
<IP-address>  <fully-qualified-machine-name>  <machine-name>

Set Kernel Parameters

Add the following lines to the /etc/sysctl.conf file:
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
Run the following command to change the current kernel parameters:
/sbin/sysctl -p
Add the following lines to the /etc/security/limits.conf file:
*               soft    nproc   2047
*               hard    nproc   16384
*               soft    nofile  1024
*               hard    nofile  65536
Add the following line to the /etc/pam.d/login file, if it does not already exist:
session    required     /lib/security/pam_limits.so
Note by Kent Anderson: In the event that pam_limits.so cannot set privilidged limit settings see Bug 115442.

Setup

Install the following packages:
# From Fedora Core 2 Disk 1
cd /mnt/cdrom/Fedora/RPMS
rpm -Uvh setarch-1.4-1.i386.rpm
rpm -Uvh tcl-8.4.5-7.i386.rpm

# From Fedora Core 2 Disk 2
cd /mnt/cdrom/Fedora/RPMS
rpm -Uvh openmotif-2.2.3-2.i386.rpm

# From Fedora Core 2 Disk 3
cd /mnt/cdrom/Fedora/RPMS
rpm -Uvh compat-libstdc++-7.3-2.96.126.i386.rpm
rpm -Uvh compat-libstdc++-devel-7.3-2.96.126.i386.rpm
rpm -Uvh compat-db-4.1.25-2.1.i386.rpm
rpm -Uvh compat-gcc-7.3-2.96.126.i386.rpm
rpm -Uvh compat-gcc-c++-7.3-2.96.126.i386.rpm
Create the new groups and users:
groupadd oinstall
groupadd dba
groupadd oper

useradd -g oinstall -G dba oracle
passwd oracle
Create the directories in which the Oracle software will be installed:
mkdir -p /u01/app/oracle/product/10.1.0/db_1
chown -R oracle.oinstall /u01
Login as root and issue the following command:
xhost +<machine-name>
Edit the /etc/redhat-release file replacing the current release information (Fedora Core release 2 (Tettnang)) with the following:
redhat-3
Login as the oracle user and add the following lines at the end of the .bash_profile file:
# Oracle Settings
TMP=/tmp; export TMP
TMPDIR=$TMP; export TMPDIR

ORACLE_BASE=/u01/app/oracle; export ORACLE_BASE
ORACLE_HOME=$ORACLE_BASE/product/10.1.0/db_1; export ORACLE_HOME
ORACLE_SID=TSH1; export ORACLE_SID
ORACLE_TERM=xterm; export ORACLE_TERM
PATH=/usr/sbin:$PATH; export PATH
PATH=$ORACLE_HOME/bin:$PATH; export PATH

LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib; export LD_LIBRARY_PATH
CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib; export CLASSPATH
LD_ASSUME_KERNEL=2.4.1; export LD_ASSUME_KERNEL

if [ $USER = "oracle" ]; then
  if [ $SHELL = "/bin/ksh" ]; then
    ulimit -p 16384
    ulimit -n 65536
  else
    ulimit -u 16384 -n 65536
  fi
fi

Installation

Log into the oracle user. If you are using X emulation then set the DISPLAY environmental variable:
DISPLAY=<machine-name>:0.0; export DISPLAY
Start the Oracle Universal Installer (OUI) by issuing the following command in the Disk1 directory:
./runInstaller
During the installation enter the appropriate ORACLE_HOME and name then continue with a "software only" installation.

Post Installation

As the oracle user issue the following commands:
cd $ORACLE_HOME/bin

mv oracle oracle.bin

cat >oracle <<"EOF"
#!/bin/bash
 
export DISABLE_HUGETLBFS=1
exec $ORACLE_HOME/bin/oracle.bin $@
EOF
 
chmod +x oracle
This should prevent the "ORA-27125: unable to create shared memory segment" being produced by the DBCA.

Edit the /etc/redhat-release file restoring the original release information:
Fedora Core release 2 (Tettnang)
Finally edit the /etc/oratab file setting the restart flag for each instance to 'Y':
TSH1:/u01/app/oracle/product/10.1.0:Y
For more information see:
Hope this helps. Regards Tim...
Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:01
반응형

======================================================================
ORA-00030 : ALTER SYSTEM KILL SESSION에 대하여
======================================================================

◈ 현상 사용자는 다음과 같은 상황에서 session 을 kill 하려는 시도를 하게 된다. 1. os 에는 process 가 존재하지 않지만, v$session 에는 active 로 존재하고 있을 경우 2. shadow process 는 살아 있는데, client machine 을 rebooting 한 경우 3. session 이 걸고 있던 lock 을 release 해야 할 경우 4. OS 나 Oracle 의 자원을 지나치게 많이 사용하여 성능을 저하시키는 process 그런데, alter system kill session ('sid, serial#'); 후에 다음과 같은 에러가 발생할 경우가 있다. ora-00030, 00000, "user session ID does not exist" // *Cause: The user session id no longer exists, probably because the // session was logged out. // *Action: Use a valid session ID. ◈ 원인 kill session을 할 수 없는 이유는 PMON이 이미 이 session을 delete하고 있는 중이기 때문이다. 즉, PMON 이 dead session 을 clean-up 하고 있는 중에는 serial number의 값이 증가한다. 문제는 PMON이 process를 kill하는 시간인데, transaction의 크기에 따라, PMON의 rollback 시간이 결정된다. 먼저 PMON은 dead process를 찾아내어, 이 process가 사용한 resource 를 release하는 시도를 한다. PMON은 계속 이 작업을 시도하다가 마침내, free buffer의 부족으로 더 이상 resource를 free-up 하지 못하게 된다. 이 때, 이 process를 delete하고 있다는 message를 trace file에 출력하는데, 이것은 process를 delete하는 데 필요한 resource(data cache 내의 free buffer)의 부족으로 위의 작업이 지연되고 있다는 의미이다. ◈ 조치 PMON이 process 를 clean-up 할 때 걸리는 시간은, 5분에서 24 시간까지 소요될 수 있다. 문제는 이 process가 hold 하고 있는 lock으로 인해 특정 작업이 수행되지 못하는 데 있다. MTS 를 사용할 때는 configuration MTS setting, sqlnet.expire_time 사용)에 따라 다르지만, clean-up 작업을 하는데 72 시간 이 소요된 경우도 있다. 아직까지는 PMON이 작업을 마칠 때까지 기다리는 방법 또는 db를 restartup하는 방법 밖에는 없다. --- PMON 의 작업 PMON은 network failure 나 기타의 원인으로 생긴 old process connection을 clean-up하는 역할을 한다. 그런데, PMON 은 clean-up 해야 하는 connection 중에 정해진 개수 만큼의 transaction 을 rollback 할 수 있는데, 이 값은 initSID.ora 의 cleanup_rollback_entries(default = 20) 에 의해 결정된다. 예를 들어, 1000 개의 uncommitted update가 있다면, 일정한 시간마다 cleanup_rollback_entries의 개수 만큼의 record만 rollback 할 수 있으므로 이 작업 동안에 lock 은 그대로 유지된다. PMON 은 위의 작업 이외에 DB maintenance 역할이 있으므로, 위의 rollback 이 비교적 빠르게 처리 되지 못할 수도 있다. 이러한 rollback을 빠르게 처리하기 위하여 cleanup_rollback_entries 를 늘릴 수도 있다. 그러나, 그 만큼 일정시간 동안 PMON의 작업이 많아지게 되므로, 다른 사용자들의 작업 요청이 느려지게 되는 trade-off가 있으므로, 신중히 고려한 후에 수정하는 것이 바람직하다. alter system kill session 에 의해서도 위와 같이 rollback 이 이루어지는데, 이 session 이 완전히 clean-up 되기 전까지 v$session, v$process에 남아 있게된다. --- ALTER SYSTEM KILL SESSION 을 하기 전에 ... kill session 을 원할 경우는 다음의 순서대로 작업하는 것이 좋다. 1. kill the user process first 2. wait for 3 - 4 minutes 3. query v$session 4. if any information find in v$session, query v$lock like select count(*) from v$lock where SID ='sid'; 위의 count(*) 가 0 이 아니라면, 아직 PMON 이 rollback을 끝내지 못한 경우이므로 다시 얼마후에 v$lock 을 조회하여 lock 의 개수가 감소하였는지 반복적으로 확인한다. 만약, 이 값이 전혀 변하지 않았다면, ALTER SYSTEM KILL SESSION 을 수행하고 v$session, v$lock을 query 하여 변화가 있는지 확인하여 변화가 있다면, 좀 더 기다린다. 그래도, v$lock 의 count(*) 가 0 이 되지 않을 경우, 마지막으로 수행할 수 있는 유일한 방법은 instance 를 restartup 하는 것이다.

======================================================================
ORA-00054 : TABLE에 TRANSACTION이 종료되지 않은 경우
======================================================================

TABLE 을 DROP 하려고 할때 그 TABLE에 TRANSACTION이 종료되지 않아 ORA-54 ERROR가 나오는 경우가 있다. DB를 RESTART하면 되지만 더 효율적인 해결 방법은 다음과 같이 할수 있다. * 참고 : Serial Number 가 Negative 인 경우 그 값에 65536 을 더해야 함. rem sqlplus system/manager rem rem prompt Enter table name accept tname CHAR col type format a6 col object_name format a20 select a.sid,a.serial#,b.type,c.object_name from v$session a,v$lock b,dba_objects c where a.sid=b.sid and b.id1=c.object_id and b.type='TM' and c.object_name=upper('&amp;tname'); Prompt Enter session ID(SID) ? accept sid Prompt Enter serial number(serial#) ? prompt -- if serial number < 0, prompt -- then serial number #=Serial number + 65536 accept serial alter system kill session '&amp;sid,&amp;serial'


==================================================================================
ORA-00060 : DEADLOCK과 INITRANS (같은 TABLE내의 다른 범위의 DATA처리시 ORA-60)
==================================================================================

 deadlock에  관한  일반적인  사항은  <Bul:11742>에  정리되어  있다.  같은  data를  동시에   변경하는
 transaction의 경우  deadlock이 발생하는  것은 application  logic을 수정하여  해결해야 하는  경우가
 대부분이다.

 그런데 같은 table에 대해서 동시에 수행되는  transaction이 각자 서로 다른 data를 처리하는  경우에도
 ora-60(deadlock detected while waiting for resource)이 발생할 수 있다.

 예를 들어 한 transaction은 A table의 1월 data를 처리하고, 동시에 다른 transaction은 같은 A  table의
 2월 data를 처리하는 것과 같은 경우이다.

 이러한 경우에도 initrans가  작게 설정되어 있으면,  ora-60이 발생할 수  있는데, 이 자료에서는  이와
 같이 다른 data를 처리하는 transaction들 사이에서의 ora-60이 발생하는 경우와 조치사항을 확인한다.

  1. transaction entry에 대해서
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 table이나 index에 포함된 모든 block에 update/delete/insert와 같은 dml을 수행하기 위해서는 일단  그
 block에 transaction정보를 저장시킬 transaction entry를 확보한 후에 원하는 작업이 수행가능하다.

 이  transaction entry의  크기는 os  dependent하기는 하나  대부분 23  bytes이며, table이나   index의
 initrans  option에 의해,  미리 확보되는  block당 transaction  entry의 갯수가  결정된다. default는
 table이 1, index가 2이다.

 이  transaction  entry가  특정 transaction에  할당되면  그  transaction이 commit이나   rollback되기
 전까지는 다른 transaction에서  사용할 수 없다.  같은 block에 다른  transaction이 dml을  수행하려면,
 남은 공간중에서 23 bytes의 transaction entry를 새로 할당하거나, 공간이 없으면 앞에서 먼저 사용중인
 transaction이 commit/rollback되기를 기다려야 한다.

  2. ORA-60이 발생하는 경우
  ~~~~~~~~~~~~~~~~~~~~~~~~~
 deadlock을 유발시키는 transaction이 서로간에 완전히 다른 data(같은 table)를 처리하더라도 그  data가
 같은 block에  함께 들어가  있는 경우라면  ORA-60이 발생할  수 있다.  즉, transaction  entry를  잡는
 과정에서  block내에 남은  space가 부족한   경우, 서로  상대방의 transaction이  종료되기를  기다리는
 deadlock이 발생가능하다는 것이다. 아래에 실제 예를 들어 자세한 발생 시나리오를 정리하였다.

① ORDER table은  날짜별로 data가 추가,    변경, 삭제되는 100만건  이상의 data를 가진  table이다. 이
 table에   대해서   월별로   통계작업을  수행하는데,   6개월씩   처리하기   위해  6개  transaction을
 동시에 수행하였다. 즉, T1은 1월 data, T2는 2월 data, T6는 6월 data를 처리하는 식이다.

② ORDER table은 initrans값이 1로 지정되어 있고 현재 1000개의 block이 이 table에 할당되어 있다.

③  100번지  block에  2월,  3월,  5월  data가  함께  저장되어  있다.  200번지  block에는  2월,   3월
 data가 저장되어 있다.

④ T2  transaction이  100번지  block에  이미  확보되어  있는  1개의  transaction   entry를  사용하여
 transaction정보를 저장하였다. 그리고, 2월달 data에 대한 작업을 수행하였다.

⑤ T3 transaction이 200번지 block에 initrans  1에 의해 확보되어 있는 23 bytes의  transaction entry를
 이용하여 transaction정보를 저장한 후 3월달 data에 대한 처리를 수행하였다.

⑥ T2 transaction이 2월달 data중 나머지 부분을  처리하기 위해 200번지를 access하여 23 bytes의 T2  를
 위한   transaction     entry를   확보하려고      하였으나,   block에     남은   공간이      없어서,
 T3 transaction이  commit할때까지   기다린다.   5번  단계에서,    initrans에  의해  미리    확보되어
 있는 공간을  사용하는 T3 transaction이 종료되면, 그 부분을 T2가 사용할 수 있게 되는 것이다.

⑦ T3  transaction도  100번지에  있는 3월  data를  처리하기  위해  100번지내에 transaction   entry를
 추가적으로   확보하려 하였으나,    공간이 없어서,    마찬가지로  미리   100번지 block을    사용하고
 있는 T2 transaction이 종료되기를 기다리게 된다.

⑧ 6과 7상황에  의해 T2와 T3  transaction은 서로 상대방이  종료되기를 기다리는, deadlock이  발생하게
 되므로   deadlock상황을  유발시킨     T3   transaction이   ORA-60을    발생시키면서   종료   되고,
 T3  transaction은   rollback된다.  200번지에   확보한    transaction   entry부분도  반환하여   다른
 transaction이 사용가능한 상태가 된다.

⑨ 8번에서 release된 200번지  block내의 transaction entry 23  bytes를 6번 단계에서 기다리고  있던 T2
  transaction이 확보하고 작업을 진행한다.

  3. deadlock을 피하기 위한 방법
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

결론적으로,  같은  table에 대해서  다른  data를 처리하는  transaction이라  하더라도 동시에  수행하는
transaction이 많은 경우라면 initrans 값이 작은 경우 ora-60이 발생할 수 있게 된다.

하나의 table에 대해서  performance등의 이유로 동시에  다른 data를 처리하는  transaction을 수행하고자
한다면,  table의  initrans  값을  크게하여,  하나의  block에  여러  개의  transaction이  dml  처리를
수행하더라도 space가 부족하여 기다리는 상황은 없도록 하여야 한다.

initrans를 n으로 지정한다면 23*n bytes가 항상 transaction entry로 미리 확보되어 있는 것이다.  이렇게
transaction entry로 초기에 확보된  공간은 data를 저장할 수  없는 공간이 되므로, 너무  크게 하는 것은
space 낭비가 초래된다. 하나의 block에 대해서  동시에 여러 transaction이 처리되지 않는 경우라면  미리
확보된  transaction entry는  사용도 되지  않고 낭비되어,  full table  scan 등의  작업에 성능  악화만
초래하게 된다.

initrans값은 하나의 table에 대해서 동시에  처리하는 transaction의 갯수 이하로 지정하도록  한다. 해당
table에  대한  동시  transaction의  갯수만큼 initrans를  지정하면  앞에서  설명한  상황의 deadlock은
발생하지 않는 것이 보장되나 space를 고려할 때 그 보다는 약간 작게 하는 것이 일반적인다.

initrans는 table이나 index에  대해서 create나 alter문장시  지정, 변경이 가능하나,  alter의 경우 이미
확보된 block에는 영향을 미치지 못하므로 export/import를 이용하여 새로 지정하는 것이 필요하다.

다음에 scott.dept table에 대해서 예를 들었다. column정의 storage등은 임의의 값을 예로 사용한 것이며,
initrans도 예로 3을 지정하였다.

  os> exp scott/tiger file=test.dmp tables=dept

  os> sqlplus scott/tiger
  SQL> drop table dept;
  SQL> create table dept (deptno number(2), dname varchar2(10))
	   initrans 3
	   storage(initial 10m next 2m pctincrease 0);

  os> imp scott/tiger file=test.dmp tables=dept ignore=y




======================================================================
ORA-00210 : TABLE에 TRANSACTION이 종료되지 않은 경우
======================================================================

Sequent Symmetry  or NUMA-Q  platform의 Oracle  7.3.2, 7.3.3,  7.3.4 OPS  Product 설치  및 DB 생성후
Master node startup parallel 후 다른 node를 startup parallel 시 다음과 같은 현상이 발생할 경우.

◈ 현상
  SVRMGR> startup parallel

     ORACLE instance started.
     Total System Global Area     546275472 bytes
     Fixed Size                       39108 bytes
     Variable Size                210167756 bytes
     Database Buffers             327680000 bytes
     Redo Buffers                   8388608 bytes

  ORA-00210: cannot open control file '/dev/vx/rdsk/oracle/v_ctl1'
  ORA-07368: sfofi: open error, unable to open database file.
  SEQUENT DYNIX/ptx Error: 16: Device busy

  발생하면서 startup fail 발생

◈ 원인
  Sequent Symmetry or NUMA-Q platform이 very large file (O/S에서 2GB 이상의 file system 지원)을
  지원하기 위해  VLFS patch를  적용했거나 VLFS를   이미 지원하는  O/S Version일  경우 오라클  master
  node가 정상적으로  startup  되고  나서  다른  node가  startup  parallel이  될  때  먼저 startup 된
  master node가 shared disk 의 모든 오라클 관련 file을 none-shared mode로 open 하기 때문에 위의 현상
  이 발생됨

◈ 조치
  1) PTX/Cluster V1.3.2일 경우
     * Oracle  V7.3.x : O/S상에서 VLFS patch적용하지 않았을 경우는 관계 없으나, 이미 적용 되었다면
       추가적으로 O/S patch FP#23373 적용하여야 함
  2) PTX/Cluster running DYNIX/PTX 4.4.x 일 경우
     * Oracle V7.3.3 : 현재 fix된 patch는 없으며 다음과 같은 workaround 방법으로 해결이 가능함.

  (Workaround)
     $ORACLE_HOME/rdbms/lib/ins_rdbms.mk file에 아래의 추가된 부분만 삽입하여 오라클 kernel relink 실시
     (예:make -f ins_rdbms ioracle)
     oracle: $(ORALIBD) $(CORELIBD) $(NETLIBD) $(KSMS) $(CONFIG)
             $(PSOLIBLIST) opimai.o @$(ECHO) $(LINK) -o $@ $(LDFLAGS)
             $(LDFLAGS_ORA) opimai.o $(CONFIG) \r
             -llkseqora  ---> 추가된 부분
             $(LLIBSERVER) $(LLIBORA) $(LLIBKNLOPT) $(LLIBSLAX)
             $(LLIBPLSQL) \r
             $(LLIBSICX) $(LLIBSOWSUTL) \r
             $(LLIBSICX) $(LLIBSOWSUTL) \r

                ...........
                ...........

  * Oracle V7.3.4 :
    Oracle V7.3.4 일 경우는 문제가 없으나 patchset을 적용할 경우 V7.3.4.2에서는 V7.3.3과 같은
    방법으로 oracle kernel을 relink하면 문제가 해결됨.

======================================================================
ORA-00312, ORA-00313 : ONLINE REDO LOG CRASH
======================================================================

[ ONLINE REDO LOG가 손상되었을 때 DB에 OPERATION 이 없었던 경우는 다음과
같은 절차로 DB 을 OPEN 할 수 있다. - 확률 70% ]
-------------------------------------------------------------------------
1. CONTROLFILE 생성

-. 손상된 online log 는 포함시키지 않는다.
-. resetlogs option 으로 생성한다.
-. reuse option 은 생략하고 기존 controlfile 은 다른 이름으로 move 시킴.

<V7 에서 CONTROLFILE 생성하는 방법>
  sqldba> startup mount
  sqldba> alter database backup controlfile to trace;

  위와 같이 명령을 입력하면 ORACLE_HOME/rdbms/log 디렉토리에 트레이스 화일이다. 그 트레이스 화일에서
  create controlfile 명령부분을 남기고 삭제한다.

  (7.3 이상에서는 cd $ORACLE_HOME
                  cd ../../admin/SID dir/udump 에 있습니다)

콘트롤화일 생성 문장 예 - <cnt.sql> : GROUP 1 이 ONLINE LOG 라고 가정
--------------------------------------------------------------------------
 CREATE CONTROLFILE DATABASE 'RC722' RESETLOGS NOARCHIVELOG
 MAXLOGFILES 32        ********
 MAXLOGMEMBERS 2
 MAXDATAFILES 30
 MAXINSTANCES 8
 MAXLOGHISTORY 800
 LOGFILE
 GROUP 2 '/oracle/oracle/dbs/log2RC722.dbf' SIZE 5M,
 GROUP 3 '/oracle/oracle/dbs/log3RC722.dbf' SIZE 5M
 DATAFILE
 '/oracle/oracle/dbs/systRC722.dbf',
 '/oracle/oracle/dbs/rbsRC722.dbf',
 '/oracle/oracle/dbs/toolRC722.dbf',
 '/oracle/oracle/dbs/usrRC722.dbf',
 '/oracle/oracle/dbs/tempRC722.dbf',
 '/oracle/oracle/rcdata.dbf'
 ;

2.절차

$ sqldba lmode=y
 SQLDBA> connect internal
 SQLDBA> shutdown abort
 SQLDBA> startup nomount
 statement processed
 SQLDBA> @cnt
 SQLDBA> recover database using backup controlfile until cancel;
 ....
 ...
 CANCEL (Return)
 Recovery canceled
 SQLDBA> alter database open resetlogs;

 : 만일 정상적으로 open 되면 log file 추가
 SQLDBA> alter database add logfile '?/dbs/log1ORA722.dbf' size 1M;

======================================================================
ORA-00600 : BLOCK 손상 해결 방법
(ORA-600[3339], ORA-600[3398], ORA-600[4519], ORA-1578)
======================================================================

◈ 개요 
 블럭의 손상 원인은 여러가지가 있는데, 메모리내의 블럭이 손상된 경우와 디스크상의 물리적인 블럭이
 손상되는 경우가 있다.

 (1)  오라클  오류  블럭  손상과  관계된 오라클  오류는  internal error인  ORA-600중  첫번째 인수가
 3339,3398, 4519인  경우와 ORA-1578이  있으며, 이중  Ora-600[3398]은 메모리  블럭만 손상된 경우이고,
 ORA-1578은 물리적 블럭이 손상된 경우 발생한다. ORA-600[3339]와 ORA-600[4519]는 메모리와 디스크 손상
 모두가 연관될 수 있다. 각각의 오류에 대한 자세한 설명은 아래의 3번에서 기술하였다.

 (2) DBA (database address)  ORACLE 데이타  블럭은 블럭의 정보를 담은 Fixed Header를  갖고   있으며
 이 정보를 이용하여 각각의 블럭과  데이타베이스 전체의 INTEGRITY를 유지한다. DBA는  Fixed   Header의
 한  부분으로 32bit 길이의 정수이며  데이타베이스의 화일 번호와 파일에서 블록위치를  나타낸다.  블럭
 손상이  발생하면  오라클은 오류  메시지에  이 DBA를  나타내거나  파일 번호와  블럭  위치를
 십진수로 나타내기도 한다.

◈ 블럭 손상의 원인 
 오라클은 화일에 블럭을 읽고  쓸 때 lseek(), read(),  readv(), write(), writev()와 같은  OS의 system
 function  call을 이용한다.  블럭이 이러한  시스템콜을 이용하여  읽혀지거나 씌여진  후, 혹은  직전에
 오라클은 DBA에  대한 검사를  하여 블럭이  손상되었는지 확인하게  된다. 그러나  대개 블럭의 데이타가
 손상될 당시에는 그  사실이 드러나지 않다가  손상된 부분의 데이타가  사용될 때 비로소  손상된 사실이
 알려지게 되므로 대부분 블럭 손상은 OS나 HW에 의해 손상된 블럭을 이후 오라클이 사용하고자 검사하는
 과정에 발견하는 것이 대부분이다.

 블럭 손상이 야기될 수 있는 주된 상황은 다음과 같이 요약될 수 있다.

 (1) ORACLE 블럭내의 첫번째 OS 블럭이 디스크상의  문제로 해서 이상이 있는 경우, OS 또는  디스크 복구
  프로그램이 해당 블럭을 복구하려는 과정에서 블럭의 값이 모두 비정상적적으로 0이 되어 버릴 수 있다.

 (2) 매우 드문  경우이긴 하지만, 메모리상에서  이미 손상된 블럭을  디스크상에 그대로 기록하는  경우
  물리적 블럭의 DBA가 틀리게 된다

 (3)  블럭이   데이타  화일상에   기록될  위치를   잘못  찾아   손상이  발생하기도   하는데,  이러한
  경우를 'write blocks   out  of  sequence'  라고   불리운다. 이것은   ORACLE이  lseek()을  호출했을
  때 OS가 블럭을 잘못된 곳에 기록해서   생기는  경우가 많다.  이러한   예는 4.2G를  넘는 큰   화일을
  다룰 수  있는   기능을 제공하는  HW/OS의   경우  발생한다.   4.2G를   넘는  화일의  경우,    32bit
  unsigned number로 다룰   수 있는 범위를  벗어나기   때문에 OS는offset   값을  ORACLE이  사용할  수
  있도록 적절히 변환시켜야  한다. ORACLE은  OS의 지원  여부와  관계없이 2G  이상의  화일을  지원하지
  않으며 위와  같은  큰   파일을 다룰    수 있는   환경에서는 lseek()   시스템콜이 정확한   위치로의
  변환을 시켜주지 못함에 따라 보다 작은 크기의 화일에서도 문제가 발생하는 경우도 있다.

 (4) 네번째 원인은  I/O기능이 전혀 작동하지  않는 경우이다. ORACLE은  lseek(), read() 시스템  콜이
  리턴하는 에러 코드를 검사하며 read()가   읽어들인 바이트수가 BLOCK SIZE의 정수배인지를   검사한다.
  이 검사를   통과하면  ORACLE은  성공적으로  READ가   수행되었다고 가정한다.   만약  DBA가 정확하지
  않다고 체크되면 DATABASE에 대한 읽기 요구는 실패하기 때문에 실제의 블럭 읽기는 일어나지 않는다.

 (5)  다른  원인은  동일한  디바이스에서  다른 블럭을  읽어온  경우이다.  이것은  작업이  메우  바쁜
  디스크에서  발생하곤  한다.   어떤 경우에는   수백개  이상  떨어진  곳의   블럭을 읽어오는  경우도
  있다. 이러한 경우와 위의   (4)번의 경우에는 다시  한번  동작을 반복함으로써  문제는 해결  수 될 수
  있으며 이것은 일반적으로 ORACLE의 문제가 아니라 OS나 HW의 문제인 경우가 많다.

◈ 블럭 손상과 관계된 오류의 종류와 가능한 조치방법
 (1) ORA-600[3339] 
  ORA-600[3339]에러는  ORACLE이  직접  버퍼로  데이타를 읽어들일  때  읽은  블럭의  DBA (Data  Block
  Address)가 잘못되었음(INVALID)을  의미한다. 실제로  읽어들인 블록의  DBA와 ORACLE이  읽고자 하였던
  블럭의 DBA가  다르면 위에서와  같은 에러가  발생하며 주로  OS나 HW의  문제가 그 원인이 되는 경우가
  많다.  만약  메모리에  문제가  있다고  생각된다면  다음과  같은  Event  Parameter를  initSID.ora에
  추가함으로써 블록 검사를 할 수 있다. 이것은 ORA-600[3398], ORA-600[4519]에서도 마찬가지이나 이러한
  event를 사용하기전에 먼저 한국오라클에 지원을 요청하는 것이 바람직하다.

  event = '10210 trace name context forever, level 10'
  event = '10211 trace name context forever, level 10'

 ORA-1578이 함께  발생하는 디스크  블럭 손상이  발생하였다면, 아래의  (4)의 ORA-1578해결 방법과 같이
 조치 하면 된다.

 (2) ORA-600[3398]
  DBWR가 디스크에 데이타를  쓰기 전에 캐쉬에서  손상된 블럭을 발견하면  OERI(3398) 메시지를 출력하고
  인스턴스를 정지시킬 것이다. 따라서 문제의 블록은 디스크에 저장되지 않으므로, 실제 디스크상의  블럭
  손상은 야기시키지 않는다. 이때 DBA를 포함한 많은 인수들이 OERI(3398) 내부 에러 처리기에 전달되므로
  이것을 확인하여 한국 오라클에 지원을 요청한다.

 (3) ORA-600[4519] 
  메모리내의 블럭을 update/delete가 아닌 consistent  read를 위해 읽고자 할때 블록이  손상됨을 발견한
  경우, ORA-600[4519]가  발생한다. 이  오류는 메모리  손상과, 디스크  손상 모두의 경우 발생가능하며,
  오류가 발생하는 즉시 한국오라클에 지원을 요청하는 것이 바람직하다.

 (4) ORA-1578 ORA-1578 에러는 ORA-600[3339] 에러와 함께 발생하곤 하며 디스크상에 물리적으로  블럭이
  손상되었음을 의미한다. 이러한 디스크 블럭 손상의 복구방법을 살펴보자.

(a)손상된  블럭을  포함하고  있는  세그먼트  확인  ORA-1578  에러가  발생하면  Corruption이 발생한
  화일번호와 블럭번호를  알려준다. 여기서는  이 때의  파일번호를 f,  블럭번호를 b라고 부르기로 한다.
  우선 해야할 일은 어떠한 오브젝트가 Corrupt되었는가를 알아내는 것으로써, 다음의 스크립트를 이용하면
  알 수 있다.

 SQL> select  segment_name, segment_type
        from  dba_extents
    where  file_id = f
         and  b between block_id and block_id + blocks - 1;

(b) 해당 세그먼트가 인덱스이면 Drop 시키고 다시 생성하면 된다.

(c) 해당  세그먼트가 테이블이면  Corrupt 된  블럭의 데이타는  손상된 것이다.이렇게 테이블이 손상된
  경우, 만약  해당 테이블이 들어있는 엑스포트 화일이   있다면 손상 된 테이블을  Drop 시키고  임포트
  받는것이 제일  간단한 방법이다. 하지만 만약  엑스 포트 받은 화일이  없거나 백업해 둔 화일도 없다면
  해당 테이블에 인덱스가 생성되어 있는 경우에 한해서 다음의 방법을 사용해서 복구를 하도록 한다.

 예를 들어 다음과 같은 에러 메시지가 떨어졌다고 하자.
 01578, 00000, 'ORACLE data block corrupted (file # 10, block # 4)

<1> 먼저 (a)번의 script를 이용하여 손상된 블럭을 포함하는 세그먼트를 확인한다.
   SQL> select  segment_name, segment_type  
        from  dba_extents  
       where  file_id = 10
            and  4 between block_id and block_id + blocks - 1;

         SEGMENT_NAME        SEGMENT_TYPE
         ------------        ------------
             EMP                 TABLE

<2> Rowid를 이용하여 손상된 블럭내의 데이타를 찾아낸다.
 위의 결과값이 EMP table이 empno, ename,  deptno 를 컬럼으로 가지며, empno 컬럼에  인덱스가 생성되어
 있다고  하자.클러스터화되지  않은   모든  테이블은  유니크한Rowid를   가진다.  Rowid는  총   18자로
 블럭어드레스(8자), 점(1자),  로우 어드레스(4자),  점(1자), 화일  어드레스(4자)로 구성되어  있다. 이
 rowid를 이용하여 다음과 같이 손상된 블록에 있는 employee 에 대한 empno를 구할 수 있다. 이때 empno가
 char type 이라면 [where empno > 0] 대신 [where empno > ‘ ‘]를 사용하여 empno에 대한 인덱
 스를 사용하도록 유도한다. 

    SQL> select  empno  
           from  emp
          where  empno > 0 
            and  rowidtochar(rowid) like '00000004.%.000A';  

        EMPNO           ROWID  
    ------------  ------------------------------
        500      00000004.0000.000A
        501      00000004.0001.000A

<3> EMP 테이블과 같은 구조를 갖는 새로운 테이블을 만든다.
    SQL> create table temp 
             as select * from emp 
          where 1 = 2;  

<4> 손상된 부분을 피해서 새로운 테이블에 손상된 테이블의 데이타를 추가한다.
    SQL> insert into temp select * from emp where empno < 500; 
    SQL> insert into temp select * from emp where empno > 501;

<5> 손상된 테이블인 EMP테이블을 Drop시키고 Temp테이블의 이름을 EMP로 변경한다.
    그리고 백업된 자료나 문서자료를 통하여 손상된 부분에 대한 정보를 추가한다.
    SQL> drop table emp;  
    SQL> rename temp to emp;

<6> 손상된 블럭에 대부분의 로우가  존재하고 있다면 다음의 방법을 이용한다.
   SQL> create table empnos as  
         select empno from emp
         where empno > 0  
          and rowidtochar(rowid) not like '00000004.%.000A';

   이 스크립트를 이용하면 손상된  블럭에 포함되지 않은 empno 들을 알 수 있다.
   다음의 스크립트를 계속 실행시켜 복구를 한다.

    SQL> create  table temp  as select * from emp  where 1 = 2;
    SQL> insert  into temp
         select  emp.empno, emp.ename, emp.deptno
       from  emp, empnos
     where  emp.empno > 0
       and  emp.empno = empnos.empno;

<7>  만약  데이타  딕셔너리의  테이블이나 인덱스에서  손상된  블럭이  발생했다면  지원 을  요청해야
 한다

======================================================================
ORA-00604: 익스텐트가 가득 찬 경우
======================================================================

 이 에러는 내부적으로 SQL명령이 실행될 때 발생한다. 예를 들어 현재 할당된 익스텐트가 가득 차서  다음
 익스텐트를 할당 받으려고 할 때 오라클이 다음 익스텐트의 크기와 위치를 결정하기 위하여  SELECT명령을
 내리게 되는 것과 같은 경우이다.

 * 이 문제가 발생하면 우선 alert.log 화일을 검사하여 ORA-600 과 같은 에러가 발 생했는가를  확인한다.
 ORA-600 에러가 발생했다면 오라클측에 지원을 요청 하도록 하고 그렇지 않다면 다른 원인을 검사해 봐야
 한다.

 * 가장 먼저 고려할 사항은 init.ora 화일에 지정된 open_cursors의 크기를 알아보는  것이다.
 이 값이 설정이 안되어 있으면 Default가  50이므로 open_cursors=255 와 같이 설정하도록 한다.  이 값은
 단지 커서의 최대 값을 지정하는 것이므로 커서를  적게 쓰 는 프로그램에 아무런 영향을 끼치지  않는다.
 open_cursors를 변경하고 DB를 tdown 하고 Startup 시키면 된다.

 * 만약 이 방법으로  해결이 안되면 다음의 방법을  따른다. 정확한 에러의 원인을  찾기 위해서 init.ora
 화일에 다음과 같은 라인을 추가한다. events = '604 trace name errorstack' 이렇게 init.ora를 변경하고
 DB를 Shutdown 하고 Startup  하면 ORA-604 에러가 발생하는 경우에 자세한 정보를  Trace 화일에  기록해
 주므로 이 화일을 검사하여 에러의 원인을 찾을 수 있다.

 * 에러의 다른 원인으로는 init.ora 화일의 파라미터 가운데 DC_FREE_EXTENTS나 ROW_CACHE_ENQUEUES의  값
 이 너무 작게 설정된 경우를 생각해 볼 수 있다. 이와같은 경우는 이들 값을 크게 설정해 주도록 한다.

 * 테이블 스페이스가 가득 차거나 Extent  갯수의 최대 허용값을 초과해서 에러가 발생하는  경우 ORA-604
 에러가 함께 발생할 수가 있는데 이와같은 경우에는 이들 문제를 먼저 해결하면 ORA-604 에러는 함께 해결
 된다. 

======================================================================
ORA-01046, ORA-01050, ORA-01051 : CONTEXT SIZE & CURSORS
======================================================================

1. Context size 에 관련한 error message
.ora-1046 :can't acquire space to extend context area.
.ora-1050 :can't acquire space to open context area.
.ora-1051 :maximum context area extents exceeded.

2. Context size란 무엇인가?

(1) 쉽게 말하면 Cursor의 initial size이다 .
즉, Cursor 에 allocate 되는 user memory 이다.
(2) 이는 init.ora 의 CONTEXT_SIZE 에 의해 결정된다.
(3) Cursor 에 할당되는 additional space 는 CONTEXT_INCR 에 의하며 50 extents를 갖는다.
(4) Recommended context size 와 increment 는 4096 bytes(4K) 이다.
(5) SQL statement가 수행시마다 cursor 가 open 되며,같은 cursor가 reuse 되도록 design 되어 SQL*PLUS
    session은 2-3 개 이상 open 되어지지 않는다.
    그러나 SQL*FORMS 는 여러 다른 task 를 수행하므로 많은 cursor를 open한다. (100 or more)

(6)Cursor 가 hold 하는 item
* the SQL statement
* the parsed SQL statement
* one row of the result

3 ORA-1051 은 무엇이 문제인가?
(1) cursor 의 size 를 줄인다
(2) CONTEXT_SIZE,CONTEXT_INCR 를 늘린다.

4 OPEN_CURSORS 수를 줄이는 전략 .
(1) Commit을 자주한다.
(2) Synonym이나 view 를 사용하지 않음으로써 implicit cursor 수를 줄인다.
(3) SQL*FORMS 에서 select 문대신 #COPY 로 바꿔 사용한다.
(4) SQL*FORMS 에서 large forms를 여러개의 작은 forms 로 나눈다
(5) ASAP, EXEC SQL CLOSE C1; 을 수행한다.
(6) HOLD_CURSOR=NO &amp; RELEASE_CURSOR=YES 를 사용한다.

======================================================================
LK FILE에 대하여 (ORA-1102에 대한 원인 설명)
======================================================================

> Unix 용 Oracle7.3.3  이전의 version에서는 parallel  server mode(OPS)로 운용하지  않더라도 서로 다른
 ORACLE_SID를 이용하는  두개의 instance가  하나의 database를  동시에 mount하는  것이 경우에 따라서는
 가능할  수도  있었다 (<Bug:272030>).  이  경우, 서로  독립적인  두개의 instance가  동일한  database
 file들을 동기화  (synchronisation)없이 access할  수 있기  때문에 database  corruption을 유발시킬 수
 있었다.

 Unix system에서의 이러한 문제를 회피하기 위하여  7.3.3부터 'mount lock' file이 이용된다. 이  file은
 그 size가 0 byte, 생성되는 위치는 $ORACLE_HOME/dbs 이며 그 이름은 lk<DB_NAME> 이다.

 Oracle이 database를 mount할 때 lk<DB_NAME> file과 관련하여 다음과 같은 절차를 수행한다.

 1.  file name의  'DB_NAME' 부분은  db_name parameter를  이용한다. 예를  들어, db_name=V803  이라면
 사용되는 lock file의 위치와 이름은  '$ORACLE_HOME/dbs/lkV803'이 된다. 2. 만약 해당  file이 존재하지
 않는다면 생성한다. 존재한다면 file을 open한다. 3. 이 file에 exclusive Unix file lock을 설정한다.

 위의 과정 상에서 문제가  발생된다면 해당 instance는 db를  mount할 수 없으며 ORA-1102('cannot  mount
 database in exclusive mode')가 return된다.

 Releasae  7.3.3  이전에서는  동일한  $ORACLE_HOME, 동일한  db_name을  이용하는  두  개의 database를
 $ORACLE_SID만 다르다면 동시에 open하여 사용할  수 있었다. 그러나 lock file이  사용되는 7.3.3부터는,
 lock  file의 이름에  db_name이 이용되기  때문에 어느  한쪽의 db_name을  변경해야만 동시에  open하여
 사용할  수가  있다.(db_name의  변경은  controlfile을  재생성함으로써  가능하다.)  이렇게 database의
 db_name이 변경되면 각각의 lk<DB_NAME> file을 생성하여
이용하게 된다.


참고 사항
--------

1. database를 구동하고 있는 instance가 있을 때에는 lk<DB_NAME> file은
   삭제하지 않도록 한다.

2. database가 shutdown되더라도 lk<DB_NAME> file은 삭제되지 않고 존재한다.
   따라서 이 file의 유무를 가지고 database의 구동 유무를 판단할 수 없다.

3. lk<DB_NAME>의 DB_NAME은 SID와는 다를 수 있다. SID가 아닌 DB_NAME을 이용함에 주의.

4. lock file과 관련하여 다음의 error들이 발생될 수 있다.
   ORA-9992 scumnt: failed to open <FILENAME>
   ORA-9993 scumnt: failed to lock <FILENAME>
   ORA-1102 cannot mount database in exclusive mode

======================================================================
ORA-1118 조치 방법 : MAXDATAFILES와 DB_FILES PARAMETER
======================================================================

 테이블 스페이스를  만들거나 데이타  화일을 추가하다  보면 ORA-01118:  cannot add  any more database
 files: limit of XXX exceeded와 같은 에러가 발생하는 경우가 있다. 오라클의 데이타 화일의 최대 갯수는
 MAXDATAFILES와 DB_FILES 에  의해서 제한을  받는데 여기서는  이 에러를  해결하는 방법을  알아보기로
 한다.

  * 데이타베이스를  처음 만들  때 사용되는  CREATE DATABASE  명령에서 MAXDATAFILES  라는 파라미터를
 찾아볼 수 있다.  여기서 지정된 값(명시를  안하면 디폴트로 설정)은  콘트롤 화일에 기록된다.  이 값은
 데이타 베이스에  대해서 설정된  최대 데이타화일  갯수이다. 이  값을 변경하려  면 콘트롤 화일을 다시
 만들어야 한다. 

  * 한편, init.ora(UNIX에서는 init<SID>.ora, VMS에서는 <node>_<ora_sid>_init.ora)  에는 DB_FILES라는
 파라미터가 있는데 이 값은 해당 인스턴스에 대해서 지정된 최대 데이타화일 갯수이다. DB_FILES는 단순히
 에디터 상에서 init.ora 화일을 수정한 다음 에DB를 Restartup 하면 새로운 값이 적용된다.

 1. 왜 MAXDATAFILES 와 같은 한계값을 설정하는가?    
 * O/S는 오라클 화일의 갯수를 지정하기  위하여 특정한 갯수의 bit를 사용하며 이 값은 Platform에 따라
 다르다. MAXDATAFILES는 이 값의 영향하에 있게 된다. 일반적인 최대 값은 다음과 같다. 

 V6 V7
 UNIX 62 1022
 VMS  254 1022
 DOS  254 NA 
[참조]일부 유닉스 Platform상의 V7.0.16 이전 버전의 경우 1022보다 작은 경우도 있다.

2. 왜 MAXDATAFILES 값을 가능한 최대로 설정해 두지 않는가? 
  * MAXDATAFILES 를 크게 지정하면 그만큼 콘트롤 화일의 크기도 늘어나기 때문이다.

3. 왜 DB_FILES를 MAXDATAFILES 의 크기만큼 크게 설정해 두지 않는가? 
 * DB_FILES를 늘리면 각 User Process 에 할당되는 PGA(Program Global Area)의 크기가 커지기 때문이다. 

4. 사용하는 시스템의 MAXDATAFILES를 알 수 있는 방법은? 
  * 시스템에 따라서 다르므로 Installation Guide 를 참조해야만 한다. 

5. 콘트롤 화일의 위치를 아는 방법은? 
  * SQLDBA> show parameter control_files;
      또는 
   SQLDBA> select * from v$controlfile; (7.0.16 이상)
  위의 Query 를 이용하거나 $ORACLE_HOME/dbs/config.ora 화일을 보면 알 수 있다.

 [ORA-1118 해결방법] 
 * ORA-1118 에러는 데이타 화일의 갯수가 MAXDATAFILES 값에 도달한 경우 발생한다. DB_FILES 값에 도달한
 경우라면 ORA-59 에러가  발생한다. ORA-59 에러는  init.ora 의 DB_FILES  를 늘려주고 DB  를 Restartup
 하면 해결 되지만 ORA-1118 에러는 이와같이  간단하게 해결되지는 않는다. 다음과 같은 방법이  있다. 
 
 1. 여러개의 데이타화일로 구성된 테이블 스페이스가  있으면 이를 Export 받고 테이블 스페이스를 Drop한
 다음 하나의 큰 데이타화일을 갖도록 테이블 스페이스를 만들고 Import를 한다.  
 
 2. V6.0.33 이전 버젼을 사용중이라면 MAXDATAFILES를 늘리기 위해서는 DB를 새로 만들어야 하며  그 이후 
 버전을 사용중이라면 콘트롤 화일을 새로 만들어서 MAXDATAFILES를 늘릴 수 있다.

 <V7에서 콘트롤화일을 만드는 방법>
 * DB가 mount 또는 open 된 상태에서
  SQLDBA>alter database backup controlfile to trace;  
 와 같은 명령을 내리면 <user_dump_dest>에 지정된  디렉토리에 트레이스 화일이 하나 생긴다. 이  화일을
 찾으려면  해당 디렉토리에서  가장 최근에  생긴 트레이스  화일을 찾으면  된다. 
 
 * 이 화일을 다른 이름으로   복사한 다음   에디터로 열어서   CREATE CONTROLFILE 명령부분 외의 불필요
 한 부분은  지우고 MAXDATAFILES를  늘려  준다. 이  화일의  이름을 newctl.sql로  하기로 한다. 
 
 * DB를 NORMAL 또는 IMMEDIATE로 Shutdown하고, 콘트롤 화일 생성시 DB 영향을 줄 수 있기 때문에 만약을
 위해서 DB 전체를 백업 받도록 한다. 
 
 * 현재 사용중인 콘트롤 화일을 다른 이름으로 옮기고 다음을 실행한다. 

 SQLDBA> startup nomount  
 SQLDBA> @newctl  
 SQLDBA> alter database open noresetlogs;

 * 이제 필요한 모든 작업은 끝났지만 여기서 다시 한번 Full Bakcup 을 받는 것이 좋다.

[ 참고 ]  다음은 콘트롤 화일을 생성하는 명령의 예이다.

 SQLDBA> CREATE CONTROLFILE
      DATABASE ORACLE
      LOGFILE '/users/oracle/dbs/log1ORACLE.dbf',       
                 '/users/oracle/dbs/log2ORACLE.dbf',       
                 '/users/oracle/dbs/log3ORACLE.dbf'   
         NORESETLOGS  
         DATAFILE '/users/oracle/dbs/systORACLE.dbf',       
                  '/users/oracle/dbs/rbsORACLE.dbf',       
                  '/users/oracle/dbs/tempORACLE.dbf',       
                  '/users/oracle/dbs/toolORACLE.dbf',       
                  '/users/oracle/dbs/usrORACLE.dbf'
         MAXDATAFILES 121;
</p>
<p align="right"><A target='_blank'  class='con_link' href="#top"><img src="../images/top.gif" width="33" height="37" border="0"></a></p>
</td>
</tr>

<tr>
<td width="578">
<p>
======================================================================<br />
<b><A target='_blank'  class='con_link' name="ORA-01157">ORA-01157</a>,
<A target='_blank'  class='con_link' name="ORA-01110">ORA-1110</a></b>
:OS 명령으로 DATAFILE을 삭제한 경우<br />
======================================================================<br />
</p>

<PRE><XMP>
 DATABASE RECOVERY에 앞서  ORACLE INSTANCE(즉, ORACLE  RDBMS)의 STARTUP단계를 우선  살펴보기로 하자.
 첫번째 단계로 INSTANCE를 START시키며,  여기서는  initORACLE_SID.ora 화일의 파라미터를 참조하여 SGA
 (SYSTEM GLOBAL AREA)를 할당하고 백그라운드 프로세스를 START 시킨다. 두번째 단계로 DATABASE의 MOUNT
 이며 파라미터 화일에 명시된 CONTROL  FILE을 오픈한다. CONTROL FILE로부터 DATABASE  NAME과 REDO LOG 
 FILE의 이름을 읽는다.
 세번째 단계로 CONTROL FILE 내의 정보를 이용하여 모든 데이타 파일을 오픈한다.

 SVRMGR> CONNECT INTERNAL;
 Connected.
 SVRMGR> STARTUP;
 ORACLE instance started.
 Database mounted.
 Database opened.
 Total System Global Area 1913196 bytes
 Fixed Size 27764 bytes
 Variable Size 1787128 bytes
 Database Buffers 65536 bytes
 Redo Buffers 32768 bytes

 RDBMS의 STARTUP시 문제의 데이타 화일이 CONTROL FILE 정보에서는 존재하지만, 실제로 O/S상에서는 존재하
 지 않으므로 DATABASE OPEN 단계에서 삭제된 데이터 화일을 OPEN할 수 없다. 따라서 다음과 같은 데이타 화
 일 오픈에 관련된 에러가 발생된다 :

 SVRMGR> STARTUP;
  ORACLE instance started
  Database mounted
  ORA-01157 : cannot identify data file 11 - file not found
  ORA-01110 : data file 11 : '/user1/oracle7/dbs/user2.dbf'
  Attempting to dismount database .... Database dismounted
  Attempting to shutdown instance .... ORACLE instance shut down

 DATABASE OPEN단계에서 CONTROL FILE에서는 ORA-1157에러에서 나타난 11번  데이타 화일이 존재하는 것으로 
 인식하지만, 실제로 O/S상의 데이터 화일 (ORA-1110에러에 명시된 '/user1/oracle7/dbs/user2.dbf' 파일)이
 삭제된 상태이다.

 이러한  경우에는  DATABASE  STARTUP 시  STARTUP  MOUNT  단계까지 실행한  후,문제의  데이  터 화일을
 OFFLINE시킨 다음 데이타베이스를 오픈한다. 단, 데이타베이스 오픈이 정상적으로 수행되면 문제가 발생한
 데이타 파일을 포함하고  있는 TABLESPACE를 DROP하지  않을 경우에는 DATABASE  STARTUP 시 항상  데이타
 파일의 오픈 단계에서 에러가 발생된다. 따라서, 문제의 데이타 화일의 OFFLINE과 TABLESPACE의 DROP 전에
 반드시 해당 TABLESPACE를 사용하고 있는 USER의 데이타 백업을 수행해야 한다.

 데이타 화일의 OFFLINE과 관련된 명령은 다음과 같다.
 먼저 SVRMGR을 Line Mode로 기동시킨다.

 $ svrmgrl
 SVRMGR> CONNECT INTERNAL;
 SVRMGR> STARTUP MOUNT;
  ORACLE
  instance started.
  Database
  mounted.

 SVRMGR> ALTER DATABASE DATAFILE '/user1/oracle7/dbs/user2.dbf' OFFLINE DROP;
  Statement processed.

 SVRMGR> ALTER DATABASE OPEN;
  Statement processed.

 SVRMGR> DROP TABLESPACE tablespace_name INCLUDING CONTENTS;
  Statement processed.

 (이와 같이 offline  drop된 datafile을 포함하는  tablespace는 drop하여야 한다.  이 tablespace에 다른
  datafile도 포함되어 있다면 export를 받아낸 후 tablespace를 drop하고 재 생성 후 import하도록 한다.)

 정상적으로 DATABASE가 Open된 후 CONTROL FILE로부터의 데이타베이스 정보를 갖는 DATA DICTIONARY TABLE
 인 V$DATAFILE(SYS USER에서 액세스 가능)의  내용과 데이타베이스 화일에 관한 정보를  가지고 있는 DATA 
 DICTIONARY VIEW인 DBA_DATA_FILES(SYSTEM USER)을 조회하면 아래와 같은 내용을 확인할 수 있다 :

(1) SQL> SELECT * FROM V$DATAFILE ;
    FILE#   STATUS                 NAME
    -----  --------   --------------------------------------
      9     ONLINE      /user1/oracle7/dbs/tools.dbf
      10    ONLINE      /user1/oracle7/dbs/user1.dbf
      11    RECOVER     /user1/oracle7/dbs/user2.dbf

(2) SQL> SELECT * FROM DBA_DATA_FILES ;
          FILE_NAME              FILE_ID     TABLESPACE_NAME STATUS
   ----------------------------  --------   --------------------------
   /user1/oracle7/dbs/tools.dbf    9         TOOLS AVAILABLE
   /user1/oracle7/dbs/user1.dbf    10        TEST AVAILABLE
   /user1/oracle7/dbs/user2.dbf    11        TEST AVAILABLE

====================================================================== ORA-01403 조치 방법 : EXPORT 실행시 ======================================================================

 EXPORT 실행시 ORA-1403이 발생되는 경우가 있는 데,  이 에러는 테이블 혹은 인덱스에 문제가 있는  경우
 발생할 수 있다. 여기서는 ROWID를 사용하여 테이블을 복구시키는 방법을 소개한다.

1. 기존 테이블과 같은 구조를 갖는 테이블을 만든다.

SQL> CREATE TABLE TEMP 
2>   AS SELECT  * 
3>        FROM EMP 
4>       WHERE 1=2; 

2. 기존 테이블에서 RECORD를 FETCH하여 새로운 테이블에 입력.
이 때, INDEX가 설정되어 있는 COLUMN을 WHERE 조건에 부여함. 

<CREATE.SQL>
 declare 
 row_id char(18); 
 cursor c1 is select rowid 
                from emp 
               where empno > 0; --empno에 index 
 begin 
   open c1; 
   loop 
     fetch c1 into row_id; 
     insert into temp select * from emp where rowid=row_id; 
     exit when c1%notfound; 
   end loop; 
 end; 
/ 

3. create.sql file실행 
sql> @create
</XMP</PRE>

<p align="right"><A target='_blank'  class='con_link' href="#top"><img src="../images/top.gif" width="33" height="37" border="0"></a></p>
</td>
</tr>


<tr>
<td width="578">
<p>
======================================================================<br />
 <b><A target='_blank'  class='con_link' name="ORA-01547">ORA-01547</a></b>
조치방법 :ORACLE 블럭을 할당받지 못할 경우<br />
======================================================================<br />
</p>

<PRE><XMP>
 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.

======================================================================
ORA-01562 조치방법 : MAXEXTENTS (DEFAULT 121)에 도달한 경우
======================================================================

 ROLLBACK SEGMENT는 TRANSACTION을 수행하면 필요한 만큼의 EXTENT를 발생하여 그 크기가 증가된 이후에는
 그 TRANSACTION이  COMMIT혹은 ROLLBACK되더라도  SIZE가 줄  어들지 않는다.  (OPTIMAL을 지정하지  않는
 경우)  이것은 DB를  SHUTDOWN후 다시  STARTUP 하여도  마찬가지이며, ROLLBACK  SEGMENT가 자신이  속한
 TABLESPACE로 부터  EXTENT를 할  당받다가 더  이상 할당받을  EXTENT가 없을  때, 혹은 이미 MAXEXTENTS
 (DEFAULT 121)에 도달한 경우에 ORA-1562가 발생한다. 

1. 현재 ROLLBACK SEGMENT가 포함되어 있는 RBS TABLESPACE의 크기 확인 

sqlplus system/manager 
SQL> SELECT  file_name, bytes 
       FROM  dba_data_files 
      WHERE  tablespace_name = 'RBS'; 

         FILE_NAME                 BYTES
------------------------------- ------------ 
/oracle/pms/dbs/rbsPMS01.dbf      20971520 
/oracle/pms/dbs/rbsPMS02.dbf      10485760 

 여기에서 나타난 결과값이 절대적으로 작은 경우 RBS TABLESPACE에 DATAFILE을 ADD 시켜줄 필요가 있다. 

2. 각 ROLLBACK SEGMENT의 SIZE및 발생한 EXTENT의 수 확인 

sqlplus system/manager 
SQL> SELECT  segment_name, initial_extent, next_extent, maxextents, rssize, extents, xacts 
       FROM  dba_rollback_segs a, v$rollstat b 
      WHERE  a.segment_id = b.usn; 

결과는 다음과 같은 형태로 나온다. 
 (1) INITIAL_EXTENT는 ROLLBACK SEGMENT가 필요한 경우 처음으로 자신의 SPACE를 잡는 크기이며, 이 크기만
  큼의 연속된 공간을 RBS TABLESPACE로 부터 잡는다. 
 (2) NEXT_EXTENT는 INITIAL_EXTENT를 잡은 후에 추가적으로 SPACE가 필요한 경우 이 크기만큼씩 SPACE를 잡
  게 된다. 
 (3) MAXEXTENTS는 각 ROLLBACK SEGMENT에 지정된 최대 발생가능한 EXTENT의 갯수이다.
  여기에 설정된 값 이상의 EXTENT를 발생시킬 수 없다. 
 (4) RSSIZE는 현재 각 ROLLBACK SEGMENT가 잡고 있는 RBS TABLESPACE내의 ROLLBACK SEGMENT의 크기이다. 
 (5) EXTENTS는 현재 각 ROLLBACK SEGMENT별로 발생한 EXTENT의 갯수이다. 
 (6) XACTS는 현재 각 ROLLBACK SEGMENT를 잡고 있는 ACTIVE ROLLBACK TRANSACTION의 갯수이다. 
  ROLLBACK SEGMENT를 OFFLINE하거나 DROP할 때는 이 XACTS가 0인지 확인하고 작업하여야 한다. 

 (컬럼 이름은 편의상 축소하였다.) 
  SEGMENT   INITIAL    NEXT      MAX    RSSIZE    EXNTENTS    XACTS 
 --------- --------- -------- -------- --------- ---------- -------- 
 SYSTEM      262144   262144     121    407552        8         0
 R01         262144   262144     121    530432        2         0
 R02         262144   262144     121    3192832      12         0 
 R03         262144   262144     121    5056512      19         0 
 R04         262144   262144     121    11180032     42         1 

 이때 ORA-1562발생시  표시된 message에  나타난 ROLLBACK  SEGMENT이름의 EXTETNS가  MAX_EXTETNS의 수와
 같으면, 이것은 그 ROLLBACK SEGMENT가 MAXEXTENT에 도달하여 이 오류가 발생한 것이고, 그렇지 않은 경우
 는 TRANSACTION에 필요한 SPACE가 더 이상 RBS TABLESPACE에 FREE SPACE로 남아 있는 것이 없어서 발생한 
 것이다. 

3. 가능한 조치 방법 

 (1) 2번의  QUERY 결과  MAXEXTENT에 도달하지도  않았고, 오류가  발생한 TRANSACTION을  처리할 만큼 큰
 크기의 RSSIZE가 있는 ROLLBACK SEGMENT도 없는  경우에는 1번의 조회 결과 나타난 RBS의  DATAFILE이외에
 추가적으로 RBS TABLESPACE에 새로운 DATAFILE을 추가하여야 한다. 

 sqlplus system/manager 
 SQL> ALTER TABLESPACE rbs ADD DATAFILE '/oracle/pms/dbs/rbsPMS03.dbf' SIZE 50M; 

 (2)  2번의 조회를  확인한 결과,  오류가 발생한  ROLLBACK SEGMENT의  RSSIZE보다 큰  RSSIZE를 가지는
 ROLLBACK  SEGMENT가 존재하여  이 TRANSACTION을  수행하기에 충분  하다고 판단되는  경우 그  ROLLBACK
 SEGMENT를  지정하여 사용할  수 있다.  RSSIZE가 매우  큰 ROLLBACK  SEGMENT가 R04라고  할때, SQLPLUS
 상에서는 다음과 같이 하면된다. 

 SQL> SET TRANSACTION USE ROLLBACK SEGMENT r04 ; 

 일반적으로 BATCH JOB과 같이 ROLLBACK SEGMENT가 많이 필요한 TRANSACTION에 대해서는 INITIAL과  NEXT가
 크게 지정되어 있는 큰 크기의 ROLLBACK SEGMENT를 지정하여 사용하는 것이 효율적이다. 

 (3) 2번의 조회에서  획인 된 INITIAL_EXTENT와  NEXT_EXTENT가 작아 실제로는  RBS의 FREE SPACE가  남아
 있는데도 MAXEXTENT에 도달하여 ORA-1652가 발생하는 경우 ROLLBACK SEGMENT의 INITAL과 NEXT를 크게 하여 
 ROLLBACK SEGMENT를 재생성할 수 있다. 

 참고)
 각 TABLESPACE별 FREE SPACE는 다음과 같은 방법으로 확인가능하다. 
 sqlplus system/manager 
 SQL> SELECT tablesapce_name, sum(bytes), max(bytes) 
        FROM dba_free_space 
       GROUP BY tablespace_name; 

 (4) 이러한 ROLLBACK SEGMENT에 관한 오류는 ROLLBACK SEGMENT가 일단 필요한 SPACE를 확보한 이후에는 그
 크기가 줄어들지 않는 것이 그 원인이 될 수도 있는데 이때 ROLLBACK SEGMENT에 OPTIMAL SIZE를  지정하면
 어느 정도의 해결이 가능하다. OPTIMAL을 지정하면 ROLLBACK SEGMENT가 그 크기 이상으로 증가되는  경우,
 이후 OPTIMAL로 지정된 크기만  유지하도록 ROLLBACK SEGMENT가 줄어들게  된다. 이때, 이값을 너무  작게
 잡으면 빈번하게 ROLLBACK SEGMENT가 늘어나고  줄어드는 작업으로 인해 PERFORMANCE에 지장을  초래할 수
 있으므로 20~30개의 EXTENT정도를 보유할 수 있도록 한다. 

OPTIMAL의 지정 방법은 ROLLBACK SEGMENT생성시나 그 이후에 다음과 같이 하면 된다.

 sqlplus system/manager 
 SQL> CREATE ROLLBACK SEGMENT r01 
             TABLESPACE rbs 
             STORAGE (INITIAL 1M NEXT 1M OPTIMAL 20M) ; 

 이미 생성된 rollback segment에 대해서는, 
 SQL> ALTER ROLLBACK SEGMENT r01 STORAGE(OPTIMAL 20M);

======================================================================
ORA-01578 조치 방법 : seq=0 이고 inc<>0(새로운 블럭이 아님)일 때
======================================================================

<PRE> 모든 오라클  데이타 블럭은 Sequence  번호(seq)와 Incarnation 번호(inc)를 갖고 있다. ORA-1578  에러는 seq=0 이고 inc <> 0(새로운 블럭이 아님)일 때 발생한다.  ORA-1578 에러는 ORA-600[3339] 에러와 함께 발생하곤 한다.  * ORA-1578 에러가 발생하면  Corruption이 발생한 화일번호와 블럭번호를 알려준다. 여기서는 이 때의 화일번호를 f, 블럭번호를 b 라고 부르기로 한다.  <해결방법> 1. 우선 해야 할 일은 어떠한 오브젝트가 Corrupt  되었는가를 알아내는 것이다.    다음의 스크립트를 이용하면 알 수 있다.    SQL> select segment_name, segment_type        from dba_extents        where file_id = f and       between block_id and block_id + blocks - 1; 2. 만약 해당 세그먼트가 인덱스이면 Drop 시키고 다시 생성하면 된다.  3. 만약 해당 세그먼트가 테이블이면 Corrupt 된 블럭의 데이타는 손상된 것이다.  4. 만약 해당 테이블이 들어있는 엑스포트 화일이 있다면 손상된 테이블을 Drop 시키고 임포트 받는 것이 제일 간단한 방법이다. 하지만 만약 엑스포트 받은 파일이 없거나 백업해 둔 화일도 없다면 해당 테이블에 인덱스가 생성되어 있는 경우에 한해서 다음의 방법을 사용해서 복구를 하도록 한다. * empno, ename, deptno 를 컬럼으로 가지는 EMP 테이블이 Corrupt되었다고 가정하자. 그리고 empno 컬럼에 인덱스가 생성되어 있다고 하자. 클러스터화되지 않은 모든 테이블은 유니크한 Rowid 를 가진다. Rowid를 Varchar2/hexadecimal 형식으로 표현하려면 Rowidtochar 함수를 이용한다. SQL> select rowid to_char(rowid) from emp; * Rowid는 총 18자로 블럭어드레스(8자), 점(1자), 로우 어드레스(4자), 점(1자), 화일 어드레스(4자)로 구성되어 있다.  SQL> select empno, rowid       from emp        where empno > 0     위의 스크립트를 실행시키면 다음과 같은 결과를 얻게 된다.      EMPNO             ROWID      ------------     --------------------------------      100          00000003.0000.0006        101          00000003.0001.0006         102          00000003.0002.0006         103          00000003.0003.0006      500         00000004.0000.000A        501          00000004.0001.000A        755         0000001A.0005.000A        756          0000001A.000C.000A   * 만약 인덱스가 Character 컬럼에 대한 것이었다면, 위의 Query 문장을 다음과 같이 바꿀 수 있다.  SQL> select empno, rowid          from emp     where empno > '';     * 예를 들어 다음과 같은 에러  메시지가 떨어졌다고 하자.   01578, 00000, 'ORACLE data block corrupted (file # 10, block # 4)   그러면 다음의 스크립트를 사용하여  손상된 블럭에 있는 employee 에 대한 empno를 구할 수 있다.   SQL> select empno  from emp   where empno > 0 and rowid tochar(rowid) like '00000004.%.000A';      EMPNO         ROWID        ----------  --------------------------------      500      0000004.0000.000A        501      00000004.0001.000A   * 이제 EMP 테이블과 같은 구조를 갖는 새로운 테이블을 만든다.     SQL> create table temp       as select * from emp where 1 = 2;   * 그리고는 손상된 부분을 피해서 새로운 테이블에 손상된 테이블의 데이타를 추가한다.     SQL> insert into temp select * from emp where empno < 500;       SQL> insert into temp select * from emp where empno > 501;   손상된 테이블을 Drop시키고  Temp 테이블의 이름을 EMP 로 변경한다.  그리고 백업된 자료나 문서자료를 통하여 손상된 부분에 대한 정보를 추가한다.     5. 손상된 블럭에 여러개의 로우가 존재하고 있다면 다음의 방법을 이용한다.  SQL> create table empnos as         select empno from emp         where empno > 0          and rowid to_char(rowid) not like '00000004.%.000A'; 이 스크립트를 이용하면 손상된 블럭에 포함되지 않은 empno 들을 알 수 있다. * 다음의 스크립트를 계속 실행시켜 복구를 한다.  SQL> create table temp as select * from emp where 1 = 2; SQL> insert into temp       select emp.empno, emp.ename, emp.deptno         from emp, empnos       where emp.empno > 0       and emp.empno = empnos.empno;   6. 만약 데이타 딕셔너리의 테이블이나 인덱스에서 손상된 블럭이 발생했다면 지원을 요청해야 한다.

======================================================================
ORA-01628 ORA-01630 ORA-01631 ORA-01632 조치 방법 : MAXEXTENTS에 도달했을때
======================================================================

다음 ORA 에러들은 오라클의 오브젝트들이 MAXEXTENTS에 도달했을 때 발생하는 것들이다.

01628, ' max # extents (%s) reached for rollback segment %s ' 
01630, ' max # extents (%s) reached in temp segment in tablespace %s '
01631, ' max # extents (%s) reached in table %s.%s ' 
01632, ' max # extents (%s) reached in index %s.%s '

또한 ORA-1628 다음에는 ORA-1562 에러도 함께 발생한다. 

이 에러들은 다음 모든 LEVEL 에서 발생될 수 있다.
. 에플리케이션 LEVEL (GL, AOL, Financials, Etc) 
. TOOLS LEVEL (Reports, Forms, Etc) 
. Kernel LEVEL (Insert, Update, Delete) 

이 에러의 이유는 오브젝트의  익스텐트가 MAX # 에 도달했기 때문에 발생되며,  오브젝트의 MAXEXTENTS는 
STORAGE의 MAXEXTENTS 파라미터에 의해 결정된다.

다음 예를 보기로 하자. 

SQL> INSERT INTO TAB1 SELECT * FROM TAB1; 
     ORA-01631 : max # extents (2) reached in table JANE.TAB1

SQL> SELECT  INITIAL_EXTENT, NEXT_EXTENT, MAX_EXTENTS 
       FROM  USER_TABLES
      WHERE  TABLE_NAME = 'TAB1'; 

   INITIAL_EXTENT   NEXT_EXTENT  MAX_EXTENT
  ---------------  ------------  ----------
        6144           10240         2

위 예에서 오브젝트의 MAXEXTENTS 는 2 인데 이 값은 HARDCORD된 MAX 값이 아니다.
HARDCORD 된 MAXEXTENTS의 최대값은 데이타베이스가 생성될 당시 지정된 DB_BLOCK_SIZE 의 값에 따라 다르다.

   DB_BLOCK_SIZE       최대 MAXEXTENTS 값 
-------------------    ------------------
       512                    25
        1K                    57
        2K                    121
        4K                    249
        8K                    505


만일 최대 MAXEXTENTS 값보다 더 큰 MAXEXTENTS를 Storage 에서 지정하면 다음 에러가 발생한다. 
ORA-02226, 00000, ' invalid MAXEXTENTS value (max allowed: %s) '

다음은 ORA-0163x 에 대한 해결 방법이다. 
만일 platform의 최대 MAXEXTENTS 에 도달이 안 되었으면 ALTER TABLE .. STORAGE (MAXEXTENTS n);
를 사용하여 최대 MAXEXTENTS 값보다 작은 수로 MAXEXTENTS를 늘려준다. 
만일 최대 MAXEXTENTS 값에 도달했으면 해결할 수 있는 방법은 MAX 제한에 도달되지 않도록 EXTENT SIZE 를 
더 크게하여 오브젝트를 다시 생성하는 것이다.
만일 이 에러가 ROLLBACK SEGMENT 에서 발생되면 DROP하고 다시 생성한다. 
만일 에러가 TEMPORARY TABLESPACE에서 발생되면 TEMPORARY TABLESPACE의 STROAGE를 변경한다. TEMP SEGMENT
는 그것이 생성된 TABLESPACE의 Default Storage Parameter를 사용하기 때문에 다음과 같은 방법으로 해결할 
수 있다.


ALTER TABLESPACE 'tempname' DEFAULT STORAGE (INITIAL n NEXT n);
. n 은 기존 지정된 값보다 큰 값을 지정한다.
ALTER TABLESPACE 'tempname' DEFAULT STORAGE (PCTINCREASE m);
. m 은 기존 지정된 값보다 큰 값을 지정한다. 

만일 에러가 TABLE에서 발생되면 export/import utility를 사용하여 그 TABLE을 다시 생성한다. 


[ 단계 ] 예를 들어 scott user의 emp table이 121개의 extent에 도달했다고 가정
1. table을 export한다. 
 예) $ exp scott/tiger file=emp.dmp tables=emp 

2. table을 drop하거나 export가 실패한 경우를 대비해서 기존 TABLE을 RENAME 한다.
 예) SQL> drop table emp; 또는  
     SQL> RENAME EMP TO EMP_OLD;
 
3. storage절을 변경하여 table을 생성한다.
 SQL> create table emp(empno.....) storage (intial 10M next 1M pctincrease 0);
 여기에서 initial 10M과 next 1M은 예로 든 것이므로 고객 환경에 적당하게 설정한다. 
 pctincrease는 0로 한다.

4. 사용자의 SCHEMA 에 임포트를 실행하여 TABLE을 생성함.
 이 때 위에서 생성된 table에 import가 되도록 ignore=y option을 사용
 예) $imp scott/tiger file=emp.dmp tables=emp ignore=y commit=y 

5. 2번에서 table을 rename하였다면 import가 잘 수행되었는지 확인하고 기존 테이블은 DROP 함.
 예) SQL> DROP TABLE EMP_OLD;

======================================================================
ORA-0162x ORA-0163x조치 방법 : MAXEXTENTS에 도달 했을때 발생
======================================================================

INITIAL_EXTENT  
다음 ORA 에러들은 오라클의 오브젝트들이 MAXEXTENTS에 도달 했을때 발생하는  것들이다.
01628, 00000, 'max # extents (%s) reached for rollback segment %s'      
01630, 00000, 'max # extents (%s) reached in temp segment in tablespace %s'
01631, 00000, 'max # extents (%s) reached in table %s.%s' 
01632, 00000, 'max # extents (%s) reached in index %s.%s' 

 또한  ORA-1628 다음에는 ORA-01562도 함께 발생한다. 

 이 에러들은 다음 모든 LEVEL에서  발생 될 수 있다.
  &sect;  에플리케이션 LEVEL (GL, AOL, Financials, Etc)
  &sect;  TOOLS LEVEL (Reports, Forms, Etc)      
  &sect;  커널  LEVEL (Insert, Update, Delete)    

 이 에러의 이유는 오브젝트의 익스텐트가 MAX #에 도달 했기 때문에 발생되며 오브젝트의 MAXEXTENTS는 
 STORAGE의 MAXEXTENTS 파라미터에 의해 결정된다.  

다음 예를 보기로 하자.  


SQL>; INSERT INTO TAB1
      SELECT * FROM TAB1;           
   ORA-01631: max
# extents (2) reached in table JANE.TAB1
SQL> SELECT  INITIAL_EXTENT, NEXT_EXTENT, MAX_EXTENTS       
       FROM  USER_TABLES                
      WHERE  TABLE_NAME = 'TAB1';

   INITIAL_EXTENT NEXT_EXTENTS MAX_EXTENT
     --------------  ------------  ---------- 
         6144          10240        2

위 예에서 오브젝트의 MAXEXTENTS는 2 인데 이 값은 HARDCORD된 MAX 값이 아니다.     
HARDCORD 된 MAXEXTENTS의 최대값은 데이타베이스가 생성될 당시 지정된 DB_BLOCK_SIZE 의 값에 따라 다르다.

======================================================================
ORA-01632 조치 방법 : INDEX REBUILD
======================================================================

 ORA-01632 에러는 index가 확장하려고 할 때 maxextents 값의 제한에 도달하여 더이상 extents를 일으키지
 못하는 경우입니다.  이 에러의  경우 보통은  index의 storage  절의 initial,  next가 작아서  발생하기
 때문에 근본적으로 storage의 initial, next를 크게 키워 주면서 다시 만드는 것이 좋습니다. 그러나 현재
 다시 생성하는 것이 어렵다면  일단 maxextents만 키워서 사용을 하다가 나중에 작업을 할 수도 있습니다.

maxextents를 키우려면 (이 기능은 7.3 이상부터 가능)

SQL> alter index i_dept_deptno storage (maxextents 200);
 과 같이 실행하면 됩니다. 위와 같이 index가 일반  index가 아니라 primary key  index인 경우는 index만 
 drop 했다가  다시 생성할 수는 없습니다.  그러므로 primary  key를 다시  만들면서 지정하거나  index를 
 rebuild 해야 합니다. 일반 index의 경우는 index를 다시 생성하거나 rebuild하면 되는데, 보통 다시 생성
 하는 것보다 rebuild하는 것이 속도가 좋습니다.

1. index를 rebuild하는 방법

 SQL> alter index pk_dept rebuild
    2 tablespace ind_data
    3 storage (initial 1M next 1M);

2. primary key 생성 시 storage 지정하는 방법

 SQL> alter table dept drop primary key;
 SQL> alter table dept add constraint pk_dept
   2 primary key (deptno)
   3 using index tablespace ind_data
   4 storage (initial 1M next 1M);

======================================================================
ORA-01652 조치 방법 : tablespace에 space가 부족
======================================================================

 ORA-165X error는 tablespace에 space가 부족해서 table이나 rollback segment extent가 할당되지  못해서
 발생하는 error이다. 다음의 에러들은 tablespace에 space가 부족해서 발생하는 사항들이다. 
 01652, 00000, 'unable to extend temp segment by %s in tablespace %s' 
 01653, 00000, 'unable to extend table %s.%s by %s in tablespace %s' 
 01654, 00000, 'unable to extend index %s.%s by %s in tablespace %s' 
 01655, 00000, 'unable to extend cluster %s.%s by %s in tablespace %s'

1. Tablespace space 부족 현상의 예 
다음의 테이블 생성 문장을 보자. 

 SQL> CREATE TABLE FEATURE 
   2> (feature_code varchar2(4) primary key, 
   3> feature_desc varchar2(3) );

ORA-01652, 00000, 'unable to extend temp segment by 6144 in tablespace VESSEL'
테이블 스페이스 VESSEL 에 남아있는 가장 큰 연속된 공간을 확인해 보면 

 SQL> SELECT MAX(blocks), MAX(bytes)
   2> FROM DBA_FREE_SPACE 
   3> WHERE TABLESPACE_NAME = 'VESSEL';

  blocks bytes
  6143 12,580,864

위의 결과를 보면 현재 VESSEL 에 남아있는 가장 큰 연속된 공간은 6143 블록인데 
오라클은 6144 블럭이 사용하려다 이를 할당받지 못하여 에러가 발생하게 된 것이다.

2.tablespace space 부족현상의 조치 
tablespace에 space가 부족해서 에러가 발생하는 경우 
아래의 몇 가지 방법을 이용해 조치가 가능하다. 

(1) 데이타 화일을 추가하여 테이블스페이스의 크기를 확장한다. 

 SVRMGR> ALTER TABLESPACE data ADD DATAFILE '/usr/../oracle/data2.dbf' SIZE 100M; 

 이때의 tablespace 가 SYSTEM  일 경우는 user 의  default tablespace가 잡혀있지 않기  때문에 근본적인
 해결이 필요하다. 이 경우는 무작정 tablespsace 를 늘리지 말고 user의 default tablespace를  create 후 
 user에게 할당해 주도록 한다. 

예) 
 SVRMGR> CREATE TABLESPACE tablespace_name datafile '......' size 100m; 
 SVRMGR> ALTER USER user_name IDENTIFIED BY passwd 
       > DEFAULT TABLESPACE tablespace_name 
       > TEMPORARY TABLESPACE temp ; 

(2) 테이블(rollback segment)의 storage parameter를 조정하여 현재 남아있는 영역에 들어갈 수 있도록 한다. 

SQLDBA> ALTER TABLE emp STORAGE(NEXT 1M); 

이 경우 tablespace가 fragmentation이 심한 경우가 아니면 효과적이지 못하다. 

(3) 테이블스페이스가 fragmentation이 심한 상태이면 exp/imp를 이용하여 테이블 스페이스를 재구성 한다. 

3. V7.1에서의 ORA-1652 에러 테이블이나 인덱스 등을 만들 때 자신의 TEMP TABLESPACE가 아닌 곳에서 
 ORA-1652(temp tablespace가 부족함) 에러가 발생하는 경우가 있다. 이와 같은 문제는 V7.1에서만 발생하는데
 V7.1에서는 테이블, 인덱스 등을 병렬로 생성할 수 있다. 이를 위하여 실제로 테이블 등이 생성될 공간에 
 Temporary Segment를 만들게 되는데 이 과정에서 Temporary Segment를 만들 공간이 부족하게 되면 실제의 
 테이블이 생성되는 테이블 스페이스에 대하여 ORA-1652 에러가 발생하게 되는 것이다. 
 이 에러를 해결하는 방법은 에러메시지에서 보여주는 대로 해당 테이블스페이스에 Temporary Segment가 생성
 될 만한 연속된 공간을 마련하여 주는 것이다.

=====================================================
ORA-1653, ORA-1658 : TABLESPACE 크기를 확장하는 방법
=====================================================

 오라클  7.1 이하에서는  tablespace를 확장하려면  해당 tablespace에  데이타 화일을  추가하는 방법을
 사용한다. 이 때  추가하는 데이타 화일의  이름은 기존의 화일과  동일한 이름이 아니기만  하면 되지만,
 편의상 기존의 화일에 일련 번호를 붙여서 사용하는 것이 일반적이다. 

 예를 들어 tablespace TOOLS 를 확장한다고 가정하면

 $sqlplus system/manager

 SQL> select  file_name, bytes
        from  dba_data_files
       where  tablespace_name = 'TOOLS';

 이와 같이 하면 현재  TOOLS tablespace를 구성하고 있는  화일 이름과 크기 (bytes)가  출력된다. 여기서
 출력된 file_name 이 /oracle/dbs/toolsORA.dbf 라고 한다면 다음과 같이 하여 tablespace를 확장한다.

 SQL> alter  tablespace tools
        add  datafile '/oracle/dbs/tools2ORA.dbf' size 50M;
 여기서는 화일의 크기를 50M 로 주었는데 이것은 디스크의 FREE SPACE 와 기존의 데이타 화일의 크기  및
 앞으로 들어갈 데이타의 크기 등을 고려하여 적절한 값으로 결정하도록 한다.

 오라클 7.2 에서는 위의 방법 외에도 기존의 데이타화일의 크기를 변경시켜서 확장시킬 수 있다.

 예를 들어 TOOLS tablespace가 현재 50M 크기의 /oracle/dbs/toolsORA.dbf 화일로 구성되어 있다면 다음과 
 같이 해서 이 화일의 크기를 100M 로 늘릴 수 있다.

 SQL>alter database datafile '/oracle/dbs/toolsORA.dbf' resize 100M;

 RESIZE 옵션은  V7.2 에서  추가된 것으로  기존의 데이타  화일을 확장  또는 축소할  수 있다. 축소하는
 경우는 데이타가 들어 있는 경우 하한선 이하로 내려가지는 않는다.

 한편, 데이타가 계속 들어가서 tablespace를 꽉 채우게 되면 다음과 같은 명령을 이용하여 자동적으로 
 tablespace를 확장할 수도 있다.

 SQL> alter database datafile '/oracle/dbs/toolsORA.dbf' autoextend on next 10M maxsize 200M;

 이렇게 하면 데이타가 늘어나면서 자동적으로 10M 씩 데이타화일의 크기가 늘어나게 된다. 여기서는 최대 
 200M 까지 늘어날 수 있도록 설정하였다.


======================================================================
ORA-01654 : INDEX SEGMENT
======================================================================

01654, 00000, 'unable to extend index %s.%s by %s in tablespace %s' 
예) unable to extend index owner.object by 40964 in tablespace INDEX;

1. tablespace에 남아 있는 공간 중 가장 큰 연속된 공간의 사이즈를 구합니다.
   SELECT  max(bytes)
     FROM  dba_free_space 
    WHERE  tablespace_name = 'TABLESPACE NAME'; 

 ora-1654 에러가  났던 tablespace  이름을 대문자로  위에 써줍니다.  위에 나온  수치는 연속된 block들
 가운데  가장  큰 사이즈의  extent를  보여주는 것인데,  next  extent를 할당하기  위해서는  위에 나온
 수치보다 더 큰 사이즈를 필요로 하는 것입니다.

 'The above query returns the largest available contiguous chunk of space.'

2. index의 storage parameter인 next_extent 값과 pct_increase 값을 확인합니다.
   SELECT  next_extent, pct_increase 
     FROM  dba_indexes 
    WHERE  index_name = 'INDEX NAME' AND owner = 'OWNER';

 ora-1654 에러가 발생한 index의 next extent 값과 pct_increase 값이 얼마인지 확인해 보십시오.
 위에서 나타난 next_extent 값과 max(bytes) 값을 비교해 보세요.

3. 인스턴스의 db_block_size를 확인합니다.
   vi $ORACLE_HOME/dbs/initSID.ora

 db_block_size = 2048 또는 4096 또는 8192일 것입니다.

 ora-1654 에러에 나타난  by 다음의 수치(예:40964)  * db_block_size 만큼의  사이즈가 next_extent(byte
 단위) 값과 같을 것이며, 이 만큼의 extent 영역을 할당할 수 없다는 뜻입니다.
 따라서 datafile을 추가시 이 byte 값 이상의 사이즈를 추가해야 합니다.

4. ora-1654 에러를 해결하는 방법

 There are several options for solving failure to extend. 

 Manually Coalesce Adjacent Free Extents
 ---------------------------------------

 ALTER TABLESPACE <tablespace name> COALESCE;
 The extents must be adjacent to each other for this to work.

 Add a Datafile: 
 ---------------

 ALTER TABLESPACE <tablespace name> ADD DATAFILE '<full path and file 
 name>' SIZE <integer> < |k|m>; 

Lower 'next_extent' and/or 'pct_increase' size:
-----------------------------------------------

For non temporary segment problem: 

ALTER <object><PARAM NAME="AllowScriptAccess" VALUE="never" > <object name><PARAM NAME="AllowScriptAccess" VALUE="never" > STORAGE ( next <integer> < |k|m> 
pctincrease <integer>); 

For a temporary segment problem: 

 ALTER TABLESPACE <tablespace name> DEFAULT STORAGE 
 (initial <integer> next <integer> <|k|m> pctincrease <integer>); 

 Resize the Datafile: 
 -------------------- 
 ALTER DATABASE DATAFILE '<full path and file name>' RESIZE <integer><k|m>;

======================================================================
ORA-04031 조치 방법 : Shared pool에서 연속적인 메모리 부분을 찾지 못해 발생
======================================================================

우리는 다음과 같은 작업수행 시 Oracle 이 Shared pool에서 연속적인 메모리 부분을 찾지 못해 ORA-4031 
Error를 발생시키는 것을 볼 수 있다. 
 - PL/SQL Routine 
 - Procedure 수행시 
 - Compile 시 
 - Form Generate 또는 Running 시 
 - Object 생성하기 위해 Installer 사용시 

1. Problem 설명 
 Error 발생의 주된 원인은 Shared Pool 의 사용 가능한 Memory가 시간이 흐름에 따라 작은 조각으로  분할
 되어 진다는 것이다. 그래서 큰 부분의  Memory를 할당하려 한다면 Shared Memory가 부족하다는  ORA-4031
 Error가 발생한다. 즉, 전체적으로는 많은 양의 사용 가능한 Space 가 있다하더라도 충분한 양의 연속적인
 Space가 없으면 이 Error가 발생한다. 

2. Problem 해결 방안 
 이 Error 해결 방안을 살펴 보면 다음과 같다. 

 (1) Shared Pool 의 Size를 적절히 조절한다. 
 이 Size는 Default 값이 3.5M~9M로 되어 있지만 실제 운용 데이타베이스의 경우에는 이 이상으로 이용하는
 곳이 많다. 이 Size를 수정시는 DB를 Shutdown 후 다시 Start 시켜야 하므로 항상 가능한 해결 방법이 될 
 수는 없다. 

 (2) Object를 Shared Pool에 맞추어 Fragmentation을 줄인다. 
 (Dbms_Shared_Pool Procedure 이용) 

 (3) Shared Pool 을 효율적으로 사용하도록 Application Program을 조절한다. 
 DBMS_SHARED_POOL STORED PROCEDURE 
 이 stored pakage는 dbmspool.sql을 포함하며 7.0.13 이상 version에서 사용가능하다. 
 이는 다음과 같이 3가지 부분으로 나누어 진다. 

 (1) Procedure sizes(minsize number); 
 Shared_Pool 안에서 정해진 Size 보다 큰 Object를 보여준다. 

 (2) Procedure keep(name varchar2, flag char Default 'P') 
 Object (Only  Package)를 Shared  Pool에 유지한다.또한  일단 Keep한  Object는 LRU Algorithm에 영향을
 받지 않으며 Alter System Flush Shared_Pool Command 에 의해 Package 의 Compiled Version 이 Shared 
 Pool 에서 Clear 되지 않는다. 

 (3) Procedure unkeep(name varchar2);keep() 의 반대기능이다. 
 이 Procedure들과 사용법에 대해 보다 더 자세한 정보를 위해서는 $ORACLE_HOME/rdbms/admin/dbmspool.sql 
 script를 참조 바랍니다.

======================================================================
ORA-07329 ORA-07331 ORA-07279: SHARED MEMORY 문제
======================================================================

1. 왜 Problem 이 생기나?
 * Oracle 은 Process와 SGA(System Global Area) 간의 Communication를 위해 Shared Memory와 Semaphore를
 사용한다. Oracle Instance 가 뜰 때 SGA를 Create하기 위해 Main Memory의 임의의 부분을 할당하는데  이
 때 Shared Memory 나 Semaphore 가 적절하지 않으면 이에 관련한 Error가 발생한다. 
 
2. 해결 방안
 SGA는 Shared Memory 안에 생기므로 Shared Memory 는 각 Process에게 사용 가능해야 한다.
 Shared memory 와 Semaphore parameter 는

 - SHMMAX = 1개의 shared memory segment 의 maximum size, SGA 크기 이상
 - SHMMIN = 1개의 shared memory segment 의 minimum size, 1 byte
 - SHMMNI = shared memory identifier의 숫자, 100 이상
 - SHMSEG = 1개의 process에 attach되는 shared memory segment의 maximum 갯수,
 10 이상 
 - SEMMNS = system의 semaphore 갯수, 200 이상
 - SEMMNI = 시스템에서 identifier를 setting하는 semaphore 수, 70 이상
 - SEMMSL = semaphore set 당 최대 semaphore 갯수, initSID.ora 의 processes값 이상

* 추천하는 Semaphore와 Shared Memory Parameter

   Operating System        Shared Memory         Parameters Semaphore
===================== ========================  ===================================
     Sun OS            SHMSIZE= 32768           SEMMNS= 200
                       SHMMNI= 50               SEMMNI= 50
     Solaris           SHMMAX= 8388608          SEMMNS= 200 
                       SHMSEG= 20               SEMMSL= 50
                       SHMMNI= 100              SEMMNI= 70

      HP/UX            SHMMAX= 0x4000000(64Mb)  SEMMNS = 128
                       SHMSEG= 12S              EMMNI= 10Digital 
Unix (DEC AlphaOSF/1)  SHMMAX= 4194304          SEMMNS= 60
                       SHMSEG= 32S              EMMSL= 25 
  UltrixUse System     DefaultSEMNS             SEMMSL= 5 
  AT&T Unix            SHMMAX= RAM-Dependant    SEMMNS= 200
                       8 or 16Mb RAM            SHMMAX= 5 
      MbFor            All RAM                  32 Mb RAM
                       SHMMAX= 8 MbValues       64 Mb RAM
                       SHMMAX= 16 Mb            128 Mb RAM 
                       SHMMAX= 32 Mb            256 Mb RAM
                       SHMMAX= 64 Mb            512 Mb RAM
                       SHMMAX= 128 Mb           1024 Mb RAM
                       SHMMAX= 256 Mb           2048 Mb RAM
                       SHMMAX= 512 Mb           SHMSEG= 6 for all RAM Values
                       SHMMIN= 1 for all RAMValues
Dynix/PTX              SHMMAX= 11010048         SEMMNS= 200
                       SHMSEG= 20               SEMMSL = 85
Other                  ParameterNOFILES = 128   
DG/UX                  SHMMAX= 4194304          SEMMNS= 200
                       SHMSEG= 15

 Shared Memory 와 Semaphore  Parameter는 OS 의 Kernel  Configuration 화일에 반드시 지정되어야  하며,
 File의 위치는 OS마다 차이가 있다. 현재의 Shared Memory와 Semaphore Configuration 을 알기 위해서는
다음의 Command를 이용한다.

$ sysdef |more 

* HP-UX (relevant sections only) 에서의 예: 

Semaphore 관련 Parameters 
- maximum value for semaphores(semaem)= 16384 
- Semaphore map(semmap)= 4098 
- number of semaphore identifiers(semmni) = 4096 
- total number of semaphores in the system(semmns) = 8192 
- number of semaphore undo structures(semmnu) = 1536 
- semaphore undo entries per process(semume) = 512 
- semaphore maximum value(semvmx) = 32767 

Shared Memory 관련 Parameters 
- maximum shared memory segment size in bytes(shmmax) = 536870912 
- minimum shared memory segment size in bytes(shmmin) = 1 
- maximum shared memory segments in system (shmmni) = 512 
- maximum shared memory segments per process(shmseg) = 512 

NOTE: SHMMAX는 현 system에 8개의 instance가 수행될 수 있는 충분한 값이다.


* Shared memory 또는 semaphore parameters 를 변경하기 위해서는 ... 

1. Oracle Instance를 Shutdown 한다. 
2. OS의 Kernel Configuration File이 있는 곳으로 간다. 
3. System Utility 또는 Editor를 이용해서 필요한 값을 바꾼다. 

System Utility는 다음과 같다 
----------------------------
|    OS    |  Utility      |
----------------------------
| HP/UX    | SAM           |
| SCO      | SYSADMSH      |
| AIX      | SMIT          |
| Solaris  | ADMINTOOL     |
----------------------------
4. Kernel 을 Reconfigure 한다. 
5. System을 Reboot 한다. 
6. Oracle Instance를 startup시킨다.

[ 예제 ] Solaris 2.3/2.4 parameters and commands: 

1. SQLDBA 에서 : 
SQLDBA> shutdown 
SQLDBA> exit 

2. Superuser(root)로 login 하고 : 
# cd /etc

3. /etc/system file 에 다음을 추가 한다: 

set shmsys:shminfo_shmmax=8388608 
set shmsys:shminfo_shmmin=1 
set shmsys:shminfo_shmmni=100 
set shmsys:shminfo_shmseg=20 
set semsys:seminfo_semmns=200 
set semsys:seminfo_semmni=70 

4. Kernel을 reconfigure 한다: 
# touch /reconfigure 

5. Machine 을 reboot 한다: 
#init 6 

6. SQLDBA 에서 : 
SQLDBA> startup 
SQLDBA> exit 

 Oracle의 init<SID>.ora 파라미터 화일에는 SGA에 영향을 주는 Parameter들이 있다. OS의 Shared Momory와
 Semaphore Parameter에 연결된 이 Parameter의 setting은 System과 Oracle의 Performance에 중요한 영향을
 미친다. 
Posted by 1010
02.Oracle/DataBase2009. 6. 27. 11:00
반응형

======================================================================
ORA-00030 : ALTER SYSTEM KILL SESSION에 대하여
======================================================================

◈ 현상 사용자는 다음과 같은 상황에서 session 을 kill 하려는 시도를 하게 된다. 1. os 에는 process 가 존재하지 않지만, v$session 에는 active 로 존재하고 있을 경우 2. shadow process 는 살아 있는데, client machine 을 rebooting 한 경우 3. session 이 걸고 있던 lock 을 release 해야 할 경우 4. OS 나 Oracle 의 자원을 지나치게 많이 사용하여 성능을 저하시키는 process 그런데, alter system kill session ('sid, serial#'); 후에 다음과 같은 에러가 발생할 경우가 있다. ora-00030, 00000, "user session ID does not exist" // *Cause: The user session id no longer exists, probably because the // session was logged out. // *Action: Use a valid session ID. ◈ 원인 kill session을 할 수 없는 이유는 PMON이 이미 이 session을 delete하고 있는 중이기 때문이다. 즉, PMON 이 dead session 을 clean-up 하고 있는 중에는 serial number의 값이 증가한다. 문제는 PMON이 process를 kill하는 시간인데, transaction의 크기에 따라, PMON의 rollback 시간이 결정된다. 먼저 PMON은 dead process를 찾아내어, 이 process가 사용한 resource 를 release하는 시도를 한다. PMON은 계속 이 작업을 시도하다가 마침내, free buffer의 부족으로 더 이상 resource를 free-up 하지 못하게 된다. 이 때, 이 process를 delete하고 있다는 message를 trace file에 출력하는데, 이것은 process를 delete하는 데 필요한 resource(data cache 내의 free buffer)의 부족으로 위의 작업이 지연되고 있다는 의미이다. ◈ 조치 PMON이 process 를 clean-up 할 때 걸리는 시간은, 5분에서 24 시간까지 소요될 수 있다. 문제는 이 process가 hold 하고 있는 lock으로 인해 특정 작업이 수행되지 못하는 데 있다. MTS 를 사용할 때는 configuration MTS setting, sqlnet.expire_time 사용)에 따라 다르지만, clean-up 작업을 하는데 72 시간 이 소요된 경우도 있다. 아직까지는 PMON이 작업을 마칠 때까지 기다리는 방법 또는 db를 restartup하는 방법 밖에는 없다. --- PMON 의 작업 PMON은 network failure 나 기타의 원인으로 생긴 old process connection을 clean-up하는 역할을 한다. 그런데, PMON 은 clean-up 해야 하는 connection 중에 정해진 개수 만큼의 transaction 을 rollback 할 수 있는데, 이 값은 initSID.ora 의 cleanup_rollback_entries(default = 20) 에 의해 결정된다. 예를 들어, 1000 개의 uncommitted update가 있다면, 일정한 시간마다 cleanup_rollback_entries의 개수 만큼의 record만 rollback 할 수 있으므로 이 작업 동안에 lock 은 그대로 유지된다. PMON 은 위의 작업 이외에 DB maintenance 역할이 있으므로, 위의 rollback 이 비교적 빠르게 처리 되지 못할 수도 있다. 이러한 rollback을 빠르게 처리하기 위하여 cleanup_rollback_entries 를 늘릴 수도 있다. 그러나, 그 만큼 일정시간 동안 PMON의 작업이 많아지게 되므로, 다른 사용자들의 작업 요청이 느려지게 되는 trade-off가 있으므로, 신중히 고려한 후에 수정하는 것이 바람직하다. alter system kill session 에 의해서도 위와 같이 rollback 이 이루어지는데, 이 session 이 완전히 clean-up 되기 전까지 v$session, v$process에 남아 있게된다. --- ALTER SYSTEM KILL SESSION 을 하기 전에 ... kill session 을 원할 경우는 다음의 순서대로 작업하는 것이 좋다. 1. kill the user process first 2. wait for 3 - 4 minutes 3. query v$session 4. if any information find in v$session, query v$lock like select count(*) from v$lock where SID ='sid'; 위의 count(*) 가 0 이 아니라면, 아직 PMON 이 rollback을 끝내지 못한 경우이므로 다시 얼마후에 v$lock 을 조회하여 lock 의 개수가 감소하였는지 반복적으로 확인한다. 만약, 이 값이 전혀 변하지 않았다면, ALTER SYSTEM KILL SESSION 을 수행하고 v$session, v$lock을 query 하여 변화가 있는지 확인하여 변화가 있다면, 좀 더 기다린다. 그래도, v$lock 의 count(*) 가 0 이 되지 않을 경우, 마지막으로 수행할 수 있는 유일한 방법은 instance 를 restartup 하는 것이다.

======================================================================
ORA-00054 : TABLE에 TRANSACTION이 종료되지 않은 경우
======================================================================

TABLE 을 DROP 하려고 할때 그 TABLE에 TRANSACTION이 종료되지 않아 ORA-54 ERROR가 나오는 경우가 있다. DB를 RESTART하면 되지만 더 효율적인 해결 방법은 다음과 같이 할수 있다. * 참고 : Serial Number 가 Negative 인 경우 그 값에 65536 을 더해야 함. rem sqlplus system/manager rem rem prompt Enter table name accept tname CHAR col type format a6 col object_name format a20 select a.sid,a.serial#,b.type,c.object_name from v$session a,v$lock b,dba_objects c where a.sid=b.sid and b.id1=c.object_id and b.type='TM' and c.object_name=upper('&amp;tname'); Prompt Enter session ID(SID) ? accept sid Prompt Enter serial number(serial#) ? prompt -- if serial number < 0, prompt -- then serial number #=Serial number + 65536 accept serial alter system kill session '&amp;sid,&amp;serial'


==================================================================================
ORA-00060 : DEADLOCK과 INITRANS (같은 TABLE내의 다른 범위의 DATA처리시 ORA-60)
==================================================================================

 deadlock에  관한  일반적인  사항은  <Bul:11742>에  정리되어  있다.  같은  data를  동시에   변경하는
 transaction의 경우  deadlock이 발생하는  것은 application  logic을 수정하여  해결해야 하는  경우가
 대부분이다.

 그런데 같은 table에 대해서 동시에 수행되는  transaction이 각자 서로 다른 data를 처리하는  경우에도
 ora-60(deadlock detected while waiting for resource)이 발생할 수 있다.

 예를 들어 한 transaction은 A table의 1월 data를 처리하고, 동시에 다른 transaction은 같은 A  table의
 2월 data를 처리하는 것과 같은 경우이다.

 이러한 경우에도 initrans가  작게 설정되어 있으면,  ora-60이 발생할 수  있는데, 이 자료에서는  이와
 같이 다른 data를 처리하는 transaction들 사이에서의 ora-60이 발생하는 경우와 조치사항을 확인한다.

  1. transaction entry에 대해서
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 table이나 index에 포함된 모든 block에 update/delete/insert와 같은 dml을 수행하기 위해서는 일단  그
 block에 transaction정보를 저장시킬 transaction entry를 확보한 후에 원하는 작업이 수행가능하다.

 이  transaction entry의  크기는 os  dependent하기는 하나  대부분 23  bytes이며, table이나   index의
 initrans  option에 의해,  미리 확보되는  block당 transaction  entry의 갯수가  결정된다. default는
 table이 1, index가 2이다.

 이  transaction  entry가  특정 transaction에  할당되면  그  transaction이 commit이나   rollback되기
 전까지는 다른 transaction에서  사용할 수 없다.  같은 block에 다른  transaction이 dml을  수행하려면,
 남은 공간중에서 23 bytes의 transaction entry를 새로 할당하거나, 공간이 없으면 앞에서 먼저 사용중인
 transaction이 commit/rollback되기를 기다려야 한다.

  2. ORA-60이 발생하는 경우
  ~~~~~~~~~~~~~~~~~~~~~~~~~
 deadlock을 유발시키는 transaction이 서로간에 완전히 다른 data(같은 table)를 처리하더라도 그  data가
 같은 block에  함께 들어가  있는 경우라면  ORA-60이 발생할  수 있다.  즉, transaction  entry를  잡는
 과정에서  block내에 남은  space가 부족한   경우, 서로  상대방의 transaction이  종료되기를  기다리는
 deadlock이 발생가능하다는 것이다. 아래에 실제 예를 들어 자세한 발생 시나리오를 정리하였다.

① ORDER table은  날짜별로 data가 추가,    변경, 삭제되는 100만건  이상의 data를 가진  table이다. 이
 table에   대해서   월별로   통계작업을  수행하는데,   6개월씩   처리하기   위해  6개  transaction을
 동시에 수행하였다. 즉, T1은 1월 data, T2는 2월 data, T6는 6월 data를 처리하는 식이다.

② ORDER table은 initrans값이 1로 지정되어 있고 현재 1000개의 block이 이 table에 할당되어 있다.

③  100번지  block에  2월,  3월,  5월  data가  함께  저장되어  있다.  200번지  block에는  2월,   3월
 data가 저장되어 있다.

④ T2  transaction이  100번지  block에  이미  확보되어  있는  1개의  transaction   entry를  사용하여
 transaction정보를 저장하였다. 그리고, 2월달 data에 대한 작업을 수행하였다.

⑤ T3 transaction이 200번지 block에 initrans  1에 의해 확보되어 있는 23 bytes의  transaction entry를
 이용하여 transaction정보를 저장한 후 3월달 data에 대한 처리를 수행하였다.

⑥ T2 transaction이 2월달 data중 나머지 부분을  처리하기 위해 200번지를 access하여 23 bytes의 T2  를
 위한   transaction     entry를   확보하려고      하였으나,   block에     남은   공간이      없어서,
 T3 transaction이  commit할때까지   기다린다.   5번  단계에서,    initrans에  의해  미리    확보되어
 있는 공간을  사용하는 T3 transaction이 종료되면, 그 부분을 T2가 사용할 수 있게 되는 것이다.

⑦ T3  transaction도  100번지에  있는 3월  data를  처리하기  위해  100번지내에 transaction   entry를
 추가적으로   확보하려 하였으나,    공간이 없어서,    마찬가지로  미리   100번지 block을    사용하고
 있는 T2 transaction이 종료되기를 기다리게 된다.

⑧ 6과 7상황에  의해 T2와 T3  transaction은 서로 상대방이  종료되기를 기다리는, deadlock이  발생하게
 되므로   deadlock상황을  유발시킨     T3   transaction이   ORA-60을    발생시키면서   종료   되고,
 T3  transaction은   rollback된다.  200번지에   확보한    transaction   entry부분도  반환하여   다른
 transaction이 사용가능한 상태가 된다.

⑨ 8번에서 release된 200번지  block내의 transaction entry 23  bytes를 6번 단계에서 기다리고  있던 T2
  transaction이 확보하고 작업을 진행한다.

  3. deadlock을 피하기 위한 방법
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

결론적으로,  같은  table에 대해서  다른  data를 처리하는  transaction이라  하더라도 동시에  수행하는
transaction이 많은 경우라면 initrans 값이 작은 경우 ora-60이 발생할 수 있게 된다.

하나의 table에 대해서  performance등의 이유로 동시에  다른 data를 처리하는  transaction을 수행하고자
한다면,  table의  initrans  값을  크게하여,  하나의  block에  여러  개의  transaction이  dml  처리를
수행하더라도 space가 부족하여 기다리는 상황은 없도록 하여야 한다.

initrans를 n으로 지정한다면 23*n bytes가 항상 transaction entry로 미리 확보되어 있는 것이다.  이렇게
transaction entry로 초기에 확보된  공간은 data를 저장할 수  없는 공간이 되므로, 너무  크게 하는 것은
space 낭비가 초래된다. 하나의 block에 대해서  동시에 여러 transaction이 처리되지 않는 경우라면  미리
확보된  transaction entry는  사용도 되지  않고 낭비되어,  full table  scan 등의  작업에 성능  악화만
초래하게 된다.

initrans값은 하나의 table에 대해서 동시에  처리하는 transaction의 갯수 이하로 지정하도록  한다. 해당
table에  대한  동시  transaction의  갯수만큼 initrans를  지정하면  앞에서  설명한  상황의 deadlock은
발생하지 않는 것이 보장되나 space를 고려할 때 그 보다는 약간 작게 하는 것이 일반적인다.

initrans는 table이나 index에  대해서 create나 alter문장시  지정, 변경이 가능하나,  alter의 경우 이미
확보된 block에는 영향을 미치지 못하므로 export/import를 이용하여 새로 지정하는 것이 필요하다.

다음에 scott.dept table에 대해서 예를 들었다. column정의 storage등은 임의의 값을 예로 사용한 것이며,
initrans도 예로 3을 지정하였다.

  os> exp scott/tiger file=test.dmp tables=dept

  os> sqlplus scott/tiger
  SQL> drop table dept;
  SQL> create table dept (deptno number(2), dname varchar2(10))
	   initrans 3
	   storage(initial 10m next 2m pctincrease 0);

  os> imp scott/tiger file=test.dmp tables=dept ignore=y




======================================================================
ORA-00210 : TABLE에 TRANSACTION이 종료되지 않은 경우
======================================================================

Sequent Symmetry  or NUMA-Q  platform의 Oracle  7.3.2, 7.3.3,  7.3.4 OPS  Product 설치  및 DB 생성후
Master node startup parallel 후 다른 node를 startup parallel 시 다음과 같은 현상이 발생할 경우.

◈ 현상
  SVRMGR> startup parallel

     ORACLE instance started.
     Total System Global Area     546275472 bytes
     Fixed Size                       39108 bytes
     Variable Size                210167756 bytes
     Database Buffers             327680000 bytes
     Redo Buffers                   8388608 bytes

  ORA-00210: cannot open control file '/dev/vx/rdsk/oracle/v_ctl1'
  ORA-07368: sfofi: open error, unable to open database file.
  SEQUENT DYNIX/ptx Error: 16: Device busy

  발생하면서 startup fail 발생

◈ 원인
  Sequent Symmetry or NUMA-Q platform이 very large file (O/S에서 2GB 이상의 file system 지원)을
  지원하기 위해  VLFS patch를  적용했거나 VLFS를   이미 지원하는  O/S Version일  경우 오라클  master
  node가 정상적으로  startup  되고  나서  다른  node가  startup  parallel이  될  때  먼저 startup 된
  master node가 shared disk 의 모든 오라클 관련 file을 none-shared mode로 open 하기 때문에 위의 현상
  이 발생됨

◈ 조치
  1) PTX/Cluster V1.3.2일 경우
     * Oracle  V7.3.x : O/S상에서 VLFS patch적용하지 않았을 경우는 관계 없으나, 이미 적용 되었다면
       추가적으로 O/S patch FP#23373 적용하여야 함
  2) PTX/Cluster running DYNIX/PTX 4.4.x 일 경우
     * Oracle V7.3.3 : 현재 fix된 patch는 없으며 다음과 같은 workaround 방법으로 해결이 가능함.

  (Workaround)
     $ORACLE_HOME/rdbms/lib/ins_rdbms.mk file에 아래의 추가된 부분만 삽입하여 오라클 kernel relink 실시
     (예:make -f ins_rdbms ioracle)
     oracle: $(ORALIBD) $(CORELIBD) $(NETLIBD) $(KSMS) $(CONFIG)
             $(PSOLIBLIST) opimai.o @$(ECHO) $(LINK) -o $@ $(LDFLAGS)
             $(LDFLAGS_ORA) opimai.o $(CONFIG) \r
             -llkseqora  ---> 추가된 부분
             $(LLIBSERVER) $(LLIBORA) $(LLIBKNLOPT) $(LLIBSLAX)
             $(LLIBPLSQL) \r
             $(LLIBSICX) $(LLIBSOWSUTL) \r
             $(LLIBSICX) $(LLIBSOWSUTL) \r

                ...........
                ...........

  * Oracle V7.3.4 :
    Oracle V7.3.4 일 경우는 문제가 없으나 patchset을 적용할 경우 V7.3.4.2에서는 V7.3.3과 같은
    방법으로 oracle kernel을 relink하면 문제가 해결됨.

======================================================================
ORA-00312, ORA-00313 : ONLINE REDO LOG CRASH
======================================================================

[ ONLINE REDO LOG가 손상되었을 때 DB에 OPERATION 이 없었던 경우는 다음과
같은 절차로 DB 을 OPEN 할 수 있다. - 확률 70% ]
-------------------------------------------------------------------------
1. CONTROLFILE 생성

-. 손상된 online log 는 포함시키지 않는다.
-. resetlogs option 으로 생성한다.
-. reuse option 은 생략하고 기존 controlfile 은 다른 이름으로 move 시킴.

<V7 에서 CONTROLFILE 생성하는 방법>
  sqldba> startup mount
  sqldba> alter database backup controlfile to trace;

  위와 같이 명령을 입력하면 ORACLE_HOME/rdbms/log 디렉토리에 트레이스 화일이다. 그 트레이스 화일에서
  create controlfile 명령부분을 남기고 삭제한다.

  (7.3 이상에서는 cd $ORACLE_HOME
                  cd ../../admin/SID dir/udump 에 있습니다)

콘트롤화일 생성 문장 예 - <cnt.sql> : GROUP 1 이 ONLINE LOG 라고 가정
--------------------------------------------------------------------------
 CREATE CONTROLFILE DATABASE 'RC722' RESETLOGS NOARCHIVELOG
 MAXLOGFILES 32        ********
 MAXLOGMEMBERS 2
 MAXDATAFILES 30
 MAXINSTANCES 8
 MAXLOGHISTORY 800
 LOGFILE
 GROUP 2 '/oracle/oracle/dbs/log2RC722.dbf' SIZE 5M,
 GROUP 3 '/oracle/oracle/dbs/log3RC722.dbf' SIZE 5M
 DATAFILE
 '/oracle/oracle/dbs/systRC722.dbf',
 '/oracle/oracle/dbs/rbsRC722.dbf',
 '/oracle/oracle/dbs/toolRC722.dbf',
 '/oracle/oracle/dbs/usrRC722.dbf',
 '/oracle/oracle/dbs/tempRC722.dbf',
 '/oracle/oracle/rcdata.dbf'
 ;

2.절차

$ sqldba lmode=y
 SQLDBA> connect internal
 SQLDBA> shutdown abort
 SQLDBA> startup nomount
 statement processed
 SQLDBA> @cnt
 SQLDBA> recover database using backup controlfile until cancel;
 ....
 ...
 CANCEL (Return)
 Recovery canceled
 SQLDBA> alter database open resetlogs;

 : 만일 정상적으로 open 되면 log file 추가
 SQLDBA> alter database add logfile '?/dbs/log1ORA722.dbf' size 1M;

======================================================================
ORA-00600 : BLOCK 손상 해결 방법
(ORA-600[3339], ORA-600[3398], ORA-600[4519], ORA-1578)
======================================================================

◈ 개요 
 블럭의 손상 원인은 여러가지가 있는데, 메모리내의 블럭이 손상된 경우와 디스크상의 물리적인 블럭이
 손상되는 경우가 있다.

 (1)  오라클  오류  블럭  손상과  관계된 오라클  오류는  internal error인  ORA-600중  첫번째 인수가
 3339,3398, 4519인  경우와 ORA-1578이  있으며, 이중  Ora-600[3398]은 메모리  블럭만 손상된 경우이고,
 ORA-1578은 물리적 블럭이 손상된 경우 발생한다. ORA-600[3339]와 ORA-600[4519]는 메모리와 디스크 손상
 모두가 연관될 수 있다. 각각의 오류에 대한 자세한 설명은 아래의 3번에서 기술하였다.

 (2) DBA (database address)  ORACLE 데이타  블럭은 블럭의 정보를 담은 Fixed Header를  갖고   있으며
 이 정보를 이용하여 각각의 블럭과  데이타베이스 전체의 INTEGRITY를 유지한다. DBA는  Fixed   Header의
 한  부분으로 32bit 길이의 정수이며  데이타베이스의 화일 번호와 파일에서 블록위치를  나타낸다.  블럭
 손상이  발생하면  오라클은 오류  메시지에  이 DBA를  나타내거나  파일 번호와  블럭  위치를
 십진수로 나타내기도 한다.

◈ 블럭 손상의 원인 
 오라클은 화일에 블럭을 읽고  쓸 때 lseek(), read(),  readv(), write(), writev()와 같은  OS의 system
 function  call을 이용한다.  블럭이 이러한  시스템콜을 이용하여  읽혀지거나 씌여진  후, 혹은  직전에
 오라클은 DBA에  대한 검사를  하여 블럭이  손상되었는지 확인하게  된다. 그러나  대개 블럭의 데이타가
 손상될 당시에는 그  사실이 드러나지 않다가  손상된 부분의 데이타가  사용될 때 비로소  손상된 사실이
 알려지게 되므로 대부분 블럭 손상은 OS나 HW에 의해 손상된 블럭을 이후 오라클이 사용하고자 검사하는
 과정에 발견하는 것이 대부분이다.

 블럭 손상이 야기될 수 있는 주된 상황은 다음과 같이 요약될 수 있다.

 (1) ORACLE 블럭내의 첫번째 OS 블럭이 디스크상의  문제로 해서 이상이 있는 경우, OS 또는  디스크 복구
  프로그램이 해당 블럭을 복구하려는 과정에서 블럭의 값이 모두 비정상적적으로 0이 되어 버릴 수 있다.

 (2) 매우 드문  경우이긴 하지만, 메모리상에서  이미 손상된 블럭을  디스크상에 그대로 기록하는  경우
  물리적 블럭의 DBA가 틀리게 된다

 (3)  블럭이   데이타  화일상에   기록될  위치를   잘못  찾아   손상이  발생하기도   하는데,  이러한
  경우를 'write blocks   out  of  sequence'  라고   불리운다. 이것은   ORACLE이  lseek()을  호출했을
  때 OS가 블럭을 잘못된 곳에 기록해서   생기는  경우가 많다.  이러한   예는 4.2G를  넘는 큰   화일을
  다룰 수  있는   기능을 제공하는  HW/OS의   경우  발생한다.   4.2G를   넘는  화일의  경우,    32bit
  unsigned number로 다룰   수 있는 범위를  벗어나기   때문에 OS는offset   값을  ORACLE이  사용할  수
  있도록 적절히 변환시켜야  한다. ORACLE은  OS의 지원  여부와  관계없이 2G  이상의  화일을  지원하지
  않으며 위와  같은  큰   파일을 다룰    수 있는   환경에서는 lseek()   시스템콜이 정확한   위치로의
  변환을 시켜주지 못함에 따라 보다 작은 크기의 화일에서도 문제가 발생하는 경우도 있다.

 (4) 네번째 원인은  I/O기능이 전혀 작동하지  않는 경우이다. ORACLE은  lseek(), read() 시스템  콜이
  리턴하는 에러 코드를 검사하며 read()가   읽어들인 바이트수가 BLOCK SIZE의 정수배인지를   검사한다.
  이 검사를   통과하면  ORACLE은  성공적으로  READ가   수행되었다고 가정한다.   만약  DBA가 정확하지
  않다고 체크되면 DATABASE에 대한 읽기 요구는 실패하기 때문에 실제의 블럭 읽기는 일어나지 않는다.

 (5)  다른  원인은  동일한  디바이스에서  다른 블럭을  읽어온  경우이다.  이것은  작업이  메우  바쁜
  디스크에서  발생하곤  한다.   어떤 경우에는   수백개  이상  떨어진  곳의   블럭을 읽어오는  경우도
  있다. 이러한 경우와 위의   (4)번의 경우에는 다시  한번  동작을 반복함으로써  문제는 해결  수 될 수
  있으며 이것은 일반적으로 ORACLE의 문제가 아니라 OS나 HW의 문제인 경우가 많다.

◈ 블럭 손상과 관계된 오류의 종류와 가능한 조치방법
 (1) ORA-600[3339] 
  ORA-600[3339]에러는  ORACLE이  직접  버퍼로  데이타를 읽어들일  때  읽은  블럭의  DBA (Data  Block
  Address)가 잘못되었음(INVALID)을  의미한다. 실제로  읽어들인 블록의  DBA와 ORACLE이  읽고자 하였던
  블럭의 DBA가  다르면 위에서와  같은 에러가  발생하며 주로  OS나 HW의  문제가 그 원인이 되는 경우가
  많다.  만약  메모리에  문제가  있다고  생각된다면  다음과  같은  Event  Parameter를  initSID.ora에
  추가함으로써 블록 검사를 할 수 있다. 이것은 ORA-600[3398], ORA-600[4519]에서도 마찬가지이나 이러한
  event를 사용하기전에 먼저 한국오라클에 지원을 요청하는 것이 바람직하다.

  event = '10210 trace name context forever, level 10'
  event = '10211 trace name context forever, level 10'

 ORA-1578이 함께  발생하는 디스크  블럭 손상이  발생하였다면, 아래의  (4)의 ORA-1578해결 방법과 같이
 조치 하면 된다.

 (2) ORA-600[3398]
  DBWR가 디스크에 데이타를  쓰기 전에 캐쉬에서  손상된 블럭을 발견하면  OERI(3398) 메시지를 출력하고
  인스턴스를 정지시킬 것이다. 따라서 문제의 블록은 디스크에 저장되지 않으므로, 실제 디스크상의  블럭
  손상은 야기시키지 않는다. 이때 DBA를 포함한 많은 인수들이 OERI(3398) 내부 에러 처리기에 전달되므로
  이것을 확인하여 한국 오라클에 지원을 요청한다.

 (3) ORA-600[4519] 
  메모리내의 블럭을 update/delete가 아닌 consistent  read를 위해 읽고자 할때 블록이  손상됨을 발견한
  경우, ORA-600[4519]가  발생한다. 이  오류는 메모리  손상과, 디스크  손상 모두의 경우 발생가능하며,
  오류가 발생하는 즉시 한국오라클에 지원을 요청하는 것이 바람직하다.

 (4) ORA-1578 ORA-1578 에러는 ORA-600[3339] 에러와 함께 발생하곤 하며 디스크상에 물리적으로  블럭이
  손상되었음을 의미한다. 이러한 디스크 블럭 손상의 복구방법을 살펴보자.

(a)손상된  블럭을  포함하고  있는  세그먼트  확인  ORA-1578  에러가  발생하면  Corruption이 발생한
  화일번호와 블럭번호를  알려준다. 여기서는  이 때의  파일번호를 f,  블럭번호를 b라고 부르기로 한다.
  우선 해야할 일은 어떠한 오브젝트가 Corrupt되었는가를 알아내는 것으로써, 다음의 스크립트를 이용하면
  알 수 있다.

 SQL> select  segment_name, segment_type
        from  dba_extents
    where  file_id = f
         and  b between block_id and block_id + blocks - 1;

(b) 해당 세그먼트가 인덱스이면 Drop 시키고 다시 생성하면 된다.

(c) 해당  세그먼트가 테이블이면  Corrupt 된  블럭의 데이타는  손상된 것이다.이렇게 테이블이 손상된
  경우, 만약  해당 테이블이 들어있는 엑스포트 화일이   있다면 손상 된 테이블을  Drop 시키고  임포트
  받는것이 제일  간단한 방법이다. 하지만 만약  엑스 포트 받은 화일이  없거나 백업해 둔 화일도 없다면
  해당 테이블에 인덱스가 생성되어 있는 경우에 한해서 다음의 방법을 사용해서 복구를 하도록 한다.

 예를 들어 다음과 같은 에러 메시지가 떨어졌다고 하자.
 01578, 00000, 'ORACLE data block corrupted (file # 10, block # 4)

<1> 먼저 (a)번의 script를 이용하여 손상된 블럭을 포함하는 세그먼트를 확인한다.
   SQL> select  segment_name, segment_type  
        from  dba_extents  
       where  file_id = 10
            and  4 between block_id and block_id + blocks - 1;

         SEGMENT_NAME        SEGMENT_TYPE
         ------------        ------------
             EMP                 TABLE

<2> Rowid를 이용하여 손상된 블럭내의 데이타를 찾아낸다.
 위의 결과값이 EMP table이 empno, ename,  deptno 를 컬럼으로 가지며, empno 컬럼에  인덱스가 생성되어
 있다고  하자.클러스터화되지  않은   모든  테이블은  유니크한Rowid를   가진다.  Rowid는  총   18자로
 블럭어드레스(8자), 점(1자),  로우 어드레스(4자),  점(1자), 화일  어드레스(4자)로 구성되어  있다. 이
 rowid를 이용하여 다음과 같이 손상된 블록에 있는 employee 에 대한 empno를 구할 수 있다. 이때 empno가
 char type 이라면 [where empno > 0] 대신 [where empno > ‘ ‘]를 사용하여 empno에 대한 인덱
 스를 사용하도록 유도한다. 

    SQL> select  empno  
           from  emp
          where  empno > 0 
            and  rowidtochar(rowid) like '00000004.%.000A';  

        EMPNO           ROWID  
    ------------  ------------------------------
        500      00000004.0000.000A
        501      00000004.0001.000A

<3> EMP 테이블과 같은 구조를 갖는 새로운 테이블을 만든다.
    SQL> create table temp 
             as select * from emp 
          where 1 = 2;  

<4> 손상된 부분을 피해서 새로운 테이블에 손상된 테이블의 데이타를 추가한다.
    SQL> insert into temp select * from emp where empno < 500; 
    SQL> insert into temp select * from emp where empno > 501;

<5> 손상된 테이블인 EMP테이블을 Drop시키고 Temp테이블의 이름을 EMP로 변경한다.
    그리고 백업된 자료나 문서자료를 통하여 손상된 부분에 대한 정보를 추가한다.
    SQL> drop table emp;  
    SQL> rename temp to emp;

<6> 손상된 블럭에 대부분의 로우가  존재하고 있다면 다음의 방법을 이용한다.
   SQL> create table empnos as  
         select empno from emp
         where empno > 0  
          and rowidtochar(rowid) not like '00000004.%.000A';

   이 스크립트를 이용하면 손상된  블럭에 포함되지 않은 empno 들을 알 수 있다.
   다음의 스크립트를 계속 실행시켜 복구를 한다.

    SQL> create  table temp  as select * from emp  where 1 = 2;
    SQL> insert  into temp
         select  emp.empno, emp.ename, emp.deptno
       from  emp, empnos
     where  emp.empno > 0
       and  emp.empno = empnos.empno;

<7>  만약  데이타  딕셔너리의  테이블이나 인덱스에서  손상된  블럭이  발생했다면  지원 을  요청해야
 한다

======================================================================
ORA-00604: 익스텐트가 가득 찬 경우
======================================================================

 이 에러는 내부적으로 SQL명령이 실행될 때 발생한다. 예를 들어 현재 할당된 익스텐트가 가득 차서  다음
 익스텐트를 할당 받으려고 할 때 오라클이 다음 익스텐트의 크기와 위치를 결정하기 위하여  SELECT명령을
 내리게 되는 것과 같은 경우이다.

 * 이 문제가 발생하면 우선 alert.log 화일을 검사하여 ORA-600 과 같은 에러가 발 생했는가를  확인한다.
 ORA-600 에러가 발생했다면 오라클측에 지원을 요청 하도록 하고 그렇지 않다면 다른 원인을 검사해 봐야
 한다.

 * 가장 먼저 고려할 사항은 init.ora 화일에 지정된 open_cursors의 크기를 알아보는  것이다.
 이 값이 설정이 안되어 있으면 Default가  50이므로 open_cursors=255 와 같이 설정하도록 한다.  이 값은
 단지 커서의 최대 값을 지정하는 것이므로 커서를  적게 쓰 는 프로그램에 아무런 영향을 끼치지  않는다.
 open_cursors를 변경하고 DB를 tdown 하고 Startup 시키면 된다.

 * 만약 이 방법으로  해결이 안되면 다음의 방법을  따른다. 정확한 에러의 원인을  찾기 위해서 init.ora
 화일에 다음과 같은 라인을 추가한다. events = '604 trace name errorstack' 이렇게 init.ora를 변경하고
 DB를 Shutdown 하고 Startup  하면 ORA-604 에러가 발생하는 경우에 자세한 정보를  Trace 화일에  기록해
 주므로 이 화일을 검사하여 에러의 원인을 찾을 수 있다.

 * 에러의 다른 원인으로는 init.ora 화일의 파라미터 가운데 DC_FREE_EXTENTS나 ROW_CACHE_ENQUEUES의  값
 이 너무 작게 설정된 경우를 생각해 볼 수 있다. 이와같은 경우는 이들 값을 크게 설정해 주도록 한다.

 * 테이블 스페이스가 가득 차거나 Extent  갯수의 최대 허용값을 초과해서 에러가 발생하는  경우 ORA-604
 에러가 함께 발생할 수가 있는데 이와같은 경우에는 이들 문제를 먼저 해결하면 ORA-604 에러는 함께 해결
 된다. 

======================================================================
ORA-01046, ORA-01050, ORA-01051 : CONTEXT SIZE & CURSORS
======================================================================

1. Context size 에 관련한 error message
.ora-1046 :can't acquire space to extend context area.
.ora-1050 :can't acquire space to open context area.
.ora-1051 :maximum context area extents exceeded.

2. Context size란 무엇인가?

(1) 쉽게 말하면 Cursor의 initial size이다 .
즉, Cursor 에 allocate 되는 user memory 이다.
(2) 이는 init.ora 의 CONTEXT_SIZE 에 의해 결정된다.
(3) Cursor 에 할당되는 additional space 는 CONTEXT_INCR 에 의하며 50 extents를 갖는다.
(4) Recommended context size 와 increment 는 4096 bytes(4K) 이다.
(5) SQL statement가 수행시마다 cursor 가 open 되며,같은 cursor가 reuse 되도록 design 되어 SQL*PLUS
    session은 2-3 개 이상 open 되어지지 않는다.
    그러나 SQL*FORMS 는 여러 다른 task 를 수행하므로 많은 cursor를 open한다. (100 or more)

(6)Cursor 가 hold 하는 item
* the SQL statement
* the parsed SQL statement
* one row of the result

3 ORA-1051 은 무엇이 문제인가?
(1) cursor 의 size 를 줄인다
(2) CONTEXT_SIZE,CONTEXT_INCR 를 늘린다.

4 OPEN_CURSORS 수를 줄이는 전략 .
(1) Commit을 자주한다.
(2) Synonym이나 view 를 사용하지 않음으로써 implicit cursor 수를 줄인다.
(3) SQL*FORMS 에서 select 문대신 #COPY 로 바꿔 사용한다.
(4) SQL*FORMS 에서 large forms를 여러개의 작은 forms 로 나눈다
(5) ASAP, EXEC SQL CLOSE C1; 을 수행한다.
(6) HOLD_CURSOR=NO &amp; RELEASE_CURSOR=YES 를 사용한다.

======================================================================
LK FILE에 대하여 (ORA-1102에 대한 원인 설명)
======================================================================

> Unix 용 Oracle7.3.3  이전의 version에서는 parallel  server mode(OPS)로 운용하지  않더라도 서로 다른
 ORACLE_SID를 이용하는  두개의 instance가  하나의 database를  동시에 mount하는  것이 경우에 따라서는
 가능할  수도  있었다 (<Bug:272030>).  이  경우, 서로  독립적인  두개의 instance가  동일한  database
 file들을 동기화  (synchronisation)없이 access할  수 있기  때문에 database  corruption을 유발시킬 수
 있었다.

 Unix system에서의 이러한 문제를 회피하기 위하여  7.3.3부터 'mount lock' file이 이용된다. 이  file은
 그 size가 0 byte, 생성되는 위치는 $ORACLE_HOME/dbs 이며 그 이름은 lk<DB_NAME> 이다.

 Oracle이 database를 mount할 때 lk<DB_NAME> file과 관련하여 다음과 같은 절차를 수행한다.

 1.  file name의  'DB_NAME' 부분은  db_name parameter를  이용한다. 예를  들어, db_name=V803  이라면
 사용되는 lock file의 위치와 이름은  '$ORACLE_HOME/dbs/lkV803'이 된다. 2. 만약 해당  file이 존재하지
 않는다면 생성한다. 존재한다면 file을 open한다. 3. 이 file에 exclusive Unix file lock을 설정한다.

 위의 과정 상에서 문제가  발생된다면 해당 instance는 db를  mount할 수 없으며 ORA-1102('cannot  mount
 database in exclusive mode')가 return된다.

 Releasae  7.3.3  이전에서는  동일한  $ORACLE_HOME, 동일한  db_name을  이용하는  두  개의 database를
 $ORACLE_SID만 다르다면 동시에 open하여 사용할  수 있었다. 그러나 lock file이  사용되는 7.3.3부터는,
 lock  file의 이름에  db_name이 이용되기  때문에 어느  한쪽의 db_name을  변경해야만 동시에  open하여
 사용할  수가  있다.(db_name의  변경은  controlfile을  재생성함으로써  가능하다.)  이렇게 database의
 db_name이 변경되면 각각의 lk<DB_NAME> file을 생성하여
이용하게 된다.


참고 사항
--------

1. database를 구동하고 있는 instance가 있을 때에는 lk<DB_NAME> file은
   삭제하지 않도록 한다.

2. database가 shutdown되더라도 lk<DB_NAME> file은 삭제되지 않고 존재한다.
   따라서 이 file의 유무를 가지고 database의 구동 유무를 판단할 수 없다.

3. lk<DB_NAME>의 DB_NAME은 SID와는 다를 수 있다. SID가 아닌 DB_NAME을 이용함에 주의.

4. lock file과 관련하여 다음의 error들이 발생될 수 있다.
   ORA-9992 scumnt: failed to open <FILENAME>
   ORA-9993 scumnt: failed to lock <FILENAME>
   ORA-1102 cannot mount database in exclusive mode

======================================================================
ORA-1118 조치 방법 : MAXDATAFILES와 DB_FILES PARAMETER
======================================================================

 테이블 스페이스를  만들거나 데이타  화일을 추가하다  보면 ORA-01118:  cannot add  any more database
 files: limit of XXX exceeded와 같은 에러가 발생하는 경우가 있다. 오라클의 데이타 화일의 최대 갯수는
 MAXDATAFILES와 DB_FILES 에  의해서 제한을  받는데 여기서는  이 에러를  해결하는 방법을  알아보기로
 한다.

  * 데이타베이스를  처음 만들  때 사용되는  CREATE DATABASE  명령에서 MAXDATAFILES  라는 파라미터를
 찾아볼 수 있다.  여기서 지정된 값(명시를  안하면 디폴트로 설정)은  콘트롤 화일에 기록된다.  이 값은
 데이타 베이스에  대해서 설정된  최대 데이타화일  갯수이다. 이  값을 변경하려  면 콘트롤 화일을 다시
 만들어야 한다. 

  * 한편, init.ora(UNIX에서는 init<SID>.ora, VMS에서는 <node>_<ora_sid>_init.ora)  에는 DB_FILES라는
 파라미터가 있는데 이 값은 해당 인스턴스에 대해서 지정된 최대 데이타화일 갯수이다. DB_FILES는 단순히
 에디터 상에서 init.ora 화일을 수정한 다음 에DB를 Restartup 하면 새로운 값이 적용된다.

 1. 왜 MAXDATAFILES 와 같은 한계값을 설정하는가?    
 * O/S는 오라클 화일의 갯수를 지정하기  위하여 특정한 갯수의 bit를 사용하며 이 값은 Platform에 따라
 다르다. MAXDATAFILES는 이 값의 영향하에 있게 된다. 일반적인 최대 값은 다음과 같다. 

 V6 V7
 UNIX 62 1022
 VMS  254 1022
 DOS  254 NA 
[참조]일부 유닉스 Platform상의 V7.0.16 이전 버전의 경우 1022보다 작은 경우도 있다.

2. 왜 MAXDATAFILES 값을 가능한 최대로 설정해 두지 않는가? 
  * MAXDATAFILES 를 크게 지정하면 그만큼 콘트롤 화일의 크기도 늘어나기 때문이다.

3. 왜 DB_FILES를 MAXDATAFILES 의 크기만큼 크게 설정해 두지 않는가? 
 * DB_FILES를 늘리면 각 User Process 에 할당되는 PGA(Program Global Area)의 크기가 커지기 때문이다. 

4. 사용하는 시스템의 MAXDATAFILES를 알 수 있는 방법은? 
  * 시스템에 따라서 다르므로 Installation Guide 를 참조해야만 한다. 

5. 콘트롤 화일의 위치를 아는 방법은? 
  * SQLDBA> show parameter control_files;
      또는 
   SQLDBA> select * from v$controlfile; (7.0.16 이상)
  위의 Query 를 이용하거나 $ORACLE_HOME/dbs/config.ora 화일을 보면 알 수 있다.

 [ORA-1118 해결방법] 
 * ORA-1118 에러는 데이타 화일의 갯수가 MAXDATAFILES 값에 도달한 경우 발생한다. DB_FILES 값에 도달한
 경우라면 ORA-59 에러가  발생한다. ORA-59 에러는  init.ora 의 DB_FILES  를 늘려주고 DB  를 Restartup
 하면 해결 되지만 ORA-1118 에러는 이와같이  간단하게 해결되지는 않는다. 다음과 같은 방법이  있다. 
 
 1. 여러개의 데이타화일로 구성된 테이블 스페이스가  있으면 이를 Export 받고 테이블 스페이스를 Drop한
 다음 하나의 큰 데이타화일을 갖도록 테이블 스페이스를 만들고 Import를 한다.  
 
 2. V6.0.33 이전 버젼을 사용중이라면 MAXDATAFILES를 늘리기 위해서는 DB를 새로 만들어야 하며  그 이후 
 버전을 사용중이라면 콘트롤 화일을 새로 만들어서 MAXDATAFILES를 늘릴 수 있다.

 <V7에서 콘트롤화일을 만드는 방법>
 * DB가 mount 또는 open 된 상태에서
  SQLDBA>alter database backup controlfile to trace;  
 와 같은 명령을 내리면 <user_dump_dest>에 지정된  디렉토리에 트레이스 화일이 하나 생긴다. 이  화일을
 찾으려면  해당 디렉토리에서  가장 최근에  생긴 트레이스  화일을 찾으면  된다. 
 
 * 이 화일을 다른 이름으로   복사한 다음   에디터로 열어서   CREATE CONTROLFILE 명령부분 외의 불필요
 한 부분은  지우고 MAXDATAFILES를  늘려  준다. 이  화일의  이름을 newctl.sql로  하기로 한다. 
 
 * DB를 NORMAL 또는 IMMEDIATE로 Shutdown하고, 콘트롤 화일 생성시 DB 영향을 줄 수 있기 때문에 만약을
 위해서 DB 전체를 백업 받도록 한다. 
 
 * 현재 사용중인 콘트롤 화일을 다른 이름으로 옮기고 다음을 실행한다. 

 SQLDBA> startup nomount  
 SQLDBA> @newctl  
 SQLDBA> alter database open noresetlogs;

 * 이제 필요한 모든 작업은 끝났지만 여기서 다시 한번 Full Bakcup 을 받는 것이 좋다.

[ 참고 ]  다음은 콘트롤 화일을 생성하는 명령의 예이다.

 SQLDBA> CREATE CONTROLFILE
      DATABASE ORACLE
      LOGFILE '/users/oracle/dbs/log1ORACLE.dbf',       
                 '/users/oracle/dbs/log2ORACLE.dbf',       
                 '/users/oracle/dbs/log3ORACLE.dbf'   
         NORESETLOGS  
         DATAFILE '/users/oracle/dbs/systORACLE.dbf',       
                  '/users/oracle/dbs/rbsORACLE.dbf',       
                  '/users/oracle/dbs/tempORACLE.dbf',       
                  '/users/oracle/dbs/toolORACLE.dbf',       
                  '/users/oracle/dbs/usrORACLE.dbf'
         MAXDATAFILES 121;
</p>
<p align="right"><A target='_blank'  class='con_link' href="#top"><img src="../images/top.gif" width="33" height="37" border="0"></a></p>
</td>
</tr>

<tr>
<td width="578">
<p>
======================================================================<br />
<b><A target='_blank'  class='con_link' name="ORA-01157">ORA-01157</a>,
<A target='_blank'  class='con_link' name="ORA-01110">ORA-1110</a></b>
:OS 명령으로 DATAFILE을 삭제한 경우<br />
======================================================================<br />
</p>

<PRE><XMP>
 DATABASE RECOVERY에 앞서  ORACLE INSTANCE(즉, ORACLE  RDBMS)의 STARTUP단계를 우선  살펴보기로 하자.
 첫번째 단계로 INSTANCE를 START시키며,  여기서는  initORACLE_SID.ora 화일의 파라미터를 참조하여 SGA
 (SYSTEM GLOBAL AREA)를 할당하고 백그라운드 프로세스를 START 시킨다. 두번째 단계로 DATABASE의 MOUNT
 이며 파라미터 화일에 명시된 CONTROL  FILE을 오픈한다. CONTROL FILE로부터 DATABASE  NAME과 REDO LOG 
 FILE의 이름을 읽는다.
 세번째 단계로 CONTROL FILE 내의 정보를 이용하여 모든 데이타 파일을 오픈한다.

 SVRMGR> CONNECT INTERNAL;
 Connected.
 SVRMGR> STARTUP;
 ORACLE instance started.
 Database mounted.
 Database opened.
 Total System Global Area 1913196 bytes
 Fixed Size 27764 bytes
 Variable Size 1787128 bytes
 Database Buffers 65536 bytes
 Redo Buffers 32768 bytes

 RDBMS의 STARTUP시 문제의 데이타 화일이 CONTROL FILE 정보에서는 존재하지만, 실제로 O/S상에서는 존재하
 지 않으므로 DATABASE OPEN 단계에서 삭제된 데이터 화일을 OPEN할 수 없다. 따라서 다음과 같은 데이타 화
 일 오픈에 관련된 에러가 발생된다 :

 SVRMGR> STARTUP;
  ORACLE instance started
  Database mounted
  ORA-01157 : cannot identify data file 11 - file not found
  ORA-01110 : data file 11 : '/user1/oracle7/dbs/user2.dbf'
  Attempting to dismount database .... Database dismounted
  Attempting to shutdown instance .... ORACLE instance shut down

 DATABASE OPEN단계에서 CONTROL FILE에서는 ORA-1157에러에서 나타난 11번  데이타 화일이 존재하는 것으로 
 인식하지만, 실제로 O/S상의 데이터 화일 (ORA-1110에러에 명시된 '/user1/oracle7/dbs/user2.dbf' 파일)이
 삭제된 상태이다.

 이러한  경우에는  DATABASE  STARTUP 시  STARTUP  MOUNT  단계까지 실행한  후,문제의  데이  터 화일을
 OFFLINE시킨 다음 데이타베이스를 오픈한다. 단, 데이타베이스 오픈이 정상적으로 수행되면 문제가 발생한
 데이타 파일을 포함하고  있는 TABLESPACE를 DROP하지  않을 경우에는 DATABASE  STARTUP 시 항상  데이타
 파일의 오픈 단계에서 에러가 발생된다. 따라서, 문제의 데이타 화일의 OFFLINE과 TABLESPACE의 DROP 전에
 반드시 해당 TABLESPACE를 사용하고 있는 USER의 데이타 백업을 수행해야 한다.

 데이타 화일의 OFFLINE과 관련된 명령은 다음과 같다.
 먼저 SVRMGR을 Line Mode로 기동시킨다.

 $ svrmgrl
 SVRMGR> CONNECT INTERNAL;
 SVRMGR> STARTUP MOUNT;
  ORACLE
  instance started.
  Database
  mounted.

 SVRMGR> ALTER DATABASE DATAFILE '/user1/oracle7/dbs/user2.dbf' OFFLINE DROP;
  Statement processed.

 SVRMGR> ALTER DATABASE OPEN;
  Statement processed.

 SVRMGR> DROP TABLESPACE tablespace_name INCLUDING CONTENTS;
  Statement processed.

 (이와 같이 offline  drop된 datafile을 포함하는  tablespace는 drop하여야 한다.  이 tablespace에 다른
  datafile도 포함되어 있다면 export를 받아낸 후 tablespace를 drop하고 재 생성 후 import하도록 한다.)

 정상적으로 DATABASE가 Open된 후 CONTROL FILE로부터의 데이타베이스 정보를 갖는 DATA DICTIONARY TABLE
 인 V$DATAFILE(SYS USER에서 액세스 가능)의  내용과 데이타베이스 화일에 관한 정보를  가지고 있는 DATA 
 DICTIONARY VIEW인 DBA_DATA_FILES(SYSTEM USER)을 조회하면 아래와 같은 내용을 확인할 수 있다 :

(1) SQL> SELECT * FROM V$DATAFILE ;
    FILE#   STATUS                 NAME
    -----  --------   --------------------------------------
      9     ONLINE      /user1/oracle7/dbs/tools.dbf
      10    ONLINE      /user1/oracle7/dbs/user1.dbf
      11    RECOVER     /user1/oracle7/dbs/user2.dbf

(2) SQL> SELECT * FROM DBA_DATA_FILES ;
          FILE_NAME              FILE_ID     TABLESPACE_NAME STATUS
   ----------------------------  --------   --------------------------
   /user1/oracle7/dbs/tools.dbf    9         TOOLS AVAILABLE
   /user1/oracle7/dbs/user1.dbf    10        TEST AVAILABLE
   /user1/oracle7/dbs/user2.dbf    11        TEST AVAILABLE

====================================================================== ORA-01403 조치 방법 : EXPORT 실행시 ======================================================================

 EXPORT 실행시 ORA-1403이 발생되는 경우가 있는 데,  이 에러는 테이블 혹은 인덱스에 문제가 있는  경우
 발생할 수 있다. 여기서는 ROWID를 사용하여 테이블을 복구시키는 방법을 소개한다.

1. 기존 테이블과 같은 구조를 갖는 테이블을 만든다.

SQL> CREATE TABLE TEMP 
2>   AS SELECT  * 
3>        FROM EMP 
4>       WHERE 1=2; 

2. 기존 테이블에서 RECORD를 FETCH하여 새로운 테이블에 입력.
이 때, INDEX가 설정되어 있는 COLUMN을 WHERE 조건에 부여함. 

<CREATE.SQL>
 declare 
 row_id char(18); 
 cursor c1 is select rowid 
                from emp 
               where empno > 0; --empno에 index 
 begin 
   open c1; 
   loop 
     fetch c1 into row_id; 
     insert into temp select * from emp where rowid=row_id; 
     exit when c1%notfound; 
   end loop; 
 end; 
/ 

3. create.sql file실행 
sql> @create
</XMP</PRE>

<p align="right"><A target='_blank'  class='con_link' href="#top"><img src="../images/top.gif" width="33" height="37" border="0"></a></p>
</td>
</tr>


<tr>
<td width="578">
<p>
======================================================================<br />
 <b><A target='_blank'  class='con_link' name="ORA-01547">ORA-01547</a></b>
조치방법 :ORACLE 블럭을 할당받지 못할 경우<br />
======================================================================<br />
</p>

<PRE><XMP>
 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.

======================================================================
ORA-01562 조치방법 : MAXEXTENTS (DEFAULT 121)에 도달한 경우
======================================================================

 ROLLBACK SEGMENT는 TRANSACTION을 수행하면 필요한 만큼의 EXTENT를 발생하여 그 크기가 증가된 이후에는
 그 TRANSACTION이  COMMIT혹은 ROLLBACK되더라도  SIZE가 줄  어들지 않는다.  (OPTIMAL을 지정하지  않는
 경우)  이것은 DB를  SHUTDOWN후 다시  STARTUP 하여도  마찬가지이며, ROLLBACK  SEGMENT가 자신이  속한
 TABLESPACE로 부터  EXTENT를 할  당받다가 더  이상 할당받을  EXTENT가 없을  때, 혹은 이미 MAXEXTENTS
 (DEFAULT 121)에 도달한 경우에 ORA-1562가 발생한다. 

1. 현재 ROLLBACK SEGMENT가 포함되어 있는 RBS TABLESPACE의 크기 확인 

sqlplus system/manager 
SQL> SELECT  file_name, bytes 
       FROM  dba_data_files 
      WHERE  tablespace_name = 'RBS'; 

         FILE_NAME                 BYTES
------------------------------- ------------ 
/oracle/pms/dbs/rbsPMS01.dbf      20971520 
/oracle/pms/dbs/rbsPMS02.dbf      10485760 

 여기에서 나타난 결과값이 절대적으로 작은 경우 RBS TABLESPACE에 DATAFILE을 ADD 시켜줄 필요가 있다. 

2. 각 ROLLBACK SEGMENT의 SIZE및 발생한 EXTENT의 수 확인 

sqlplus system/manager 
SQL> SELECT  segment_name, initial_extent, next_extent, maxextents, rssize, extents, xacts 
       FROM  dba_rollback_segs a, v$rollstat b 
      WHERE  a.segment_id = b.usn; 

결과는 다음과 같은 형태로 나온다. 
 (1) INITIAL_EXTENT는 ROLLBACK SEGMENT가 필요한 경우 처음으로 자신의 SPACE를 잡는 크기이며, 이 크기만
  큼의 연속된 공간을 RBS TABLESPACE로 부터 잡는다. 
 (2) NEXT_EXTENT는 INITIAL_EXTENT를 잡은 후에 추가적으로 SPACE가 필요한 경우 이 크기만큼씩 SPACE를 잡
  게 된다. 
 (3) MAXEXTENTS는 각 ROLLBACK SEGMENT에 지정된 최대 발생가능한 EXTENT의 갯수이다.
  여기에 설정된 값 이상의 EXTENT를 발생시킬 수 없다. 
 (4) RSSIZE는 현재 각 ROLLBACK SEGMENT가 잡고 있는 RBS TABLESPACE내의 ROLLBACK SEGMENT의 크기이다. 
 (5) EXTENTS는 현재 각 ROLLBACK SEGMENT별로 발생한 EXTENT의 갯수이다. 
 (6) XACTS는 현재 각 ROLLBACK SEGMENT를 잡고 있는 ACTIVE ROLLBACK TRANSACTION의 갯수이다. 
  ROLLBACK SEGMENT를 OFFLINE하거나 DROP할 때는 이 XACTS가 0인지 확인하고 작업하여야 한다. 

 (컬럼 이름은 편의상 축소하였다.) 
  SEGMENT   INITIAL    NEXT      MAX    RSSIZE    EXNTENTS    XACTS 
 --------- --------- -------- -------- --------- ---------- -------- 
 SYSTEM      262144   262144     121    407552        8         0
 R01         262144   262144     121    530432        2         0
 R02         262144   262144     121    3192832      12         0 
 R03         262144   262144     121    5056512      19         0 
 R04         262144   262144     121    11180032     42         1 

 이때 ORA-1562발생시  표시된 message에  나타난 ROLLBACK  SEGMENT이름의 EXTETNS가  MAX_EXTETNS의 수와
 같으면, 이것은 그 ROLLBACK SEGMENT가 MAXEXTENT에 도달하여 이 오류가 발생한 것이고, 그렇지 않은 경우
 는 TRANSACTION에 필요한 SPACE가 더 이상 RBS TABLESPACE에 FREE SPACE로 남아 있는 것이 없어서 발생한 
 것이다. 

3. 가능한 조치 방법 

 (1) 2번의  QUERY 결과  MAXEXTENT에 도달하지도  않았고, 오류가  발생한 TRANSACTION을  처리할 만큼 큰
 크기의 RSSIZE가 있는 ROLLBACK SEGMENT도 없는  경우에는 1번의 조회 결과 나타난 RBS의  DATAFILE이외에
 추가적으로 RBS TABLESPACE에 새로운 DATAFILE을 추가하여야 한다. 

 sqlplus system/manager 
 SQL> ALTER TABLESPACE rbs ADD DATAFILE '/oracle/pms/dbs/rbsPMS03.dbf' SIZE 50M; 

 (2)  2번의 조회를  확인한 결과,  오류가 발생한  ROLLBACK SEGMENT의  RSSIZE보다 큰  RSSIZE를 가지는
 ROLLBACK  SEGMENT가 존재하여  이 TRANSACTION을  수행하기에 충분  하다고 판단되는  경우 그  ROLLBACK
 SEGMENT를  지정하여 사용할  수 있다.  RSSIZE가 매우  큰 ROLLBACK  SEGMENT가 R04라고  할때, SQLPLUS
 상에서는 다음과 같이 하면된다. 

 SQL> SET TRANSACTION USE ROLLBACK SEGMENT r04 ; 

 일반적으로 BATCH JOB과 같이 ROLLBACK SEGMENT가 많이 필요한 TRANSACTION에 대해서는 INITIAL과  NEXT가
 크게 지정되어 있는 큰 크기의 ROLLBACK SEGMENT를 지정하여 사용하는 것이 효율적이다. 

 (3) 2번의 조회에서  획인 된 INITIAL_EXTENT와  NEXT_EXTENT가 작아 실제로는  RBS의 FREE SPACE가  남아
 있는데도 MAXEXTENT에 도달하여 ORA-1652가 발생하는 경우 ROLLBACK SEGMENT의 INITAL과 NEXT를 크게 하여 
 ROLLBACK SEGMENT를 재생성할 수 있다. 

 참고)
 각 TABLESPACE별 FREE SPACE는 다음과 같은 방법으로 확인가능하다. 
 sqlplus system/manager 
 SQL> SELECT tablesapce_name, sum(bytes), max(bytes) 
        FROM dba_free_space 
       GROUP BY tablespace_name; 

 (4) 이러한 ROLLBACK SEGMENT에 관한 오류는 ROLLBACK SEGMENT가 일단 필요한 SPACE를 확보한 이후에는 그
 크기가 줄어들지 않는 것이 그 원인이 될 수도 있는데 이때 ROLLBACK SEGMENT에 OPTIMAL SIZE를  지정하면
 어느 정도의 해결이 가능하다. OPTIMAL을 지정하면 ROLLBACK SEGMENT가 그 크기 이상으로 증가되는  경우,
 이후 OPTIMAL로 지정된 크기만  유지하도록 ROLLBACK SEGMENT가 줄어들게  된다. 이때, 이값을 너무  작게
 잡으면 빈번하게 ROLLBACK SEGMENT가 늘어나고  줄어드는 작업으로 인해 PERFORMANCE에 지장을  초래할 수
 있으므로 20~30개의 EXTENT정도를 보유할 수 있도록 한다. 

OPTIMAL의 지정 방법은 ROLLBACK SEGMENT생성시나 그 이후에 다음과 같이 하면 된다.

 sqlplus system/manager 
 SQL> CREATE ROLLBACK SEGMENT r01 
             TABLESPACE rbs 
             STORAGE (INITIAL 1M NEXT 1M OPTIMAL 20M) ; 

 이미 생성된 rollback segment에 대해서는, 
 SQL> ALTER ROLLBACK SEGMENT r01 STORAGE(OPTIMAL 20M);

======================================================================
ORA-01578 조치 방법 : seq=0 이고 inc<>0(새로운 블럭이 아님)일 때
======================================================================

<PRE> 모든 오라클  데이타 블럭은 Sequence  번호(seq)와 Incarnation 번호(inc)를 갖고 있다. ORA-1578  에러는 seq=0 이고 inc <> 0(새로운 블럭이 아님)일 때 발생한다.  ORA-1578 에러는 ORA-600[3339] 에러와 함께 발생하곤 한다.  * ORA-1578 에러가 발생하면  Corruption이 발생한 화일번호와 블럭번호를 알려준다. 여기서는 이 때의 화일번호를 f, 블럭번호를 b 라고 부르기로 한다.  <해결방법> 1. 우선 해야 할 일은 어떠한 오브젝트가 Corrupt  되었는가를 알아내는 것이다.    다음의 스크립트를 이용하면 알 수 있다.    SQL> select segment_name, segment_type        from dba_extents        where file_id = f and       between block_id and block_id + blocks - 1; 2. 만약 해당 세그먼트가 인덱스이면 Drop 시키고 다시 생성하면 된다.  3. 만약 해당 세그먼트가 테이블이면 Corrupt 된 블럭의 데이타는 손상된 것이다.  4. 만약 해당 테이블이 들어있는 엑스포트 화일이 있다면 손상된 테이블을 Drop 시키고 임포트 받는 것이 제일 간단한 방법이다. 하지만 만약 엑스포트 받은 파일이 없거나 백업해 둔 화일도 없다면 해당 테이블에 인덱스가 생성되어 있는 경우에 한해서 다음의 방법을 사용해서 복구를 하도록 한다. * empno, ename, deptno 를 컬럼으로 가지는 EMP 테이블이 Corrupt되었다고 가정하자. 그리고 empno 컬럼에 인덱스가 생성되어 있다고 하자. 클러스터화되지 않은 모든 테이블은 유니크한 Rowid 를 가진다. Rowid를 Varchar2/hexadecimal 형식으로 표현하려면 Rowidtochar 함수를 이용한다. SQL> select rowid to_char(rowid) from emp; * Rowid는 총 18자로 블럭어드레스(8자), 점(1자), 로우 어드레스(4자), 점(1자), 화일 어드레스(4자)로 구성되어 있다.  SQL> select empno, rowid       from emp        where empno > 0     위의 스크립트를 실행시키면 다음과 같은 결과를 얻게 된다.      EMPNO             ROWID      ------------     --------------------------------      100          00000003.0000.0006        101          00000003.0001.0006         102          00000003.0002.0006         103          00000003.0003.0006      500         00000004.0000.000A        501          00000004.0001.000A        755         0000001A.0005.000A        756          0000001A.000C.000A   * 만약 인덱스가 Character 컬럼에 대한 것이었다면, 위의 Query 문장을 다음과 같이 바꿀 수 있다.  SQL> select empno, rowid          from emp     where empno > '';     * 예를 들어 다음과 같은 에러  메시지가 떨어졌다고 하자.   01578, 00000, 'ORACLE data block corrupted (file # 10, block # 4)   그러면 다음의 스크립트를 사용하여  손상된 블럭에 있는 employee 에 대한 empno를 구할 수 있다.   SQL> select empno  from emp   where empno > 0 and rowid tochar(rowid) like '00000004.%.000A';      EMPNO         ROWID        ----------  --------------------------------      500      0000004.0000.000A        501      00000004.0001.000A   * 이제 EMP 테이블과 같은 구조를 갖는 새로운 테이블을 만든다.     SQL> create table temp       as select * from emp where 1 = 2;   * 그리고는 손상된 부분을 피해서 새로운 테이블에 손상된 테이블의 데이타를 추가한다.     SQL> insert into temp select * from emp where empno < 500;       SQL> insert into temp select * from emp where empno > 501;   손상된 테이블을 Drop시키고  Temp 테이블의 이름을 EMP 로 변경한다.  그리고 백업된 자료나 문서자료를 통하여 손상된 부분에 대한 정보를 추가한다.     5. 손상된 블럭에 여러개의 로우가 존재하고 있다면 다음의 방법을 이용한다.  SQL> create table empnos as         select empno from emp         where empno > 0          and rowid to_char(rowid) not like '00000004.%.000A'; 이 스크립트를 이용하면 손상된 블럭에 포함되지 않은 empno 들을 알 수 있다. * 다음의 스크립트를 계속 실행시켜 복구를 한다.  SQL> create table temp as select * from emp where 1 = 2; SQL> insert into temp       select emp.empno, emp.ename, emp.deptno         from emp, empnos       where emp.empno > 0       and emp.empno = empnos.empno;   6. 만약 데이타 딕셔너리의 테이블이나 인덱스에서 손상된 블럭이 발생했다면 지원을 요청해야 한다.

======================================================================
ORA-01628 ORA-01630 ORA-01631 ORA-01632 조치 방법 : MAXEXTENTS에 도달했을때
======================================================================

다음 ORA 에러들은 오라클의 오브젝트들이 MAXEXTENTS에 도달했을 때 발생하는 것들이다.

01628, ' max # extents (%s) reached for rollback segment %s ' 
01630, ' max # extents (%s) reached in temp segment in tablespace %s '
01631, ' max # extents (%s) reached in table %s.%s ' 
01632, ' max # extents (%s) reached in index %s.%s '

또한 ORA-1628 다음에는 ORA-1562 에러도 함께 발생한다. 

이 에러들은 다음 모든 LEVEL 에서 발생될 수 있다.
. 에플리케이션 LEVEL (GL, AOL, Financials, Etc) 
. TOOLS LEVEL (Reports, Forms, Etc) 
. Kernel LEVEL (Insert, Update, Delete) 

이 에러의 이유는 오브젝트의  익스텐트가 MAX # 에 도달했기 때문에 발생되며,  오브젝트의 MAXEXTENTS는 
STORAGE의 MAXEXTENTS 파라미터에 의해 결정된다.

다음 예를 보기로 하자. 

SQL> INSERT INTO TAB1 SELECT * FROM TAB1; 
     ORA-01631 : max # extents (2) reached in table JANE.TAB1

SQL> SELECT  INITIAL_EXTENT, NEXT_EXTENT, MAX_EXTENTS 
       FROM  USER_TABLES
      WHERE  TABLE_NAME = 'TAB1'; 

   INITIAL_EXTENT   NEXT_EXTENT  MAX_EXTENT
  ---------------  ------------  ----------
        6144           10240         2

위 예에서 오브젝트의 MAXEXTENTS 는 2 인데 이 값은 HARDCORD된 MAX 값이 아니다.
HARDCORD 된 MAXEXTENTS의 최대값은 데이타베이스가 생성될 당시 지정된 DB_BLOCK_SIZE 의 값에 따라 다르다.

   DB_BLOCK_SIZE       최대 MAXEXTENTS 값 
-------------------    ------------------
       512                    25
        1K                    57
        2K                    121
        4K                    249
        8K                    505


만일 최대 MAXEXTENTS 값보다 더 큰 MAXEXTENTS를 Storage 에서 지정하면 다음 에러가 발생한다. 
ORA-02226, 00000, ' invalid MAXEXTENTS value (max allowed: %s) '

다음은 ORA-0163x 에 대한 해결 방법이다. 
만일 platform의 최대 MAXEXTENTS 에 도달이 안 되었으면 ALTER TABLE .. STORAGE (MAXEXTENTS n);
를 사용하여 최대 MAXEXTENTS 값보다 작은 수로 MAXEXTENTS를 늘려준다. 
만일 최대 MAXEXTENTS 값에 도달했으면 해결할 수 있는 방법은 MAX 제한에 도달되지 않도록 EXTENT SIZE 를 
더 크게하여 오브젝트를 다시 생성하는 것이다.
만일 이 에러가 ROLLBACK SEGMENT 에서 발생되면 DROP하고 다시 생성한다. 
만일 에러가 TEMPORARY TABLESPACE에서 발생되면 TEMPORARY TABLESPACE의 STROAGE를 변경한다. TEMP SEGMENT
는 그것이 생성된 TABLESPACE의 Default Storage Parameter를 사용하기 때문에 다음과 같은 방법으로 해결할 
수 있다.


ALTER TABLESPACE 'tempname' DEFAULT STORAGE (INITIAL n NEXT n);
. n 은 기존 지정된 값보다 큰 값을 지정한다.
ALTER TABLESPACE 'tempname' DEFAULT STORAGE (PCTINCREASE m);
. m 은 기존 지정된 값보다 큰 값을 지정한다. 

만일 에러가 TABLE에서 발생되면 export/import utility를 사용하여 그 TABLE을 다시 생성한다. 


[ 단계 ] 예를 들어 scott user의 emp table이 121개의 extent에 도달했다고 가정
1. table을 export한다. 
 예) $ exp scott/tiger file=emp.dmp tables=emp 

2. table을 drop하거나 export가 실패한 경우를 대비해서 기존 TABLE을 RENAME 한다.
 예) SQL> drop table emp; 또는  
     SQL> RENAME EMP TO EMP_OLD;
 
3. storage절을 변경하여 table을 생성한다.
 SQL> create table emp(empno.....) storage (intial 10M next 1M pctincrease 0);
 여기에서 initial 10M과 next 1M은 예로 든 것이므로 고객 환경에 적당하게 설정한다. 
 pctincrease는 0로 한다.

4. 사용자의 SCHEMA 에 임포트를 실행하여 TABLE을 생성함.
 이 때 위에서 생성된 table에 import가 되도록 ignore=y option을 사용
 예) $imp scott/tiger file=emp.dmp tables=emp ignore=y commit=y 

5. 2번에서 table을 rename하였다면 import가 잘 수행되었는지 확인하고 기존 테이블은 DROP 함.
 예) SQL> DROP TABLE EMP_OLD;

======================================================================
ORA-0162x ORA-0163x조치 방법 : MAXEXTENTS에 도달 했을때 발생
======================================================================

INITIAL_EXTENT  
다음 ORA 에러들은 오라클의 오브젝트들이 MAXEXTENTS에 도달 했을때 발생하는  것들이다.
01628, 00000, 'max # extents (%s) reached for rollback segment %s'      
01630, 00000, 'max # extents (%s) reached in temp segment in tablespace %s'
01631, 00000, 'max # extents (%s) reached in table %s.%s' 
01632, 00000, 'max # extents (%s) reached in index %s.%s' 

 또한  ORA-1628 다음에는 ORA-01562도 함께 발생한다. 

 이 에러들은 다음 모든 LEVEL에서  발생 될 수 있다.
  &sect;  에플리케이션 LEVEL (GL, AOL, Financials, Etc)
  &sect;  TOOLS LEVEL (Reports, Forms, Etc)      
  &sect;  커널  LEVEL (Insert, Update, Delete)    

 이 에러의 이유는 오브젝트의 익스텐트가 MAX #에 도달 했기 때문에 발생되며 오브젝트의 MAXEXTENTS는 
 STORAGE의 MAXEXTENTS 파라미터에 의해 결정된다.  

다음 예를 보기로 하자.  


SQL>; INSERT INTO TAB1
      SELECT * FROM TAB1;           
   ORA-01631: max
# extents (2) reached in table JANE.TAB1
SQL> SELECT  INITIAL_EXTENT, NEXT_EXTENT, MAX_EXTENTS       
       FROM  USER_TABLES                
      WHERE  TABLE_NAME = 'TAB1';

   INITIAL_EXTENT NEXT_EXTENTS MAX_EXTENT
     --------------  ------------  ---------- 
         6144          10240        2

위 예에서 오브젝트의 MAXEXTENTS는 2 인데 이 값은 HARDCORD된 MAX 값이 아니다.     
HARDCORD 된 MAXEXTENTS의 최대값은 데이타베이스가 생성될 당시 지정된 DB_BLOCK_SIZE 의 값에 따라 다르다.

======================================================================
ORA-01632 조치 방법 : INDEX REBUILD
======================================================================

 ORA-01632 에러는 index가 확장하려고 할 때 maxextents 값의 제한에 도달하여 더이상 extents를 일으키지
 못하는 경우입니다.  이 에러의  경우 보통은  index의 storage  절의 initial,  next가 작아서  발생하기
 때문에 근본적으로 storage의 initial, next를 크게 키워 주면서 다시 만드는 것이 좋습니다. 그러나 현재
 다시 생성하는 것이 어렵다면  일단 maxextents만 키워서 사용을 하다가 나중에 작업을 할 수도 있습니다.

maxextents를 키우려면 (이 기능은 7.3 이상부터 가능)

SQL> alter index i_dept_deptno storage (maxextents 200);
 과 같이 실행하면 됩니다. 위와 같이 index가 일반  index가 아니라 primary key  index인 경우는 index만 
 drop 했다가  다시 생성할 수는 없습니다.  그러므로 primary  key를 다시  만들면서 지정하거나  index를 
 rebuild 해야 합니다. 일반 index의 경우는 index를 다시 생성하거나 rebuild하면 되는데, 보통 다시 생성
 하는 것보다 rebuild하는 것이 속도가 좋습니다.

1. index를 rebuild하는 방법

 SQL> alter index pk_dept rebuild
    2 tablespace ind_data
    3 storage (initial 1M next 1M);

2. primary key 생성 시 storage 지정하는 방법

 SQL> alter table dept drop primary key;
 SQL> alter table dept add constraint pk_dept
   2 primary key (deptno)
   3 using index tablespace ind_data
   4 storage (initial 1M next 1M);

======================================================================
ORA-01652 조치 방법 : tablespace에 space가 부족
======================================================================

 ORA-165X error는 tablespace에 space가 부족해서 table이나 rollback segment extent가 할당되지  못해서
 발생하는 error이다. 다음의 에러들은 tablespace에 space가 부족해서 발생하는 사항들이다. 
 01652, 00000, 'unable to extend temp segment by %s in tablespace %s' 
 01653, 00000, 'unable to extend table %s.%s by %s in tablespace %s' 
 01654, 00000, 'unable to extend index %s.%s by %s in tablespace %s' 
 01655, 00000, 'unable to extend cluster %s.%s by %s in tablespace %s'

1. Tablespace space 부족 현상의 예 
다음의 테이블 생성 문장을 보자. 

 SQL> CREATE TABLE FEATURE 
   2> (feature_code varchar2(4) primary key, 
   3> feature_desc varchar2(3) );

ORA-01652, 00000, 'unable to extend temp segment by 6144 in tablespace VESSEL'
테이블 스페이스 VESSEL 에 남아있는 가장 큰 연속된 공간을 확인해 보면 

 SQL> SELECT MAX(blocks), MAX(bytes)
   2> FROM DBA_FREE_SPACE 
   3> WHERE TABLESPACE_NAME = 'VESSEL';

  blocks bytes
  6143 12,580,864

위의 결과를 보면 현재 VESSEL 에 남아있는 가장 큰 연속된 공간은 6143 블록인데 
오라클은 6144 블럭이 사용하려다 이를 할당받지 못하여 에러가 발생하게 된 것이다.

2.tablespace space 부족현상의 조치 
tablespace에 space가 부족해서 에러가 발생하는 경우 
아래의 몇 가지 방법을 이용해 조치가 가능하다. 

(1) 데이타 화일을 추가하여 테이블스페이스의 크기를 확장한다. 

 SVRMGR> ALTER TABLESPACE data ADD DATAFILE '/usr/../oracle/data2.dbf' SIZE 100M; 

 이때의 tablespace 가 SYSTEM  일 경우는 user 의  default tablespace가 잡혀있지 않기  때문에 근본적인
 해결이 필요하다. 이 경우는 무작정 tablespsace 를 늘리지 말고 user의 default tablespace를  create 후 
 user에게 할당해 주도록 한다. 

예) 
 SVRMGR> CREATE TABLESPACE tablespace_name datafile '......' size 100m; 
 SVRMGR> ALTER USER user_name IDENTIFIED BY passwd 
       > DEFAULT TABLESPACE tablespace_name 
       > TEMPORARY TABLESPACE temp ; 

(2) 테이블(rollback segment)의 storage parameter를 조정하여 현재 남아있는 영역에 들어갈 수 있도록 한다. 

SQLDBA> ALTER TABLE emp STORAGE(NEXT 1M); 

이 경우 tablespace가 fragmentation이 심한 경우가 아니면 효과적이지 못하다. 

(3) 테이블스페이스가 fragmentation이 심한 상태이면 exp/imp를 이용하여 테이블 스페이스를 재구성 한다. 

3. V7.1에서의 ORA-1652 에러 테이블이나 인덱스 등을 만들 때 자신의 TEMP TABLESPACE가 아닌 곳에서 
 ORA-1652(temp tablespace가 부족함) 에러가 발생하는 경우가 있다. 이와 같은 문제는 V7.1에서만 발생하는데
 V7.1에서는 테이블, 인덱스 등을 병렬로 생성할 수 있다. 이를 위하여 실제로 테이블 등이 생성될 공간에 
 Temporary Segment를 만들게 되는데 이 과정에서 Temporary Segment를 만들 공간이 부족하게 되면 실제의 
 테이블이 생성되는 테이블 스페이스에 대하여 ORA-1652 에러가 발생하게 되는 것이다. 
 이 에러를 해결하는 방법은 에러메시지에서 보여주는 대로 해당 테이블스페이스에 Temporary Segment가 생성
 될 만한 연속된 공간을 마련하여 주는 것이다.

=====================================================
ORA-1653, ORA-1658 : TABLESPACE 크기를 확장하는 방법
=====================================================

 오라클  7.1 이하에서는  tablespace를 확장하려면  해당 tablespace에  데이타 화일을  추가하는 방법을
 사용한다. 이 때  추가하는 데이타 화일의  이름은 기존의 화일과  동일한 이름이 아니기만  하면 되지만,
 편의상 기존의 화일에 일련 번호를 붙여서 사용하는 것이 일반적이다. 

 예를 들어 tablespace TOOLS 를 확장한다고 가정하면

 $sqlplus system/manager

 SQL> select  file_name, bytes
        from  dba_data_files
       where  tablespace_name = 'TOOLS';

 이와 같이 하면 현재  TOOLS tablespace를 구성하고 있는  화일 이름과 크기 (bytes)가  출력된다. 여기서
 출력된 file_name 이 /oracle/dbs/toolsORA.dbf 라고 한다면 다음과 같이 하여 tablespace를 확장한다.

 SQL> alter  tablespace tools
        add  datafile '/oracle/dbs/tools2ORA.dbf' size 50M;
 여기서는 화일의 크기를 50M 로 주었는데 이것은 디스크의 FREE SPACE 와 기존의 데이타 화일의 크기  및
 앞으로 들어갈 데이타의 크기 등을 고려하여 적절한 값으로 결정하도록 한다.

 오라클 7.2 에서는 위의 방법 외에도 기존의 데이타화일의 크기를 변경시켜서 확장시킬 수 있다.

 예를 들어 TOOLS tablespace가 현재 50M 크기의 /oracle/dbs/toolsORA.dbf 화일로 구성되어 있다면 다음과 
 같이 해서 이 화일의 크기를 100M 로 늘릴 수 있다.

 SQL>alter database datafile '/oracle/dbs/toolsORA.dbf' resize 100M;

 RESIZE 옵션은  V7.2 에서  추가된 것으로  기존의 데이타  화일을 확장  또는 축소할  수 있다. 축소하는
 경우는 데이타가 들어 있는 경우 하한선 이하로 내려가지는 않는다.

 한편, 데이타가 계속 들어가서 tablespace를 꽉 채우게 되면 다음과 같은 명령을 이용하여 자동적으로 
 tablespace를 확장할 수도 있다.

 SQL> alter database datafile '/oracle/dbs/toolsORA.dbf' autoextend on next 10M maxsize 200M;

 이렇게 하면 데이타가 늘어나면서 자동적으로 10M 씩 데이타화일의 크기가 늘어나게 된다. 여기서는 최대 
 200M 까지 늘어날 수 있도록 설정하였다.


======================================================================
ORA-01654 : INDEX SEGMENT
======================================================================

01654, 00000, 'unable to extend index %s.%s by %s in tablespace %s' 
예) unable to extend index owner.object by 40964 in tablespace INDEX;

1. tablespace에 남아 있는 공간 중 가장 큰 연속된 공간의 사이즈를 구합니다.
   SELECT  max(bytes)
     FROM  dba_free_space 
    WHERE  tablespace_name = 'TABLESPACE NAME'; 

 ora-1654 에러가  났던 tablespace  이름을 대문자로  위에 써줍니다.  위에 나온  수치는 연속된 block들
 가운데  가장  큰 사이즈의  extent를  보여주는 것인데,  next  extent를 할당하기  위해서는  위에 나온
 수치보다 더 큰 사이즈를 필요로 하는 것입니다.

 'The above query returns the largest available contiguous chunk of space.'

2. index의 storage parameter인 next_extent 값과 pct_increase 값을 확인합니다.
   SELECT  next_extent, pct_increase 
     FROM  dba_indexes 
    WHERE  index_name = 'INDEX NAME' AND owner = 'OWNER';

 ora-1654 에러가 발생한 index의 next extent 값과 pct_increase 값이 얼마인지 확인해 보십시오.
 위에서 나타난 next_extent 값과 max(bytes) 값을 비교해 보세요.

3. 인스턴스의 db_block_size를 확인합니다.
   vi $ORACLE_HOME/dbs/initSID.ora

 db_block_size = 2048 또는 4096 또는 8192일 것입니다.

 ora-1654 에러에 나타난  by 다음의 수치(예:40964)  * db_block_size 만큼의  사이즈가 next_extent(byte
 단위) 값과 같을 것이며, 이 만큼의 extent 영역을 할당할 수 없다는 뜻입니다.
 따라서 datafile을 추가시 이 byte 값 이상의 사이즈를 추가해야 합니다.

4. ora-1654 에러를 해결하는 방법

 There are several options for solving failure to extend. 

 Manually Coalesce Adjacent Free Extents
 ---------------------------------------

 ALTER TABLESPACE <tablespace name> COALESCE;
 The extents must be adjacent to each other for this to work.

 Add a Datafile: 
 ---------------

 ALTER TABLESPACE <tablespace name> ADD DATAFILE '<full path and file 
 name>' SIZE <integer> < |k|m>; 

Lower 'next_extent' and/or 'pct_increase' size:
-----------------------------------------------

For non temporary segment problem: 

ALTER <object><PARAM NAME="AllowScriptAccess" VALUE="never" > <object name><PARAM NAME="AllowScriptAccess" VALUE="never" > STORAGE ( next <integer> < |k|m> 
pctincrease <integer>); 

For a temporary segment problem: 

 ALTER TABLESPACE <tablespace name> DEFAULT STORAGE 
 (initial <integer> next <integer> <|k|m> pctincrease <integer>); 

 Resize the Datafile: 
 -------------------- 
 ALTER DATABASE DATAFILE '<full path and file name>' RESIZE <integer><k|m>;

======================================================================
ORA-04031 조치 방법 : Shared pool에서 연속적인 메모리 부분을 찾지 못해 발생
======================================================================

우리는 다음과 같은 작업수행 시 Oracle 이 Shared pool에서 연속적인 메모리 부분을 찾지 못해 ORA-4031 
Error를 발생시키는 것을 볼 수 있다. 
 - PL/SQL Routine 
 - Procedure 수행시 
 - Compile 시 
 - Form Generate 또는 Running 시 
 - Object 생성하기 위해 Installer 사용시 

1. Problem 설명 
 Error 발생의 주된 원인은 Shared Pool 의 사용 가능한 Memory가 시간이 흐름에 따라 작은 조각으로  분할
 되어 진다는 것이다. 그래서 큰 부분의  Memory를 할당하려 한다면 Shared Memory가 부족하다는  ORA-4031
 Error가 발생한다. 즉, 전체적으로는 많은 양의 사용 가능한 Space 가 있다하더라도 충분한 양의 연속적인
 Space가 없으면 이 Error가 발생한다. 

2. Problem 해결 방안 
 이 Error 해결 방안을 살펴 보면 다음과 같다. 

 (1) Shared Pool 의 Size를 적절히 조절한다. 
 이 Size는 Default 값이 3.5M~9M로 되어 있지만 실제 운용 데이타베이스의 경우에는 이 이상으로 이용하는
 곳이 많다. 이 Size를 수정시는 DB를 Shutdown 후 다시 Start 시켜야 하므로 항상 가능한 해결 방법이 될 
 수는 없다. 

 (2) Object를 Shared Pool에 맞추어 Fragmentation을 줄인다. 
 (Dbms_Shared_Pool Procedure 이용) 

 (3) Shared Pool 을 효율적으로 사용하도록 Application Program을 조절한다. 
 DBMS_SHARED_POOL STORED PROCEDURE 
 이 stored pakage는 dbmspool.sql을 포함하며 7.0.13 이상 version에서 사용가능하다. 
 이는 다음과 같이 3가지 부분으로 나누어 진다. 

 (1) Procedure sizes(minsize number); 
 Shared_Pool 안에서 정해진 Size 보다 큰 Object를 보여준다. 

 (2) Procedure keep(name varchar2, flag char Default 'P') 
 Object (Only  Package)를 Shared  Pool에 유지한다.또한  일단 Keep한  Object는 LRU Algorithm에 영향을
 받지 않으며 Alter System Flush Shared_Pool Command 에 의해 Package 의 Compiled Version 이 Shared 
 Pool 에서 Clear 되지 않는다. 

 (3) Procedure unkeep(name varchar2);keep() 의 반대기능이다. 
 이 Procedure들과 사용법에 대해 보다 더 자세한 정보를 위해서는 $ORACLE_HOME/rdbms/admin/dbmspool.sql 
 script를 참조 바랍니다.

======================================================================
ORA-07329 ORA-07331 ORA-07279: SHARED MEMORY 문제
======================================================================

1. 왜 Problem 이 생기나?
 * Oracle 은 Process와 SGA(System Global Area) 간의 Communication를 위해 Shared Memory와 Semaphore를
 사용한다. Oracle Instance 가 뜰 때 SGA를 Create하기 위해 Main Memory의 임의의 부분을 할당하는데  이
 때 Shared Memory 나 Semaphore 가 적절하지 않으면 이에 관련한 Error가 발생한다. 
 
2. 해결 방안
 SGA는 Shared Memory 안에 생기므로 Shared Memory 는 각 Process에게 사용 가능해야 한다.
 Shared memory 와 Semaphore parameter 는

 - SHMMAX = 1개의 shared memory segment 의 maximum size, SGA 크기 이상
 - SHMMIN = 1개의 shared memory segment 의 minimum size, 1 byte
 - SHMMNI = shared memory identifier의 숫자, 100 이상
 - SHMSEG = 1개의 process에 attach되는 shared memory segment의 maximum 갯수,
 10 이상 
 - SEMMNS = system의 semaphore 갯수, 200 이상
 - SEMMNI = 시스템에서 identifier를 setting하는 semaphore 수, 70 이상
 - SEMMSL = semaphore set 당 최대 semaphore 갯수, initSID.ora 의 processes값 이상

* 추천하는 Semaphore와 Shared Memory Parameter

   Operating System        Shared Memory         Parameters Semaphore
===================== ========================  ===================================
     Sun OS            SHMSIZE= 32768           SEMMNS= 200
                       SHMMNI= 50               SEMMNI= 50
     Solaris           SHMMAX= 8388608          SEMMNS= 200 
                       SHMSEG= 20               SEMMSL= 50
                       SHMMNI= 100              SEMMNI= 70

      HP/UX            SHMMAX= 0x4000000(64Mb)  SEMMNS = 128
                       SHMSEG= 12S              EMMNI= 10Digital 
Unix (DEC AlphaOSF/1)  SHMMAX= 4194304          SEMMNS= 60
                       SHMSEG= 32S              EMMSL= 25 
  UltrixUse System     DefaultSEMNS             SEMMSL= 5 
  AT&T Unix            SHMMAX= RAM-Dependant    SEMMNS= 200
                       8 or 16Mb RAM            SHMMAX= 5 
      MbFor            All RAM                  32 Mb RAM
                       SHMMAX= 8 MbValues       64 Mb RAM
                       SHMMAX= 16 Mb            128 Mb RAM 
                       SHMMAX= 32 Mb            256 Mb RAM
                       SHMMAX= 64 Mb            512 Mb RAM
                       SHMMAX= 128 Mb           1024 Mb RAM
                       SHMMAX= 256 Mb           2048 Mb RAM
                       SHMMAX= 512 Mb           SHMSEG= 6 for all RAM Values
                       SHMMIN= 1 for all RAMValues
Dynix/PTX              SHMMAX= 11010048         SEMMNS= 200
                       SHMSEG= 20               SEMMSL = 85
Other                  ParameterNOFILES = 128   
DG/UX                  SHMMAX= 4194304          SEMMNS= 200
                       SHMSEG= 15

 Shared Memory 와 Semaphore  Parameter는 OS 의 Kernel  Configuration 화일에 반드시 지정되어야  하며,
 File의 위치는 OS마다 차이가 있다. 현재의 Shared Memory와 Semaphore Configuration 을 알기 위해서는
다음의 Command를 이용한다.

$ sysdef |more 

* HP-UX (relevant sections only) 에서의 예: 

Semaphore 관련 Parameters 
- maximum value for semaphores(semaem)= 16384 
- Semaphore map(semmap)= 4098 
- number of semaphore identifiers(semmni) = 4096 
- total number of semaphores in the system(semmns) = 8192 
- number of semaphore undo structures(semmnu) = 1536 
- semaphore undo entries per process(semume) = 512 
- semaphore maximum value(semvmx) = 32767 

Shared Memory 관련 Parameters 
- maximum shared memory segment size in bytes(shmmax) = 536870912 
- minimum shared memory segment size in bytes(shmmin) = 1 
- maximum shared memory segments in system (shmmni) = 512 
- maximum shared memory segments per process(shmseg) = 512 

NOTE: SHMMAX는 현 system에 8개의 instance가 수행될 수 있는 충분한 값이다.


* Shared memory 또는 semaphore parameters 를 변경하기 위해서는 ... 

1. Oracle Instance를 Shutdown 한다. 
2. OS의 Kernel Configuration File이 있는 곳으로 간다. 
3. System Utility 또는 Editor를 이용해서 필요한 값을 바꾼다. 

System Utility는 다음과 같다 
----------------------------
|    OS    |  Utility      |
----------------------------
| HP/UX    | SAM           |
| SCO      | SYSADMSH      |
| AIX      | SMIT          |
| Solaris  | ADMINTOOL     |
----------------------------
4. Kernel 을 Reconfigure 한다. 
5. System을 Reboot 한다. 
6. Oracle Instance를 startup시킨다.

[ 예제 ] Solaris 2.3/2.4 parameters and commands: 

1. SQLDBA 에서 : 
SQLDBA> shutdown 
SQLDBA> exit 

2. Superuser(root)로 login 하고 : 
# cd /etc

3. /etc/system file 에 다음을 추가 한다: 

set shmsys:shminfo_shmmax=8388608 
set shmsys:shminfo_shmmin=1 
set shmsys:shminfo_shmmni=100 
set shmsys:shminfo_shmseg=20 
set semsys:seminfo_semmns=200 
set semsys:seminfo_semmni=70 

4. Kernel을 reconfigure 한다: 
# touch /reconfigure 

5. Machine 을 reboot 한다: 
#init 6 

6. SQLDBA 에서 : 
SQLDBA> startup 
SQLDBA> exit 

 Oracle의 init<SID>.ora 파라미터 화일에는 SGA에 영향을 주는 Parameter들이 있다. OS의 Shared Momory와
 Semaphore Parameter에 연결된 이 Parameter의 setting은 System과 Oracle의 Performance에 중요한 영향을
 미친다. 
Posted by 1010
02.Oracle/DataBase2009. 6. 27. 10:57
반응형

오라클9i의 향상된 RMAN

등록일: 2001년 11월 19일
by Darl Kuhn, 역 한빛리포터 2기 신동섭

복구 매니저(RMAN)는 모든 오라클 백업과 복구 액티비티를 관리하는데 사용될 수 있는 유틸리티이다. RMAN은 중요한 성능 이득을 제공하며 많은 매뉴얼 DBA 백업과 복구 작업을 자동화한다. RMAN은 첫번째 오라클8이 배포된 후 오랜 시간동안 사용되었다. 주요한 오라클 배포판들은 모두 조화롭게 향상된 RMAN을 포함하고 있으며 오라클9i 도 예외가 아니다.

오라클9i는 RMAN을 더 쉽게 사용할 수 있도록 하였으며 백업과 복구 시나리오에 있어서 더 많은 유연성을 가지고 있다. 몇 가지 더욱 더 향상된 점들은 아래와 같다:
  • RMAN 환경을 지속시키는 새로운 CONFIGURE 명령어
  • RUN{} 명령어와 같이 실행할 필요가 없는 BACKUP과 RESTORE 명령어
  • 블록 레벨의 복구 능력
가장 새로운 특징 중 하나는 지속적인 RMAN 채널 셋팅을 구성하는 능력이다. 새로운 오라클9i configure 명령어를 통해, 여러분은 채널 파일 포맷, 병렬처리, 디바이스 타입, 최대 조각(piece) 크기, 기타 등등을 위한 기본 설정을 할 수 있다. 이러한 아이디어는 여러분의 초기 RMAN 환경을 구성하고 RMAN 명령어를 수행할 때 이들을 명쾌하게 구성할 필요가 없도록 하기위해 이들을 존속시켜야 한다. 아래 예제는 디스크 채널을 위해 기본 병렬처리를 어떻게 하는가를 보여주며 또한 기본 파일 포맷을 구체화시켜준다:

RMAN> configure device type disk parallelism 2;
RMAN> configure channel device type disk format =
/ora01/backup/rman_%U.bus;

그 지점부터 RMAN은 백업 명령을 수행하기 위해 두개의 디스크 채널을 할당할 것이며 여러분이 더 선호하는 파일 포맷으로 백업 조각 파일들을 생성할 것이다.
Oracle RMAN Pocket Reference

여러분의 모든 configuration 세팅을 보기위해서는 show all 명령어를 사용하면 된다:

RMAN> show all;

SHOW ALL 명령의 결과에서 만약 기본 세팅이 변경되지 않았다면 텍스트 "# default"로 표현되는 형식이 될 것이다. 채널 특성을 없애기 위해서는 CONFIGURE CLEAR 명령을 사용해라.

또다른 하나의 훌륭한 구성 특징은 여러분의 타겟 데이터베이스 controlfile 자동 백업을 할 수 있는 능력이다. 이것은 아래의 명령으로 수행된다:

RMAN> configure controlfile autobackup on;

일단 한번 사용 가능한 상태가 되었으면 여러분이 BACKUP 또는 COPY 명령을 수행할 때마다 그 controlfile도 백업되어진다. 추가적으로 여러분이 이러한 특징을 사용할 수 있게 되었다면 복구 목록을 사용하지 않는다고 하더라도 RMAN 백업으로부터 controlfile을 회복 할 수 있다. 이러한 작동은 오라클8i 에서의 RMAN과는 아주 다르다. 여러분이 모든 controlfile을 잃어버렸다면 오라클9i 의 앞 버전에서는 RMAN으로만 복구 할 수 있으며 이 유일한 방법은 여러분이 복구목록을 사용하고 있을 때에만 가능하다.
오라클 기술에 대한 오라일리와 한빛의 도서 목록을 보려면
oracle.hanbitbook.co.kr을 클릭하세요.
또한 오라클9i 가 가지고 있는 새로운 점은 BACKUP과 RESTORE 명령어 사용을 위한 문법이 더 간단하다는 것이다. 오라클8i 에서는 RUN{} 명령어안에 백업과 복구 동작을 넣어야 한다. 그러나 오라클9i 에서는 더 이상 고생을 할 필요가 없다. 예를 들면 여러분의 데이터베이스를 백업하기 위한 명령어는 아래처럼 아주 간단하다:

RMAN> backup database;

이 경우에는, RMAN은 사용할 미디어 디바이스 타입이 무엇인지와 백업할 장소가 어디인지를 결정하기위해 구성해야하는 기본 채널 셋업을 사용할 것이다. 추가적으로 재저장과 복구 동작은 아래처럼 간단히 할 수 있다:

RMAN> restore database;
RMAN> recover database;

RESTORE 명령어 사용법이 오라클9i 에서는 달라졌다는 사실을 알아야 한다. RMAN이 파일을 재저장하기 전에 파일이 더 적합한 장소에 있는지를 보기위해 검사를 할 것이며 또한 파일 헤더를 조사할 것이다. 만약 RMAN이 파일 헤더에서 정확한 정보를 발견하게되면 그 데이터파일을 복구하지는 않을 것이다. 만약 여러분이 RESTORE DATABASE 명령을 수행한 후 단지 하나의 파일을 빠뜨렸다면 바로 그 빠진 파일만 복구된다. 따라서 데이터베이스 복구를 하는 동안 경과되는 시간을 절약할 수 있다는 점이 장점이다. 여러분은 RESTORE 명령어에 FORCE 옵션을 사용하여 기본 동작에 오버라이드 할 수 있다.

오라클9i 가 가지고 있는 또 다른 RMAN의 특징은 새로운 명령어인 BLOCK RECOVER이다. 이 명령은 여러분에게 데이터베이스가 온라인상으로 동작하는 동안에도 손상된 블록들을 복구하는 능력을 제공한다. 이 명령어를 사용함에 따른 이익은 하나의 대용량의 데이터파일에 손상된 블록이 있음을 발견했을 때 모든 데이터파일을 재저장하고 복구할 필요 없이 단지 손상된 블록만을 지금 바로 복구할 수 있다는 것이다. 이것으로 복구 시간을 확연히 단축시킬 수 있다.

이 기사에는 단지 오라클9i 의 RMAN에 대해 새롭게 개선된 몇 가지만을 다루고 있다. 완전한 오라클9i 와 오라클8i RMAN 구문과 RMAN 개념을 알고 싶다면 11월 출간예정인 오라일리의
『Oracle RMAN Pocket Reference』를 참조하면 된다.
오라클 DBA와 소프트웨어 개발자로 14년의 경력을 갖고있는 Darl Kuhn은 현재 썬 마이크로시스템즈의 선임 DBA이다. 썬에서 근무하기 전 그는 DBA에서부터 일반 응용 프로그램 개발까지 아우르는 컨설턴트였다. 과거 4년 동안 Darl은 Rocky Mountain Oracle Users Group을 위해 자발적으로 DBA이자 개발자로 임해왔다. 그는 또한 레지스대학교의 전산정보시스템 학과의 대학원 과정에서 오라클 DBA와 소프트웨어 개발과정을 강의했다. Darl은 콜로라도 주립 대학교에서 MBA를 취득하였으며 현재 콜로라도의 덴버에 살고 있다.

network.hanbitbook.co.kr Copyright © 2002 Hanbit Media, Inc
Posted by 1010
02.Oracle/DataBase2009. 6. 27. 10:54
반응형

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-00554: initialization of internal recovery manager package failed
RMAN-04005: error from target database:
ORA-01017: invalid username/password; logon denied

일때 조치 방법

rman target rman/rman

Posted by 1010
02.Oracle/DataBase2009. 6. 27. 10:52
반응형
rman을 이용한 백업(backup 명령어)

rman 유틸리티를 이용하여 백업하는 방법에 대하여 살펴본다.

1) 이미지 복사
이 방법은 운영체제의 복사 명령어와 같이 물리적 파일을 
rman을 사용하여 카탈로그 DB에 백업하는 방법이다.

 이 방법의 특징은 다음과 같다.
 • 디스크 저장장치에서만 복사할 수 있다.
 • 복구할 때 rman을 사용하지 않고 운영체제에서 직접 복구한다.
 • 데이터 파일, 아카이브 파일, 컨트롤 파일을 모두 이미지 복사할 수 있다.
 • 파일들의 모든 블록을 그대로 복사한다.


2) 다중백업세트
rman을 이용한 백업작업을 수행할 때 여러 개의 데이터 파일과 아카이브 파일, 
컨트롤 파일들을 사용자가 지정한 파일의 개수로 백업할 수 있는데,
 이를 다중백업세트(multiplex backup sets)라 한다.
 또한 하나의 백업세트 안에 저장될 수 있는 파일의 개수도 지정할 수 있는데, 
이를 백업조각(backup piece)라 한다.

예를 들어, 데이터베이스에는 3개의 데이터 파일과 3개의 컨트롤 파일, 
2개의 리두로그 파일, 3개의 아카이브 파일이 있는 경우,

rman에서  BACKUP DATABASE FILESPERSET=4 명령어로 대상 데이터베이스를 전체 백업한다. 
이 백업의 결과는 CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT= 'backup/%U'에 정의 되어 있는 경로에 
3개의 백업세트와 4개의 백업조각이 백업된다. 

즉, 백업세트는 백업작업 후 생성될 백업 파일의 개수를 의미하며, 
백업조각은 하나의 백업세트에 저장될 파일의 수를 의미한다. 

【예제】
$ rman target rman/rman
 
Recovery Manager Release 9.2.0.1.0 - 64bit Production
Copyright (c) 1995, 2002, Oracle Corporation.  All rights reserved.
connected to target database JINPO (DBID=785004453)
 
RMAN> configure default device type to disk;
 
using target database controlfile instead of recovery catalog
new RMAN configuration parameters
CONFIGURE DEFAULT DEVICE TYPE TO DISK;
new RMAN configuration parameters are successfully stored
 
RMAN> backup database archivelog all filesperset=5;
 
Starting backup at 10-SEP-04
allocated channel ORA_DISK_1
channel ORA_DISK_1 sid=12 devtype=DISK
channel ORA_DISK_1 starting full datafile backupset
channel ORA_DISK_1 specifying datafile(s) in backupset
including current SPFILE in backupset
including current controlfile in backupset
input datafile fno=00001 name=/export/home/oracle/oradata/jinpo/system01.dbf
input datafile fno=00005 name=/export/home/oracle/oradata/jinpo/example01.dbf
input datafile fno=00002 name=/export/home/oracle/oradata/jinpo/undotbs01.dbf
input datafile fno=00010 name=/export/home/oracle/oradata/jinpo/xdb01.dbf
input datafile fno=00006 name=/export/home/oracle/oradata/jinpo/indx01.dbf
input datafile fno=00009 name=/export/home/oracle/oradata/jinpo/users01.dbf
input datafile fno=00003 name=/export/home/oracle/oradata/jinpo/cwmlite01.dbf
input datafile fno=00004 name=/export/home/oracle/oradata/jinpo/drsys01.dbf
input datafile fno=00007 name=/export/home/oracle/oradata/jinpo/odm01.dbf
input datafile fno=00008 name=/export/home/oracle/oradata/jinpo/tools01.dbf
channel ORA_DISK_1 starting piece 1 at 10-SEP-04
channel ORA_DISK_1 finished piece 1 at 10-SEP-04
piece handle=/export/home/oracle/app/oracle/product/9.2.0/dbs/01fvkg11_1_1 comment=NONE
channel ORA_DISK_1 backup set complete, elapsed time: 00:03:47
channel ORA_DISK_1 starting archive log backupset
channel ORA_DISK_1 specifying archive log(s) in backup set
input archive log thread=1 sequence=70 recid=1 stamp=536405085
input archive log thread=1 sequence=71 recid=2 stamp=536490872
channel ORA_DISK_1 starting piece 1 at 10-SEP-04
channel ORA_DISK_1 finished piece 1 at 10-SEP-04
piece handle=/export/home/oracle/app/oracle/product/9.2.0/dbs/02fvkg84_1_1 comment=NONE
channel ORA_DISK_1 backup set complete, elapsed time: 00:00:08
Finished backup at 10-SEP-04
 
RMAN> 


3) 이중 백업세트
다중 백업세트가 여러 개의 파일들을 하나의 백업세트로 구성하는 방법인데 반하여, 
이중백업세트는 하나의 파일을 여러 개의 백업세트로 나누는 방법을 의미한다.
BACKUP 명령어와 함께 COPIES 키워드가 하나의 데이터 파일을 몇 개의 조각으로 나눌 것인지를 지정한다. 
DATAFILE n 키워드는 대상 데이터 파일의 파일 번호이며, 
번호는 DBA_DATA_FILES 자료사전에서 확인할 수 있다.
【예제】
SQL> connect system/manager
Connected.
SQL> select file_name,file_id from dba_data_files;
 
FILE_NAME                                             FILE_ID
------------------------------------------------- ----------
/export/home/oracle/oradata/jinpo/system01.dbf            1
/export/home/oracle/oradata/jinpo/undotbs01.dbf           2
/export/home/oracle/oradata/jinpo/cwmlite01.dbf           3
export/home/oracle/oradata/jinpo/drsys01.dbf              4
/export/home/oracle/oradata/jinpo/example01.dbf           5
/export/home/oracle/oradata/jinpo/indx01.dbf              6
/export/home/oracle/oradata/jinpo/odm01.dbf               7
/export/home/oracle/oradata/jinpo/tools01.dbf             8
/export/home/oracle/oradata/jinpo/users01.dbf             9
/export/home/oracle/oradata/jinpo/xdb01.dbf              10
 
10 rows selected.
 
SQL> exit
$ rman target rman/rman
 
Recovery Manager Release 9.2.0.1.0 - 64bit Production
Copyright (c) 1995, 2002, Oracle Corporation.  All rights reserved.
connected to target database JINPO (DBID=785004453)
 
RMAN> BACKUP COPIES 2 DATAFILE 5;
 
Starting backup at 10-SEP-04
using target database controlfile instead of recovery catalog
allocated channel ORA_DISK_1
channel ORA_DISK_1 sid=9 devtype=DISK
channel ORA_DISK_1 starting full datafile backupset
channel ORA_DISK_1 specifying datafile(s) in backupset
input datafile fno=00005 name=/export/home/oracle/oradata/jinpo/example01.dbf
channel ORA_DISK_1 starting piece 1 at 10-SEP-04
channel ORA_DISK_1 finished piece 1 at 10-SEP-04 with 2 copies
piece handle=/export/home/oracle/app/oracle/product/9.2.0/dbs/03fvkhdm_1_1 comment=NONE
piece handle=/export/home/oracle/app/oracle/product/9.2.0/dbs/03fvkhdm_1_2 comment=NONE
channel ORA_DISK_1 backup set complete, elapsed time: 00:01:15
Finished backup at 10-SEP-04
 
RMAN> 


4) Backup 명령어
rman 유틸리티 프롬프트에서 사용하는 backup 명령어와 그 옵션은 다음과 같다.
【형식】
     BACKUP [BACKUP-TYPE] [옵션]

여기서 BACKUP-TYPE의 종류는 다음과 같다.
DATABASE데이터베이스 전체를 백업한다.
TABLESPACE ‘테이블스페이스명’ 지정한 테이블스페이스만 백업한다.
DATAFILE ‘파일명’ 특정 데이터 파일만 백업한다.
DATAFILECOPY ‘파일명’ 지정한 데이터파일을 복사하여 백업한다.
ARCHIVELOG ALL 백업시 모든 아카이브 파일도 함께 백업한다.
CURRENT CONTROLFILE 백업시 현재 컨트롤 파일도 함께 백업한다.
CONTROLFILECOPY ‘파일명’ 현재 컨트롤 파일을 복사하여 백업한다.
옵션의 종류는 다음과 같다.
TAG=‘내용’ 현재 백업절차에 대한 주석을 작성
FILESPERSET=n 백업조각의 수를 지정
DELETE INPUT 백업 후 아카이브 파일들을 삭제
FORMAT = ‘파일 경로와 파일명’ 백업파일의 경로와 파일명을 지정
다음은 자동으로 파일명을 지정하는 와일드카드는 다음과 같다.
%P 백업세트 내의 백업조각 번호
%S 백업세트번호
%D 대상 데이터베이스명
%N 대상 데이터베이스의 다른 표시이름
%T 초단위 시간 정보
%U 백업세트와 시간정보로 된 8문자
V$BACKUP_SET 자료사전을 참조해보면 현재 생성되어 있는 백업세트의 개수와 각 백업세트의 블록 크기를 알 수 있으며, 또한 V$BACKUP_PIECE 자료사전을 보면 백업세트의 경로와 파일명을 알 수 있다. 【예제】 SQL> connect system/manager Connected. SQL> select recid, block_size from v$backup_set; RECID BLOCK_SIZE ---------- ---------- 1 8192 2 512 3 8192 SQL> col handle format a65; SQL> select recid,set_count,piece#, handle from v$backup_piece; RECID SET_COUNT PIECE# HANDLE ---------- ---------- ---------- ----------------------- 1 1 1 /export/home/oracle/app/oracle/product/9.2.0/dbs/01fvkg11_1_1 2 2 1 /export/home/oracle/app/oracle/product/9.2.0/dbs/02fvkg84_1_1 3 3 1 /export/home/oracle/app/oracle/product/9.2.0/dbs/03fvkhdm_1_1 4 3 1 /export/home/oracle/app/oracle/product/9.2.0/dbs/03fvkhdm_1_2 SQL> 5) 컨트롤 파일의 자동 백업 rman 유틸리티에서 configure 명령으로 컨트롤 파일을 자동 백업하고 똑 같은 복사 본을 사용자가 지정하는 경로에 지정한 파일 명으로 백업할 수 있다. CONFIGURE CONTROLFILE AUTOBACKUP ON 명령을 실행하면 컨트롤 파일의 정보가 변경 될 때마다 채널 할당시 설정한 기본 백업경로에 백업해 준다. 또한 CONFIGURE SNAPSHOT CONTROLFILE NAME TO ‘경로와 파일명’ 명령으로 실행하면 지정된 경로와 파일명으로 컨트롤 파일을 백업해 준다. 【예제】 $ rman target rman/rman Recovery Manager Release 9.2.0.1.0 - 64bit Production Copyright (c) 1995, 2002, Oracle Corporation. All rights reserved. connected to target database JINPO (DBID=785004453) RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON; using target database controlfile instead of recovery catalog new RMAN configuration parameters CONFIGURE CONTROLFILE AUTOBACKUP ON; new RMAN configuration parameters are successfully stored RMAN> CONFIGURE SNAPSHOT CONTROLFILE NAME TO 'joe_contrpl'; snapshot controlfile name set to joe_contrpl new RMAN configuration parameters are successfully stored RMAN> 참조: dbv 유틸리티를 사용하여 백업된 데이터가 깨졌는지 확인할 수 있다.
Posted by 1010
02.Oracle/DataBase2009. 6. 27. 10:51
반응형
출처: http://www.dbguide.net/oracle11g_guide/oracle11g_guide_10.jsp

간략한 개요

Oracle Database 11g는 패스워드 대소문자 구분, Transparent Tablespace Encryption, UTL_TCP/HTTP/SMTP를 위한 액세스 컨트롤 리스트 등 다양한 보안 관련 신기능을 제공합니다.

디폴트 패스워드

2006년에 게시된 OTN 아티클 "프로젝트 락다운: 데이터베이스 인프라스트럭처의 보안을 위한 단계별 접근법(한글)"에서, 필자는 디폴트 패스워드의 사용, 데이터베이스 스캔과 같은 보안 문제를 해결하기 위한 방안을 설명한 바 있습니다.


이제 이 아티클 내용의 일부는 이제 더 이상 참고할 필요가 없게 되었습니다. Oracle Database 11g는 DBA_USERS_WITH_DEFPWD 데이터 딕셔너리 뷰를 조회하는 기막힐 정도로 간단한 방법으로 디폴트 패스워드를 사용 중인 사용자들을 신속하게 확인할 수 있는 기능을 제공합니다. (DBA_는 표준 접두어로, 이 뷰가 DBA 사용자들의 정보만을 포함하고 있음을 의미하는 것은 아닙니다.) 디폴트 패스워드를 사용 중인 사용자 목록을 확인하는 방법이 아래와 같습니다:


select *
from dba_users_with_defpwd


실행 결과는 아래와 같습니다:


USERNAME
------------------------------
DIP
MDSYS
WK_TEST
CTXSYS
OLAPSYS
OUTLN
EXFSYS
SCOTT
MDDATA
ORDPLUGINS
ORDSYS
XDB
LBACSYS
SI_INFORMTN_SCHEMA
WMSYS


위에서 디폴트 패스워드인 TIGER가 사용되고 있는 SCOTT 사용자를 확인할 수 있습니다. 아래와 같이 변경해 줍니다:


SQL> alter user scott identified by tiger1;
User altered.


이제 다시 뷰를 확인해 보면


SQL> select * from dba_users_with_defpwd;


SCOTT가 리스트에서 사라진 것을 확인할 수 있습니다. 아주 간단합니다!


패스워드의 대소문자 구분

Oracle Database 11g 이전 버전에서는 사용자 패스워드의 대소문자 구분은 지원되지 않았습니다. 예를 들자면 아래와 같습니다:


SQL> conn scott/tiger
Connected.
SQL> conn scott/TIGER
Connected.


하지만 이는 패스워드의 대소문자 구분을 요구하는 PCI(Payment Card Industry) 데이터 보안 표준과 같은 업계 표준에 위배되는 것이어서 많은 문제의 소지가 있었습니다.


Oracle Database 11g는 패스워드의 대소문자 구분을 지원합니다. DBCA를 통해 데이터베이스를 생성하는 과정에서, 오라클 데이터베이스는 "새로운 보안 표준"으로 업그레이드할 것인지의 여부를 묻습니다. 이 보안 표준에는 패스워드의 대소문자 구분이 포함되어 있습니다. 업그레이드를 승인하면, 패스워드는 최초 생성된 것과 동일한 대/소문자 단위로 저장됩니다. 새로운 보안 표준을 승인한 경우 아래와 같은 실행 결과를 확인할 수 있습니다:


SQL> conn scott/tiger
Connected.
SQL> conn scott/TIGER
ERROR:
ORA-01017: invalid username/password; logon denied

Warning: You are no longer connected to ORACLE.


"tiger"와 "TIGER"가 다르게 취급되는 것을 확인할 수 있습니다.


하지만 애플리케이션 중 일부는 패스워드를 전달할 때 올바른 대소문자 구분을 사용하지 않고 있을 수 있습니다. 대표적인 예가 사용자 입력 폼입니다. 사용자 입력 폼에서 패스워드를 입력 받으면서 대소문자 변환을 전혀 수행하지 않는 경우가 많습니다. Oracle Database 11g에서 대소문자를 구분한 포맷으로 사용자가 패스워드를 입력하거나, 애플리케이션에서 대소문자 변환을 수행하도록 개발자가 바꾸어 주지 않는 이상 로그인이 실패할 가능성이 있습니다.


필요하다면 아래와 같이 SEC_CASE_SENSITIVE_LOGON 시스템 매개변수를 변경하여 대소문자를 구분하지 않는 체제로 변환하는 것도 가능합니다.


SQL> conn / as sysdba
Connected.
SQL> alter system set sec_case_sensitive_logon = false;

System altered.

SQL> conn scott/TIGER
Connected.


기존의 Oracle 10g 데이터베이스를 11g로 업그레이드하는 경우에는 패스워드를 새로운 표준으로 마이그레이션 할 수 있습니다. 패스워드의 상태는 DBA_USERS 뷰의 PASSWORD_VERSIONS 컬럼을 통해 확인할 수 있습니다.



위에서 패스워드 컬럼이 NULL로 설정되어 있음을 확인할 수 있습니다. Oracle Database 10g 또는 그 이전 버전에서는 여기에 해쉬 값이 저장되어 있습니다. 그렇다면 패스워드는 어디로 간 것일까요? 패스워드는 여전히 데이터베이스(USER$ 테이블)에 저장되어 있지만 DBA_USERS 뷰를 통해서는 조회될 수 없습니다. 사용자가 글로벌하게 또는 외부 인증을 통해 생성된 경우, GLOBAL, EXTERNAL과 같이 상태 정보가 나타나지만 패스워드의 해쉬 값은 표시되지 않습니다.


다음으로, Oracle Database 11g에 새로 추가된 PASSWORD_VERSIONS 컬럼에 주목하시기 바랍니다. 이 컬럼은 패스워드의 대소문자 구분 여부를 표시합니다. "10G 11G"의 값은 사용자가 10g에서 생성되어 11g로 마이그레이션 되었거나 11g에서 직접 생성되었음을 의미합니다.


원한다면 패스워드 파일을 생성하는 과정에서 새로운 매개변수인 ignorecase를 입력하여 SYSDBA 패스워드도 대소문자를 구분하도록 강제할 수 있습니다.


$ orapwd file=orapwPRODB3 password=abc123 entries=10 ignorecase=n


위의 예제에서 SYSDBA 패스워드는 abc123이며, ABC123은 허용되지 않습니다.


패스워드의 대소문자 구분은 외부 침입자에 의한 패스워드 해킹을 더욱 어렵게 만듭니다. 또 법규 준수를 보장할 수 있다는 이점도 있습니다. 더욱 중요한 사실은, 데이터베이스 셧다운 과정을 거치지 않고도 패스워드의 대소문자 구분 설정을 다이내믹하게 변경할 수 있다는 사실입니다. 이 기능은 레거시 애플리케이션을 업그레이드하면서 발생할 수 있는 로그인 문제를 해결하는데 큰 도움이 됩니다.


프로파일, 패스워드 검증 함수

오라클 데이터베이스가 제공하는 패스워드 검증 함수에 대해 알고 계십니까? 여러분들 중 상당수가 그 존재조차도 모르고 계시리라 짐작합니다. 이 함수는 데이터베이스 패스워드의 품질을 확인하는 가장 쉽고 빠른 방법을 제공합니다. 예를 들어 패스워드가 일정한 수 이상의 문자로 구성되었는지, 유저네임과 동일하지는 않은지 등을 확인할 수 있습니다. 또 기능이 기본 내장되어 있으므로 활성화 작업만 거치면 함수를 사용할 수 있습니다.


Oracle Database 11g의 패스워드 관리 함수는 한층 개선된 검증 로직을 제공합니다. $ORACLE_HOME/rdbms/admin 디렉토리의 utlpwdmg.sql 패스워드 검증 파일은 verify_fnction_11g라는 새로운 패스워드 함수를 생성합니다. 이 스크립트의 하단에서 아래와 같은 코드를 확인할 수 있습니다:


ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME 180
PASSWORD_GRACE_TIME 7
PASSWORD_REUSE_TIME UNLIMITED
PASSWORD_REUSE_MAX UNLIMITED
FAILED_LOGIN_ATTEMPTS 10
PASSWORD_LOCK_TIME 1
PASSWORD_VERIFY_FUNCTION verify_function_11G;


이 스크립트는 DEFAULT 프로파일에 이 스크립트는 DEFAULT 프로파일에 함수를 연결합니다. DEFAULT는 (별도로 명시되지 않는 이상) 모든 사용자를 위한 디폴트 프로파일로 설정되어 있습니다. 이러한 방법으로 인증 체계에 관련된 법규 준수를 보장할 수 있습니다. 패스워드 검증 함수의 11g 버전을 생성하는 스크립트를 실행하기만 하면, 스크립트가 디폴트 프로파일에 자동으로 연결되고 패스워드 검증 기능이 활성화됩니다.



개선된 감사 기능

감사 문제 역시 관리자들의 골칫거리 중 하나입니다. 오라클 데이터베이스는 사용자 작업의 추적을 위한 강력한 감사 기능을 제공합니다. 하지만 대부분의 사용자들은 I/O 성능 저하를 우려하여 감사 기능을 적용하지 않고 있습니다. 하지만 실제로는 일부 감사 기능은 활성화하더라도 성능 오버헤드를 우려할 필요가 없습니다.


그 한 가지 예가 CREATE SESSION입니다. CREATE SESSION은 세션이 시작될 때, 그리고 종료될 때 한 번씩 기록을 저장합니다. 이 감사 옵션은 I/O에 미치는 영향은 극히 미미하지만 그 혜택은 매우 강력합니다.


Oracle Database 11g에서는 한층 강력한 감사 솔루션의 구현을 가능하게 하는 두 가지 간단한 변경 사항이 적용되었습니다. 먼저, 데이터베이스 매개변수 audit_trail이 디폴트로 NONE이 아닌 DB로 설정되어 있습니다. 따라서 데이터베이스를 재시작하지 않고도 임의의 오브젝트, 구문, 권한에 대한 감사 기능을 활성화하는 것이 가능합니다.


두 번째로 디폴트 설정에서 감사 대상에 포함되는 구문의 종류가 많아졌습니다. 그 목록이 아래와 같습니다.


ALTER SYSTEM
SYSTEM AUDIT
CREATE SESSION
CREATE USER
ALTER USER
DROP USER
ROLE
CREATE ANY TABLE
ALTER ANY TABLE
DROP ANY TABLE
CREATE PUBLIC DATABASE LINK
GRANT ANY ROLE
ALTER DATABASE
CREATE ANY PROCEDURE
ALTER ANY PROCEDURE
DROP ANY PROCEDURE
ALTER PROFILE
DROP PROFILE
GRANT ANY PRIVILEGE
CREATE ANY LIBRARY
EXEMPT ACCESS POLICY
GRANT ANY OBJECT PRIVILEGE
CREATE ANY JOB
CREATE EXTERNAL JOB


위의 작업들을 감사 대상에 포함시키더라도 I/O는 크게 증가하지 않으며, 따라서 성능 오버헤드를 최소화한 상태에서 합리적인 수준의 감사를 수행할 수 있습니다.


이 두 가지 변경 사항 덕분에 별도의 설정 작업을 거치지 않고도 강력한 감사 기능을 활용할 수 있게 되었습니다. 물론 이것은 단순한 데이터베이스 매개변수와 감사 설정에 불과하며, 필요한 경우 쉽게 비활성화할 수 있습니다. 하지만 구문 리스트를 주의 깊게 살펴 본다면, 심지어 개발 데이터베이스에서도 감사가 필요할 수 있음을 깨닫게 될 것입니다. 물론 좀 더 세부적인 튜닝은 필요할 수 있습니다. (예를 들어, 데이터 웨어하우스 환경에서는 사용자들이 많은 수의 임시 테이블을 생성, 삭제하므로 CREATE/DROP TABLE에 대한 감사가 성능 문제를 발생시킬 수 있습니다.)


주의: Oracle Database 11g로 업그레이드한 경우, 위에서 언급된 구문에 대해 감사 기능이 기본적으로 활성화됩니다. 감사 로그는 SYSTEM 테이블스페이스의 AUD$ 테이블에 저장되며 매우 빠른 속도로 차오를 수 있습니다. 이 공간에 대한 감시를 게을리 하지 마십시오.


Transparent Tablespace의 암호화

보안과 관련한 새로운 법규들이 제정되면서, 암호화 기능에 대한 관심이 점점 더 증가하고 있습니다. 데이터에 대한 암호화는 필요합니다. 하지만 정말 중요한 것은 어떻게 암호화할 것인가의 문제입니다.


Oracle Database 10g Release 1 또는 그 이전 버전에서는 DBMS_CRYPTO, DBMS_OBFUSCATION_TOOLKIT 툴킷을 이용하여 암호화 프레임워크를 직접 구현할 수 있었습니다. 하지만 Oracle Database 10g Release 2의 Transparent Data Encryption 기능이 소개되면서 이 프레임워크는 용도폐기 되어 버렸습니다.


Transparent Data Encryption 기능을 이용하면 특정 컬럼을 선택적으로 암호화하는 것이 가능합니다. 하지만 이 기능은 성능과 관련된 문제를 갖고 있습니다. 암호화된 컬럼에는 인덱스 레인지 스캔이 적용될 수 없으므로 성능이 심각하게 저하될 수 있습니다.


Oracle Database 11g의 Transparent Tablespace Encryption 기능이 돋보이는 것은 바로 이러한 이유 때문입니다. 테이블스페이스가 암호화된 것으로 선언되면, 테이블뿐 아니라 테이블스페이스 내의 모든 데이터(Transportable Tablespace, 백업 포함)가 암호화됩니다. 하지만 인덱스 스캐닝 작업은 데이터가 해독된 메모리 공간에서 실행되므로 성능 저하 문제는 발생하지 않습니다.


아직 감이 안 잡히셨습니까? 그 동작 원리에 대해 좀 더 알아 봅시다. 암호화 프로시저는 Transparent Data Encryption의 경우와 동일합니다. 이를 위해 마스터 암호화 키가 저장되는 월렛(wallet)을 생성해야 합니다. Transparent Data Encryption이 셋업 되지 않은 상태라면 월렛과 키를 생성해 주어야 합니다.


먼저, 월렛이 저장될 디렉토리를 생성합니다. 디폴트 디렉토리는 $ORACLE_BASE/admin//wallet입니다. 월렛 서브디렉토리는 디폴트 상태에서는 존재하지 않으므로 별도로 생성해 주어야 합니다. 아래의 예제에서는 /home/oracle/app/admin/PRODB3/wallet을 디렉토리로 선택하였습니다.


다음으로 아래 구문을 실행하여 월렛에 암호화 키를 생성합니다.


alter system set encryption key identified by "abcd1234!";

이 구문은 월렛과 키를 함께 생성해 줍니다. 이제 디렉토리를 조회하면 방금 생성한 월렛 파일(ewallet.p12)을 확인할 수 있습니다.


$ cd /home/oracle/app/admin/PRODB3/wallet
$ ls
ewallet.p12


월렛은 패스워드(abcd1234)를 사용해서만 열 수 있습니다. 이 구문은 월렛을 여는 작업도 함께 수행합니다. 따라서 월렛을 별도로 생성할 필요가 없습니다. 데이터베이스가 기동되고 나면 아래 구문을 실행하여 월렛을 열기만 하면 됩니다:


alter system set wallet open identified by "abcd1234!"


월렛에 관련한 자세한 정보는 다른 오라클 매거진 아티클에서 확인하실 수 있습니다.


이제 테이블스페이스를 생성합니다:


create tablespace secure1
datafile '/home/oracle/oradata/PRODB3/secure1_01.dbf'
size 1M
encryption using 'AES128'
default storage (encrypt)
/


"encryption using ... default storage (encrypt)" 구문은 테이블스페이스를 암호화된 상태로 선언합니다. (참고: 이 테이블스페이스에는 AES 128비트 암호화가 적용되었습니다. 그 밖에도 Triple DES 168-bit key, AES 192-bit key, AES 256-bit key 등의 옵션이 제공됩니다.)


테이블스페이스를 생성한 다음에는 다른 테이블스페이스의 경우와 마찬가지 방법으로 테이블을 생성할 수 있습니다.


create table secure_trans
tablespace secure1
as
select * from trans
where rownum < 201
/

create table secure_res
tablespace secure1
as
select * from res
where rownum < 201
/


위 구문은 암호화된 테이블스페이스 SECURE1에 테이블을 생성하고 있습니다. 비교를 위해 암호화가 적용되지 않은 테이블스페이스 INSECURE1을 생성하고 이 안에 SECURE_TRANS, INSECURE_RES 테이블을 생성합니다. INSECURE_TRANS 테이블과 SECURE_TRANS 테이블은 그 구조가 동일하며 다른 테이블스페이스에 저장되었다는 차이만을 갖습니다. SECURE_RES, INSECURE_RES의 경우도 마찬가지입니다.


이제 데이터파일 검색에 사용할 데이터를 테이블의 텍스트 필드를 업데이트합니다:


update secure_trans set comments = 'Transaction Comments';
update insecure_trans set comments = 'Transaction Comments';
commit;


테이블스페이스를 오프라인/온라인 처리하여 컨텐트가 디스크에 기록되도록 합니다:


alter tablespace secure1 offline;
alter tablespace secure1 online;
alter tablespace insecure1 offline;
alter tablespace insecure1 online;


이제 캐시의 데이터가 디스크에 기록되었습니다. 여기서 검색을 수행하면 어떤 결과를 얻게 될까요?


$ strings insecure1_01.dbf | grep Transaction
Transaction Comments
...


문자열은 데이터파일에 일반 텍스트로 저장되어 있습니다. 이제 같은 작업을 암호화된 SECURE1 테이블스페이스에 반복합니다.

$ strings secure1_01.dbf | grep Transaction
$


데이터파일이 암호화되었기 때문에 아무것도 반환되지 않습니다. 또 컬럼의 값을 일반 텍스트 포맷으로 조회할 수도 없습니다. 여기까지는 좋습니다. 그렇다면 성능은 어떨까요? 아래 쿼리를 실행해서 테스트해 봅시다.


select hotel_id, sum(amt)
from secure_trans t, secure_res r
where t.res_id = r.res_id
group by hotel_id


쿼리를 실행하면서 트레이스를 걸어 보겠습니다. 아래는 트레이스파일에서 발췌한 정보입니다.



Now, run the same test against INSECURE_RES and INSECURE_TEST, which are on a normal (unencrypted) tablespace.



양쪽의 실행 시간이 거의 차이가 없습니다. 암호 해독으로 인한 CPU 사용량도 그리 많지 않습니다. 따라서 테이블스페이스의 암호화로 인한 성능 영향은 거의 없다는 결론을 내릴 수 있습니다.


DBA_TABLESPACES 뷰에 새로 추가된 ENCRYPTED 컬럼은 테이블스페이스의 암호화 정보를 제공합니다. 또 새로운 뷰 V$ENCRYPTED_TABLESPACES를 이용하면 테이블스페이스를 위해 어떤 종류의 암호화 기능이 활성화 되었는지 확인할 수 있습니다.



이 뷰를 V$TABLESPACE 뷰의 TS# 컬럼과 조인하면 전체 그림을 한 눈에 파악할 수 있습니다. V$TABLESPACE 뷰의 구조가 아래와 같습니다:



여기서 ENCRYPT_IN_BACKUP 컬럼은 Transparent Tablespace Encryption과 전혀 무관하다는 점을 참고하시기 바랍니다. 이 컬럼은 Oracle Database 10g Release 2에서 처음 소개된, 백업 과정에서 RMAN이 제공하는 테이블스페이스 암호화 기능과 연관되어 있습니다.


지금까지 확인한 것처럼 Transparent Tablespace Encryption은 꽤 우아한 방법으로 두 가지 문제를 해결해 줍니다. 데이터 관리가 SGA 내부에서 수행되기 때문에 디스크에 저장된 암호화된 데이터는 성능 저하 문제를 동반하지 않습니다.


Data Pump 덤프파일의 암호화

Oracle Database 10g는 데이터 이동을 위한 가장 강력한 툴, Data Pump 제공합니다. Data Pump는 기존에 제공되던 export/import 툴을 대체하는 역할을 합니다. Data Pump는 그 전송 속도가 매우 빠를 뿐 아니라 프로세스의 병렬화, 테이블스페이스의 리매핑과 같은 다양한 신기능을 제공합니다. Oracle Database 11g에서는 ENCRYPTION이라는 새로운 매개변수를 통해 덤프파일의 보안을 한층 강화할 수 있게 되었습니다..


덤프파일은 데이터베이스 외부에 존재하며 데이터베이스의 보안 범위에 포함되지 않습니다. 이 때문에 보안과 관련한 여러 가지 문제들이 발생할 수 있습니다. 보안에 민감한 일부 기업 환경에서는 DBA들이 데이터의 익스포트 작업 이후 써드 파티 유틸리티를 이용하여 덤프파일을 암호화하는 절차를 거칩니다. 하지만 익스포트 데이터의 양이 많다면 무척 번거로운 작업이 될 것입니다.


일반적인 덤프파일이 얼마나 보안에 취약할 수 있는지 한 번 알아 보기로 합시다. 여기 COMMENTS라는 이름의 컬럼을 포함하는 TRANS 테이블이 있습니다. 이 컬럼에는 "Transaction Comments"라는 값이 저장되어 있습니다. 이 테이블을 아래와 같이 일반적인 방법으로 익스포트 했습니다:


$ expdp scott/tiger tables=trans dumpfile=insec.dmp directory=tmp_dir

덤프파일에서 컬럼 값을 조회하면:


$ strings /tmp/insec.dmp | grep Transaction


검색 조건에 매치되는 텍스트가 여럿 발견됩니다. 따라서 덤프파일의 데이터는 암호화되지 않은 일반 텍스트임을 알 수 있습니다.

이제 11g에 새로 추가된 매개변수 ENCRYPTION을 이용하여 익스포트 작업을 수행해 봅시다. 이때 사용할 알고리즘의 타입도 함께 지정해 주어야 합니다. 여기서는 AES 128비트 알고리즘을 사용하기로 하겠습니다.



이 덤프파일에 대해 텍스트 문자열을 검색해 보겠습니다


$ cat /tmp/sec.dmp | grep Transaction
$


덤프파일의 값이 암호화되어 있기 때문에 검색 결과가 전혀 표시되지 않습니다.


여기서 여러분들은 이렇게 질문할지도 모릅니다. "하지만 암호화에는 키가 필요하지 않나요? 앞 과정에서 키를 입력한 적이 없는데요? 키가 없는 상태에서 암호화된 데이터를 해독할 수 있는 건가요?"


해답은 아주 간단합니다. 바로 앞에서 설명한 Transparent Tablespace Encryption의 월렛의 키가 사용됩니다. Data Pump 암호화에서 Transparent Tablespace Encryption 기능을 이용할 필요는 없습니다. 하지만 월렛 생성을 위한 과정은 거쳐야 합니다. 말할 필요도 없는 사실이지만 월렛은 암호화/해독 과정에서 열 수 있어야 합니다.


Data Pump 툴 사용에 익숙한 사용자분들이라면 ENCRYPTION_PASSWORD 매개 변수를 통해 이와 유사한 기능이 제공되었음을 기억하실 것입니다. 그렇다면 과거에 제공되던 기능과 어떻게 다른 것일까요?


네, 좋은 질문입니다. 10g 버전은 전체 덤프파일을 암호화하는 것이 아니라, Transparent Data Encryption의 적용을 받는 컬럼만을 암호화합니다. Transparent Data Encryption을 사용하지 않고 있다면 덤프파일은 전혀 암호화되지 않습니다. 11g 버전에서는 Transparent Data Encryption의 사용 여부에 관계없이 전체 덤프파일을 암호화하는 것이 가능합니다. 이처럼 11g 버전의 암호화 기능이 훨씬 유연하고 실용적임을 알 수 있습니다. 사용자들은 성능과 같은 여러 가지 이유로 데이터베이스에 저장된 데이터를 직접 암호화하는 것을 원하지 않을 수 있습니다. 하지만 데이터베이스의 외부에 저장되는 데이터라면 암호화하는 것이 바람직합니다. 이런 경우에 Data Pump 암호화 기능은 매우 요긴하게 활용될 것입니다.


UTL_TCP/HTTP/SMTP를 위한 액세스 컨트롤 리스트

UTL_TCP, UTL_HTTP, UTL_SMTP 패키지에 대해 이미 알고 계신 분들이 많을 것입니다. 이 패키지들은 데이터베이스 외부의 서버들과의 커뮤니케이션을 위해 사용됩니다. 예를 들어, utl_tcp는 데이터베이스 링크를 통하지 않고 2대의 호스트 간에 TCP/IP 커뮤니케이션을 설정하는데 활용됩니다. 마찬가지로, utl_http는 웹 서버에 대해 http 요청을 생성하는 용도로, utl_smtp는 호스트 간의 SMTP 메일 호출을 위해 사용됩니다.


이 패키지들은 개발자들에 의해 주로 활용됩니다. 예를 들어, utl_smtp는 데이터베이스 내에서 이메일을 전송하는데, utl_http는 PL/SQL 프로그램 내부에서 웹 페이지를 처리하는 데 활용되곤 합니다. 하지만 이러한 툴들은 심각한 보안 리스크를 수반합니다. utl_tcp를 이용하는 데이터베이스에서 사용자는 시스템 프롬프트를 거치지 않고도 데이터베이스의 접근이 허용되는 다른 호스트로 쉽게 접속할 수 있습니다. 이는, 불과 1년 전 오라클 사용자 커뮤니티에 대혼란을 초래한 보이저(Voyager) 웜이 사용한 공격 수법이었습니다.


이러한 리스크를 해결하기 위해, 많은 전문가들은 이 패키지들의 "execute from public" 권한을 삭제할 것을 권고하고 있습니다. 필자 역시 OTN 프로젝트 락다운 시리즈 아티클을 통해 같은 방법을 권장한 바 있습니다. 하지만 개발자들이 이 패키지들을 꼭 실행해야 하는 상황이라면 어떻게 해야 할까요?


Oracle Database 11g는 이를 위한 참신한 해법을 제공합니다. 바로 실행 권한을 모든 사용자에게 허용하되, 호출 가능한 리소스를 통제하는 방법입니다. 예를 들어, utl_tcp 패키지에서 일부 IP 주소만을 호출할 수 있도록 제한할 수 있습니다. 이러한 메커니즘을 액세스 컨트롤 리스트(ACL)라 부릅니다. 사용자는 utl_tcp의 실행 권한을 갖고 있다 하더라도, 호스트가 ACL에 등록된 경우에만 해당 호스트에 연결할 수 있습니다. 따라서 utl_tcp 패키지를 이용한 악성 프로그램의 접근 시도를 원천적으로 차단할 수 있습니다.


그 동작 원리를 살펴 봅시다. 먼저 ACL을 생성합니다:



'CONNECT' 매개변수는 ACL이 CONNECT 역할에 적용됨을 의미합니다. 이곳에서 사용자 또는 역할을 정의할 수 있습니다. ACL은 utlpkg.xml 파일 내에 생성됩니다.


생성 작업을 완료한 후 아래와 같은 방법으로 ACL이 추가되었는지 확인할 수 있습니다:


SELECT any_path
FROM resource_view
WHERE any_path like '/sys/acls/%.xml';


실행 결과가 아래와 같습니다:



출력의 마지막 라인에서 방금 생성된 ACL을 확인할 수 있습니다. 다음으로, 이 ACL에 권한을 추가해 줍니다. 예제에서는 SCOTT 사용자만이 이 ACL을 사용할 수 있도록 제한합니다. 또 시작, 종료일도 정의가 가능합니다.



이 ACL에 관련된 호스트 및 기타 상세 정보를 적용합니다:



위의 코드는 "사용자 SCOTT은 호스트 www.proligence.com에만 접속할 수 있으며 포트 22에서 55 사이만을 사용할 수 있음"을 의미합니다. 이제 테스트해 봅시다:


SQL> grant execute on utl_http to scott
2 /

Grant succeeded.

SQL> conn scott/tiger
Connected.
SQL> select utl_http.request('http://www.proligence.com') from dual;
select utl_http.request('http://www.proligence.com') from dual
*
ERROR at line 1:
ORA-29273: HTTP request failed
ORA-06512: at "SYS.UTL_HTTP", line 1577
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at line 1

Note the error "ORA-24247: network access denied by access control list (ACL)." The user called the http server on port 80, which is outside the allowed range 22-55. Therefore the action was prevented.


문제를 해결하기 위해 새로운 룰을 추가해 봅시다:


1 begin
2 dbms_network_acl_admin.assign_acl (
3 acl => 'utlpkg.xml',
4 host => 'www.proligence.com',
5 lower_port => 1,
6 upper_port => 10000);
7* end;
8 /

PL/SQL procedure successfully completed.

SQL> conn scott/tiger
Connected.
SQL> select utl_http.request('http://www.proligence.com') from dual;

UTL_HTTP.REQUEST('HTTP://WWW.PROLIGENCE.COM')
--------------------------------------------------------------------------------
</iframe><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


<HTML><HEAD><TITLE>Proligence Home</TITLE>
<META http-equiv=Content-Language content=en-us>
...


위 룰은 www.proligence.com 호스트에 대해서만 접근 허용됩니다. 다른 웹 사이트를 호출하면 ORA-24247 에러와 함께 실패할 것입니다. 이는 매우 세분화된 보안 정책이 적용된 것으로 볼 수 있습니다. 호스트 www.proligence.com에 접속해야 할 비즈니스 상의 이유가 있다면, 이 호스트만 허용하고 다른 호스트에 대한 접근은 차단함으로써 악성 사용자의 접근 시도를 통제할 수 있습니다.


ACL의 상세 정보를 확인하려면 DBA_NETWORK_ACLS 뷰를 조회합니다:



필자의 의견으로는 이 기능이야 말로 Oracle Database 11g에서 최고로 손꼽을 만한 보안 기능이 아닐까 합니다.


데이터 마스킹

많은 기업들이 수시로 운영 데이터베이스의 이미지를 스테이징 또는 QA 데이터베이스에 업데이트함으로써, 개발자들이 운영 시스템과 유사한 환경에서 개발된 코드를 테스트하도록 하고 있습니다. 하지만 이러한 절차에는 잠재적인 보안 문제가 수반됩니다. 운영 데이터베이스의 내용이 QA 데이터베이스와 동기화될 때 민감한 개인 정보가 유출될 수 있기 때문입니다. 이러한 리스크를 해결하기 위해, 많은 기업들이 중요한 데이터들을 의미 없는 값으로 대체하는 방법을 사용하고 있습니다. 이러한 방법을 데이터 마스킹(data masking)이라 부릅니다. 예를 들어, 실제 사회보장번호를 입력하는 대신 9개의 무작위 숫자로 업데이트하는 방법이 사용됩니다.


하지만 실제로 변경하는 작업은 매우 까다로울 수 있습니다. SQL 스크립트를 직접 작성하고, 프로세스에 문제가 없는 지, 운영 시스템에 부담이 되지 않을지 등을 점검해야 합니다. 그렇다면 오라클 데이터베이스가 직접 데이터 임포트 작업을 관리할 수 있다면 좋지 않을까요? Oracle Database 11g에는 Data Pump의 임포트 과정에서 데이터 변경을 지원하기 위한 remap_data 매개변수가 새로 추가되었습니다.


이를 위해 먼저, 리매핑 함수를 생성합니다:



이 함수는 varchar 변수를 취한 후 9개의 문자를 반환합니다. 이 함수를 이용하여 SSN의 마스킹을 수행하도록 하겠습니다. ACCOUNTS 테이블은 다음과 같이 정의되어 있습니다.



계좌 소유자의 SSN 정보를 저장한 ACC_SSN 컬럼의 마스킹을 수행하고 합니다. 이제 Data Pump를 이용하여 테이블을 익스포트 합니다. 익스포트 과정에서 새로운 매개변수, remap_data를 이용하여 익스포트 덤프 파일의 데이터를 마스킹 처리합니다.

$ expdp scott/tiger tables=scott.accounts dumpfile=
accounts.dmp directory=tmp_dirremap_data=accounts.acc_ssn:pkg_mask.fn_mask_ssn

이 매개변수는 pkg_mask 패키지의 fn_mask_ssn 리매핑 함수로부터 생성된 값을 이용합니다. 매개변수의 포맷에 주의하시기 바랍니다. 매개변수는 다음과 같은 패턴을 갖습니다:


[.].:[.].


은 마스크 대상 컬럼의 이름입니다. 실제 리매핑 로직은 .에 위치하고 있습니다.



이제 개발 데이터베이스로 테이블을 임포트할 수 있습니다. 임포트 작업이 완료된 후 테이블의 데이터를 점검한 결과가 아래와 같습니다:

ACC_SSN 값이 달라져 있음을 확인할 수 있습니다. 이 값들은 앞에서 작성한 pkg_mask.fn_mask_ssn 리매핑 함수로부터 생성되어, 임포트 과정에서 함께 임포트된 것입니다.


remap_data 매개변수를 사용하지 않고 이미 테이블을 익스포트 처리했다면, 덤프파일에는 실제 값이 저장되어 있을 것입니다. 이런 경우에도 같은 매개변수를 사용하여 임포트 과정에서 마스킹을 수행할 수 있습니다.


$ impdp scott/tiger dumpfile=accounts.dmp remap_data=
accounts.acc_ssn:pkg_mask.fn_mask_ssn directory=tmp_dir tables=accounts

여기서는 randomizer 함수가 사용되고 있으며, 그 밖의 어떤 로직을 사용하더라도 무방합니다. 예를 들어, SSN의 마지막 4개 숫자를 X로 변환하는 방법도 가능합니다. 이를 위해 사용되는 함수는 아래와 같이 구현됩니다:



이 패키지 함수는 나중에 어떤 컬럼에서든 재활용이 가능하다는 이점이 있습니다.


기타 보안 기능

이전 버전에서는 대부분의 보안 작업이 Oracle Security Manage라는 툴을 통해 수행되었습니다. Oracle Database 11g의 Oracle Enterprise Manager는 이러한 작업을 수행하는데 필요한 모든 툴들을 제공하고 있습니다. OEM의 Database 홈페이지에 위치한 Server 탭의 스크린샷이 아래와 같습니다. 오른쪽 하단에 Security라는 이름의 섹션이 위치한 것을 확인하실 수 있습니다.



이 섹션은 사용자, 프로파일, 역할 관리 등의 프로세스에 관련한 전체 보안 관련 도구의 하이퍼링크를 제공하고 있습니다. 그 밖에도 Virtual Private Database, Oracle Label Security 등을 위한 마법사를 이용하거나 Enterprise Manager 스크린으로부터 애플리케이션 컨텍스트를 생성, 관리할 수 있습니다. "Oracle Database 11g: DBA와 개발자가 알고 있어야 하는 새로운 기능" 홈페이지로 돌아가기 

[출처] [오라클 11g] 보안|작성자 형기

Posted by 1010
90.개발관련문서2009. 6. 27. 01:45
반응형


지난 7일 행정안전부가 주최하고 한국정보문화진흥원이 주관한 2009년 상반기 웹 접근성 기술동향 및 향상방안 세미나가 있었습니다. 이날 부족한 제게도 기회가 주어져 발표를 할 있었고, 오늘 정보통신 접근성 향상 표준화 포럼을 통해서 발표 자료(PDF)가 공개되었습니다.

사실 이번 발표를 위해서 나름 준비를 열심히 했는데 막상 너무 큰 자리에 서다 보니 반쯤 얼어서 제대로 전달하려고 했던 내용의 반도 전달해 드리지 못한 것 같아 혼자 많이 속상해 했었습니다. 단상에서 내려오고 나니 빠뜨린 내용이 적지 않더군요. 그래서 발표용으로 작성했던 메모를 정리해서 이렇게 글로써 다시 '발표'를 하려고 합니다.


웹 개발자가 알아야할 웹 접근성이라는 주제를 받고, 한참을 고민했습니다. 지난 몇년간 있어온 여러번의 세미나를 통해서 몇번이고 반복되었던 내용들의 반복이 되고 싶지는 않았습니다.(결국은 그렇게 되었지만) 그래서 나름 고민을 거듭해서 3가지 수칙을 정하고, 그에 따라 내용을 붙여 보게 되었습니다. 첫번째 수칙은 ‘항상 공부하라’입니다. 우리가 필요로 하는 정보들이 어디에 있고, 어떻게 찾아 보면 좋을지를 알려드립니다. 두번째 수칙은 ‘습관을 버려라’입니다. 과거로부터 이어진 좋지 않은 개발 관행의 4가지 사례를 살펴보도록 하겠고, 세번째 수칙 ‘사람을 믿고, 기계를 의심하라’에서는 함께 일 하는 동료들과 에디터, 시스템 등 작업 환경에 대한 이야기를 하고자 합니다.

다음은 순서입니다:
  • 수칙 1. 항상 공부하라
    • 1.1 웹 표준 기술을 제대로 알고, 가까운 곳에 스펙을 둬라
    • 1.2 새로운 정보와 이슈를 놓치지 말라
  • 수칙 2. 습관을 버려라
  • 수칙 3. 사람을 믿고, 기계를 의심하라
    • 3.1 동료를 믿어라
    • 3.2 기계를 의심하라



수칙 1. 항상 공부하라

1.1 웹 표준 기술을 제대로 알고, 가까운 곳에 스펙을 둬라

제가 생각할 때 웹 개발자에게 있어서 웹 접근성 향상을 위해서 가장 중요한 것은 웹 표준 기술을 가장 잘 이해하고 사용하는 것입니다. 따라서 첫번째 수칙으로 ‘항상 공부하라’고 했습니다. 그리고 수칙 1-1로 ‘웹 표준 기술을 제대로 알고, 항상 가까운 곳에 스펙을 둬라’고 정해 보았습니다.

어떤 분들은 기억력이 좋으셔서 한 두번 본 내용을 곧 기억해 내십니다. 하지만 저는 그게 참 안되었습니다. 그래서 제 책상 위에는 W3C의 온갖 스펙이 출력되어 있고, 책 제본을 쌓여 있습니다. 그냥 아무렇게나 출력해 놓은 것들은 처음 한 번 이후에는 잘 보지 않게 되기도 하고, 쉽게 이면지함으로 들어가죠. 하지만 회사에 제본기가 한 대 있어서 스펙들을 한데 묶어 책으로 만들어 두시면 보기가 편할 뿐더러 보관에도 좋습니다. 그리고 브라우저의 즐겨찾기는 당연하겠죠. 의외로 많은 분들이 스펙과 관련된 궁금증을 풀기 위해서 커뮤니티 게시판을 이용합니다. 가장 먼저 스펙을 찾아보는 습관을 갖는 것이 좋습니다. 다음은 웹개발자들에게 필요한 주요 북마크입니다.
W3C에 권고안으로 공개된 표준 스펙 문서들과 MS, Mozilla, Opera가 운영하고 있는 레퍼런스 사이트들입니다. 실제로 찾아보시면 이보다 훨씬 더 많은 스펙 문서들과 레퍼런스 사이트들이 있습니다. 제 블로그를 통해서도 소개드린 것들이 있고, 정찬명님의 나라디자인 위키 페이지에서 UI개발자들을 위한 북마크를 운영하고 계시기도 합니다. 웹 개발자 분들께 유용한 자료가 될 것으로 생각됩니다.


1.2 새로운 정보와 이슈를 놓치지 말라

수칙 1.2는 '새로운 정보와 이슈를 놓치지 말라'입니다. 개발 분야 만큼 빠르게 새로운 정보와 이슈가 쏟아지는 분야도 드믈 것이라고 생각됩니다. 겨우 하나의 언어와 기술을 익혔는데 어느새 또 다른 언어가 나오고 방법론이 제시됩니다. 특히 웹이 대중화된 이후는 그 속도가 더욱 더 빨라지고 있는 추세입니다. 그런 빠름을 쫓아가지 못한다면 계속해서 뒤쳐질 밖에 없는 것이 또한 이 분야인 것 같습니다.


RSS는 여러 사이트의 새로운 글을 아주 쉽게 읽을 수 있도록 도와줍니다. 구글 리더와 같은 피드 구독기를 적극 활용하면 수 많은 블로그와 홈페이지의 최신 정보를 쉽게 얻을 수 있습니다. 파이어폭스와 같은 최신의 브라우저는 아주 쉽게 피드를 구독할 수 있도록 기능을 지원하고 있기도 합니다. 다른 하나는 Delicious와 같은 SNS기반의 북마크 서비스를 이용하는 것입니다. HTML, CSS, Web Standards 등 관련 태그를 통해서 다른 사람들이 북마크한 유용한 정보와 사이트들을 쉽게 찾아볼 수 있습니다.


수칙 2. 습관을 버려라

세살 버릇 여든까지 간다고 합니다. 한번 몸에 벤 습관이 그만큼 무섭다는 뜻입니다. 초중고와 대학을 지나면서 그리고 사회 초년생일 때- 처음 개발을 배우고 이 바닥에 발을 들이기 시작해서 처음 만났던 사수로부터 배웠던 기술들. 아무것도 몰랐던 우리는 습자지처럼 새로운 기술들을 받아 들이고 배워왔습니다. 하지만 알게 모르게 잘못된 정보와 기술을 가려 내지 못하고 무분별하게 배워왔다는 사실입니다. 책이라고 해서 다르지 않습니다. 외서의 경우 오역되거나 잘못된 의미를 전달하기도 하고, 바람직하지 않은 기술을 권장하는 듯 써 놓은 것을 그대로 믿어버린 경우가 부지기수입니다.

때문에 웹 접근성과 웹 표준을 대하는 개발자에게 있어서 가장 큰 충격은 자신의 지식에 대한 확신의 흔들림입니다. 뒤에 간단한 설문 조사 결과를 통해서도 말씀 드리겠지만 자신이 알고 있는 표준에 대한 지식이 과연 옳은 것이었는가? 하는 의심을 가질 필요가 있습니다. 그래서 두번째 수칙은 ‘관성을 버려라’ 그리고 ‘항상 현재의 방법이 최선인지를 의심하라’라고 하였습니다.

그럼 웹 개발자들이 일반적으로 잘못 알고 있었던 사례들은 어떤 것들이 있는지 살펴보겠습니다.

습관 하나. 비동기 통신은 Frame으로 구현해야 하나?

첫번째 사례는 비동기 통신을 사용하기 위해서 프레임을 사용하는 경우입니다. 최근에는 Ajax를 이용한 개발이 붐을 일고 있기는 하지만 여전히 Frameset을 설정하여 무의미한 frame을 만들어 놓고, 비동기 통신을 구현하고자 하는 개발자들이 있었습니다. 조금 더 자세히 살펴보겠습니다.

Frame 요소는 Netscape 2.0에서 최초 지원된 후 Hidden Frame, DHTML로 차차 발전해 나간다

Frame 기술의 발전하다가 Ajax에게 그 자리를 내주고 있다.


Frame은 Netscape 2.0(1996)에서 최초로 지원되었고, HTML 4.0(1997)에 이르러 공식적으로 도입되었습니다. Hidden Frame 기술은 Frameset을 설정하여 하나의 Frame의 높이를 ‘0’로 만들어 서버와의 통신을 처리하는데 사용한 최초의 비동기 요청/응답 모델이었습니다. 이후 마이크로소프트사가 자바스크립트를 이용하여 동적으로 페이지의 일부를 수정할 수 있는 기술인 DHTML을 만듭니다. Hidden Frame 기술은 이 DHTML을 만나 페이지의 어느 부분이라도 서버 정보를 가지고 언제든지 새로고침할 수 있도록 해 주었습니다. 하지만 Hidden Frame 기술은 반드시 프레임셋을 설정해야만 한다는 단점이 있었는데, iframe  엘리먼트가 HTML 4.0에 포함되면서 Inline Frame 기술을 사용할 수 있게 됩니다. 이후 CSS와 결합하여 Hidden Inline Frame 기술로 발전되어 사용되기 시작합니다. 하지만 더이상 Frame을 사용하여 웹사이트의 구조를 분리할 필요성(퍼포먼스 향상을 위해)도 없으며, 비동기 통신을 위해서라면 이미 Ajax와 같은 기술이 그 자리를 대체해 나가고 있다. 그럼에도 이같은 frame의 발전은 많은 웹개발자들이 Frame기술을 이용한 잘못된 습관을 가지게 만드는데 일조를 하게 됩니다. 다음의 마크업을 보겠습니다.

<frameset rows="*,0" frameborder="0" border="0" border="0">
    <frame src="main.html" name="main" scrolling= "auto">
    <frame src="blank.html" name="hidden" scrolling= "auto" >
</frameset>

경력이 적은 분들이라 하더라도 이와 같은 마크업을 한 두번쯤은 보셨을 것으로 생각됩니다. 이같은 프레임셋을 설정하는 이유에는 지금 설명드린 비동기 통신을 구현하기 위한 목적 외에도 도메인을 깔끔하게 유지하고자 하는 목적도 있습니다. 하지만 두 가지 이유 모두 접근성 측면에서 바람직하지 않습니다. 바로 이어서 설명드리겠습니다.

습관 둘. 고정 URL은 보안이 좋다?

과거에는 URL을 통한 해킹 공격이 이루어졌던 사례들이 있었습니다. Query Injection이라고도 하는 이 해킹 방법(SQL Injection이 더 정확한 표현이라고 합니다)은 이와 같이 URL이나 사용자 서식 요소의 필드를 통해서 특정 SQL Query를 입력함으로써 웹사이트 가입자의 비밀번호나 주민등록번호와 같은 정보를 노출시키는 방법입니다. 또한, 꼭 Query Injection 이 아니더라도 간단히 도메인 뒤에 따라 붙는 Query String의 값을 조작하는 것만으로도 웹사이트에 비정상적인 동작을 요청할 수 있습니다. 이 때문에 많은 사람들이 URL에 Query String을 보이지 않도록 눈속임을 했었습니다. 거기에 마우스 우클릭을 막아 컨텍스트 메뉴가 뜨지 않게까지 했습니다. 이렇게 하면 사용자가 임의로 웹 페이지의 전체 URL을 알 수 없을 것이라고 생각했던 것이지요.

네이버

네이버와 같은 포털의 URL은 숨겨져 있지 않다


하지만 어느 사이트보다도 보안이 생명인 검색 사이트나 포털 사이트 어느 곳도 전체 주소를 감추거나 하지 않습니다. URL을 감추고, 컨텍스트 메뉴를 무력화 시키는 것이 결코 해커의 공격을 막는 방법이 되지 않는다는 것입니다.

그럼 이러한 프레임셋 구조가 웹접근성 측면에서는 어떨까요?

프레임셋을 사용하게 되면 일단, 개별 웹 페이지의 고유 주소를 상실하기 때문에 고유성이 상실됩니다. 이것은 결국 정보와 위치의 불일치를 가져오게 됩니다. 즉, 절대 주소가 공개되지 않은 경우 사용자는 찾고자 하는 정보를 다시 얻기 위해서 웹 사이트의 초기 페이지부터 탐색을 반복해야 하는 번거로움을 가지게 됩니다. 이는 파리를 여행하는 사람에게 세계 지도를 던져 주며 에펠탑을 찾아 가 보라는 것과 다를게 없습니다.

같은 URL을 가진 서로 다른 페이지

같은 URL을 가진 서로 다른 페이지


국가정보원 웹사이트입니다. 홈페이지와 관계규정 내용을 담고 있는 페이지의 URL이 www.kecs.go.kr로 동일함을 수 있습니다. 관련 내용을 인용하기 위해서 URL이 필요한 경우에도, 다른 사람에게 해당 페이지의 내용을 소개하고 싶을 때에도 또같은 URL을 사용해야 합니다. 심지어 자신이 북마크를 해 놓고 다시 열고 싶을 때에도 국정원 사이트의 홈페이지부터 재 탐색을 해야합니다. 이것은 일반인에게도 매우 불편합니다.

그럼에도 불구하고 Frame을 사용해야 한다면 다음을 기억하십시오:
  • DTD(HTML 4.01 Frameset 또는, XHTML 1.0 Frameset)의 명확한 정의
  • title 속성을 이용한 정확한 이름을 부여
  • 최소 사용

습관 셋. alt? title? 그런거 없어도 아무 문제 없더라

alt는 툴팁이 아닙니다

alt는 툴팁이 아닙니다

다음으로 소개드릴 것은 대체 텍스트와 제목에 관해서입니다. alt 속성은 이미지의 텍스트로 대체하기 위한 속성입니다. 시각 장애가 있는 사람은 이미지의 내용을 파악할 수 없기 때문에 alt 속성의 내용으로 대신 인지합니다. 또한, 검색 엔진 역시 인간과 같이 시각 정보를 가질 수 없기 때문에 alt 속성을 통해서 정보를 수집합니다. 그런데 IE는 alt 속성을 풍선 도움말(툴팁)로 처리해서 보여주는 기능을 하고 있습니다. 일반인들이 뜬 눈으로도 이미지의 내용을 파악하지 못한다고 생각해서였을까요?

title 속성 역시 alt 처럼 스크린리더를 통해서 음성 정보를 지원하고, 일부 엘리먼트를 제외한 거의 모든 엘리먼트의 제목으로 사용될 수 있습니다. 특히 frame 엘리먼트와 label 엘리먼트를 함께 쓸 수 없는 서식 요소의 제목으로사용되면 접근성을 높일 수 있습니다. 하지만 alt와 title 속성을 처리하는데 있어서 스크린리더마다 방식이 다를 수 있기 때문에 이에 대한 사전 조사와 테스트가 필요합니다.

미투데이 스타일시트 목록

미투데이는 다양한 스타일시트를 포함하고 있고, title을 부여하고 있다.


미투데이 사이트는 여러개의 테마 스타일시트를 포함하고 있습니다. 개별 스타일시트를 연결하는 link 엘리먼트에는 해당 스타일시트의 제목이 title로 정의되어 있음을 볼 수 있습니다.

alt 속성을 잘 못 처리한 Doday

Doday는 alt 속성을 잘못 처리하고 있다


반면에, 비교적 웹 표준을 잘 준수한 Doday 서비스의 경우 메인 페이지 ‘요즘 이야기’부분에서 사용자 프로필 이미지들에 대한 alt 값이 모두 ‘님의 프로필 이미지’로 똑같습니다. 사용자 아이디를 넣어줘야 하는 부분에서 개발자가 실수로 빠뜨리지 않았나 싶습니다. 결과적으로 시각 장애인 및 검색 엔진은 서로 다른 이미지들을 모두 똑같은 의미의 이미지로 파악할 우려가 있습니다. (4월 7일 오전 저의 버그 신고로 인해 바로 수정되었습니다.)

alt와 title을 이야기하면서 항상 빠지지 않는 것이 언제 alt를 쓰고, 언제 title을 써야 하는지에 대한 문제입니다. 이 문제는 네이버 카페 ‘하드코딩을 하는 사람들’이나CSS Design Korea’에서의 논의'한국 모질라 커뮤니티'에서 논의가 이루어졌었고, 일모리님의 블로그에 잘 설명되어 있습니다. 참고해 주시기 바랍니다.

대체 텍스트를 사용하기에 앞서 다음과 같은 고민이 있을 수 있습니다.  첫째, 의미를 가진 이미지인가 꾸밈용 이미지인가 하는 것입니다. 단지 꾸밈용이라면 불필요한 대첵 텍스트가 오히려 접근성과 사용성을 떨어 뜨릴 수 있습니다. 둘째, 이미지 자체를 대체하는 것인지 아닌지를 판단하여 alt를 사용할지 title을 사용할지 적절히 판단할 수 있어야 합니다. 셋째, 대체 텍스트의 길이가 긴 경우 longdesc 속성을 이용하거나, IR기법 등 다른 방법을 고민할 있어야 합니다.


습관 넷. Label? 개발자는 다 안다고?

웹 개발자들이 자주 간과하고 있는 것 들 또다른 하나가 바로 label 요소입니다. label요소는 input과 같은 사용자 서식 요소에 대한 정보를 첨부하며 연관을 맺습니다. 주로 서식 요소의 제목 요소로 적용되고 있으며, 서식요소와 1:1로 관계를 갖습니다. 이같은 마크업은 서식 요소에 대한 접근성을 높여줍니다. 다음은 label을 적용하는 방법입니다.

명시적 선언
<label for="userId">아이디</label>
<input type="text" id="userId" />

암시(묵)적 선언
<label>비밀번호
<input type="text" id="userPw" />
</label>

Title 선언
<input type="text" id="phoneHead" title= "전화 앞자리" />
<input type="text" id="phoneBody" title= "전화 뒷자리" />

label을 마크업하는 방법에는 명시적 선언과 암시적 선언 두가지가 있습니다. 1:1로 대응되는 서식 요소에 대해서 id와 for 속성을 통해서 연결하는 방법이 명시적 선언이며, 서식 요소를 label 엘리먼트로 감싸는 것이 암시적 선언입니다. 암시적 선언인 경우에 label엘리먼트의 for 속성은 생략이 가능합니다. 하지만 전화번호와 주민등록번호와 같이 동일한 의미를 갖는 서식요소가 이상의 필드로 구성된 경우 label 엘리먼트와 1:1로 대응시키는 것이 비효율적인 경우가 있습니다. 이런 경우 각 서식요소에 title 속성을 이용해서 제목을 달아 주는 것이 좋습니다.

하지만 이렇게 의미적으로 하나의 정보를 위해서 이상의 필드로 구성하는 것은 사용성 입장에서도 별로 바람직하지 않은것 같습니다. 필드를 채우고 Tab키를 눌러서 이동해야 하는 번거로움을 차치하더라도, 필드가 채워지면 자동으로 다은 필드로 이동하는 기능의 경우에는 시각 장애인에게는 접근성을 저해하는 요소가 된다는 사실을 알아두실 필요가 있을 것 같습니다. 하나의 필드로 구성하여 자바스크립트와 서버 개발을 통해서 얼마든지 유효성 검증과 데이터 처리를 할 수 있을 것입니다.

네번째로 말씀 드릴 내용은 form 엘리먼트 처리에 관한 것으로, 자바스크립트를 이용해서 서식 요소의 값을 서버에 전달하는 경우 자바스크립트가 지원되지 않는 환경에서 ‘전달’ 자체가 이루어지지 않는 문제가 있습니다.  따라서 서식 요소의 데이터를 서버에 넘기는 작업은 form 엘리먼트의 본래 기능을 그대로 이용하는 것이 좋습니다. 실생활에서의 배달과 전달을 UPS와 같은 전문 전송 업체에게 맡기듯 서식 요소의 데이터는 form에게 믿고 맡기는 것이 좋습니다.

더불어 서식 요소에 대한 유효성 검증을 자바스크립트로만 처리하는 경우가 종종 있습니다. 이 역시 바람직하지 않은 것으로, 반드시 클라이언트와 서버 양쪽 모두에서 유효성 검증에 대한 처리를 해 주어야 사용자의 실수로 인한 문제를 막을 수 있습니다.

다음은 꼭 한번 읽어보세요: (오픈 웹 현재 구글 그룹스로 변경되어 아래 링크를 확인할 수 없을 수 있습니다)


수칙 3. 사람을 믿고, 기계를 의심하라

지금까지는 지식과 정보, 기술적인 부분에 대해서 두가지 수칙을 들었고, 그 안에서 몇가지 작은 이야기들을 전해 드렸습니다. 이제 세번째 수칙으로 ‘사람을 믿고, 기계를 의심하라’고 말씀을 드리면서 수칙 3.1 ‘사람을 믿어라’라고 부탁드리고 싶습니다.

3.1 동료를 믿어라

첫번째로 웹 기획자는 누구보다 열심히 웹 접근성와 사용성에 대해서 고민을 하는 사람입니다. 그들이 다소 거만하고 잘난 체를 할지 모르지만 그들의 머리 속에는 우리들이 걱정하는 이상으로 많은 것들을 고민하고 있다라는 사실을 잊지 마시길 바랍니다.

에이젼시에서 일을 했던 경험을 돌이켜보면 제가 사내에서 웹 접근성과 표준에 대한 이야기를 꺼낼 때 그리고 설득하는 과정에서 디자이너를 이해시키는 일이 가장 쉽지 않았었습니다. 그러던 중 함께 스터디를 하던 디자이너 친구 한 명이 이런 질문을 하더군요. ‘과연 웹 표준을 지킬 수 없는 디자인이 있느냐? 있다면 어떤 디자인이냐?’라고 말이죠. 그날 스터디에서는 저를 비롯해서 여러명의 사람들이 한국의 비주얼이 강한 디자인 때문에 표준을 적용하기 어렵다라고 목소리를 높이고 있었거든요. 하지만 막상 그 디자이너 친구의 질문에 어떤 디자인이 절대 표준 기술만 가지고 만들 수 없다라고 대답하지 못했습니다. 물론, 실무에서 작업을 하다 보면 디자인 때문에 마크업과 css 작업에 애를 많이 겪고 있고, 종종 해결책을 찾지 못하고 CSS Hacks을 사용하기도 합니다. 하지만 돌이켜보면 정말 길이 없어서 그랬다기 보다 시간이 부족해서 차선책을 택했던 적이 더 많았음을 스스로 깨닫게 됩니다. 저는 그 날 이후로 함께 일 하는 웹디자이너를 설득하는 일을 그만 두었습니다. 그리고 까짓것 한 번 해볼테니 날 믿고 디자인을 해달라고 부탁하곤 했습니다.

이 자리에 모인 대부분의 분들이 웹 퍼블리셔 또는 UI 개발자라는 명함을 가지고 계실것으로 생각됩니다. 그만큼 그 어느 직군보다 웹 표준과 접근성에 대해서 관심이 높고, 열정이 대단하다고 생각합니다. 어떤 일이든 시작이 가장 어렵고 첫 걸음을 옮기는 것이 가장 힘듭니다. 그 큰 걸음을 지금 여러분이 떼고 있으신 겁니다. 때문에 저는 감히 여러분 모두를 웹 표준 전문가라고 말씀드립니다. ASP든 JSP든 서버단에서 개발 업무를 보고 계신 개발자님들 동료 UI개발자 분들의 실력을 믿어보시길 바라겠습니다.

문화적인 차이일 수 있겠지만 한국은 지나치게 고객을 무시하고, 의심하는 경향이 있습니다. 사이트 발주자인 클라이언트의 무지함을 욕하고, 사이트 사용자인 고객의 멍청함에 잔득 걱정을 합니다. 때문에 온갖 보안 프로그램을 깔기를 강요하고 프레임셋으로 URL을 감추고, 우클릭을 막아버리고, 온갖 문서를 보면서 동의를 강요합니다.

개발자들의 논리 중에 가장 우수운 것이 바로 ‘자신 역시 한 명의 사용자(고객)이다’라는 점입니다. 그렇게 사용자들을 무시하면서 자신을 또 명의 사용자로 생각한다는 것. 결국 누워서 침을 뱉은 것 아닌가요.

또 한가지 개발자들은 오로지 코딩만 잘 하면 된다고 생각합니다. 발주자건 사용자건 그들을 상대하는 건 기획자라고 생각합니다. 웹 접근성과 웹 표준에 대한 인식 제고나 설득 역시 기획자가 해야할 것이라고 생각하고, 웹 퍼블리셔니 UI개발자니 하면서 갑자기 한 자리를 차지하기 시작한 사람들이 해야 한다고 생각합니다.

만약 개발자 직군이 명확하게 클라이언트단과 서버단으로 구분되어 서버사이드개발자가 순수하게 로직만 작성한다면 반드시 틀린 말은 아닐 수 있습니다. 하지만 제가 서두에서 개발자의 범위를 포괄적 개발자로 설정한 것 처럼 현실은 그렇치 않습니다. 그리고 앞으로도 상당한 기간동안 지금의 현실이 갑자기 바뀌지도 않을 것으로 생각됩니다. 지금, 개발자인 사람들 모두가 같은 고민과 철학으로 고객을 바꾸고 변화 시킬 필요가 있는 겁니다.

3.2 기계를 의심하라

개발 경험이 오래되신 분들은 과거 핫도그 웹 에디터나모 웹 에디터 등을 기억하실 겁니다. 어도비의 고라이브 있군요. 드림위버의 초기 버전도 언듯 떠오르실 분도 계실겁니다. 당시의 이런 에디터 툴은 편리하게 홈페이지를 만들어 주기는 했지만 웹 표준을 몰랐던 브라우저들 처럼 툴 역시 웹 표준을 인식하지 못했습니다. 때문에 불필요한 마크업과 CSS를 만들어 냈고, 호환성이 확보되지 않은 자바스크립트 코드를 마구 집어 넣었습니다. 지금은 드림위버등 많은 에디터들이 웹 접근성과 웹 표준 스펙을 반영하고 있지만 여전히 일부 에디터는 잘못된 코드와 DTD의 생략을 기본 값으로 설정해 놓고 있습니다.

특히 나모 웹 에디터는 저 역시 98년 당시에 많이 사용했던 에디터입니다. 이 에디터는 자바스크립트를 자동으로 생성해 주는 마법사 툴이 있었는데, 호환성이 확보되지 않은 스크립트 코드를 만들어 냈던 것으로 기억합니다. 그 코드가 IE전용이었다는 사실은 한참이나 지나서야 알게된 사실들이었습니다. 초기 드림위버가 만들어낸 코드 역시 엉망진창이었습니다. 초기 버전에서 만들어낸 엉망의 코드 때문에 많은 개발자들이 워지익 툴의 편리함에도 불구하고 나모 웹 에디터나 드림위버 등의 사용을 꺼리게 되기도 했었습니다. 다행히 최근 출시된 새로운 버전이나 에디터들은 많은 향상이 있어 과거처럼 엉망인 경우는 드믄것 같습니다. 옛 말에 장인은 연장 탓을 하지 않는다고 하죠. 훌륭한 웹 개발자라면 툴 때문에 웹 표준을 지키기 어렵다라는 말은 하지 않아야겠죠. 하지만 툴이 가져다 주는 편리함과 생산성은 역시 무시할 수 없을 것입니다. 때문에 어떤 툴을 자신의 주력 툴로 결정한 것인지는 매우 중요하고, 잘 선택되어야 합니다. 무료든 유료든 아주 다양한 에디터들이 존재하고 있습니다. 충분히 검증된 제품을 선택하시길 바랍니다.

또 한가지, 개발자들의 PC는 회사 사정에 따라 차이는 있겠지만 일반적으로 부족하지 않은 스펙을 가지고 있습니다. 하지만 인터넷에 접속하는 모든 PC가 아이온과 콜 오브 듀티같은 인기 게임을 실행시킬 있을 만큼 멋지진 않습니다. 학교나 관공서같은 곳의 PC는 생각보다 오래된 것이 많습니다. 이미지와 플래쉬 무비로 무겁게 제작된 사이트들 때문에 PC를 몇 번이나 리부팅해야 하는 사람들도 있을 것입니다.

Markup Validation Service

Markup Validation Service


마지막으로 표준을 열심히 지키고 계신 여러분들이 절대로 잊지 말아야 할 한가지를 말씀 드리겠습니다. HTML과 CSS에 대해서 충분히 의미 있게 그리고 호환성이 확보된 표준 스펙을 따랐을 경우에 우리는 W3C의 벨리데이션 서비스를 통해서 이같은 유효성 검사 통과 화면을 받아 볼 수 있습니다. 하지만 이 순간 여러분은 과연 이 결과가 타당한지에 대한 의구심을 가질 필요가 있습니다. 벨리데이션 검사는 단지 코드에 대한 문법 검사일 뿐입니다. 파란 하늘 이미지에 ‘용광로’라고 적어 넣은 alt 속성을 확인 했더라도 이 검사는 초록색 ‘성공’ 메세지를 멋지게 보여줄 것입니다. 과연 제대로 만든 페이지였을까요?


마치며

큰 수칙 3가지를 전해 드리면서 그리고 첫번째 수칙을 통해서 웹 개발자에게 있어서 웹 접근성을 향상시키는 가장 확실하고 정직한 방법은 '공부'라고 했습니다. 표준 스펙을 얼마나 제대로 알고 있는지 그리고 얼마나 명확하게 적용할 있는지가 가장 중요하다고 생각합니다. 그래서 저는 웹 표준을 웹 개발자에게 있어서 '기술'이라고 생각하고, 웹 접근성은 다른 사람을 생각하고 타인을 배려하고자 하는 '철학'에 빗대어 의미를 전달해 드리고자 했습니다. 기본적으로 웹 접근성 역시도 여러가지 명세와 가이드로 틀을 갖춰 나가고 있지만 근본적으로 사람에 대한 마음을 담는 것이라고 생각하기 때문입니다. 개발자는 코드만 잘 짜면 된다라는 생각은 이제 버려야 합니다. 이 코드가 사람을 차별하는 칼이 될 수 있음을 아셔야 합니다. 그래서 더욱 더 왜 내가 웹 접근성을 고민해야 하는지에 대한 자기 철학이 필요한 이유입니다. 끊임 없는 자기 계발과 철학의 발견. 이 이야기를 드리고 싶었습니다.
Posted by 1010
98..Etc/Etc...2009. 6. 27. 01:37
반응형

PC방 아르바이트 해 보신분은 공감할만한 이야기이지만, 일부 손님중에는 PC를 이용하고 난 이후에 "Programs Files" 폴더를 전부 삭제해버리거나 제어판에 들어가서 PC Setting을 엉망으로 해놓고 가는 경우가 있다.

나 같은경우에도 1999~2000년도에 잠깐 PC방을 운영해본적이 있었는데, 그당시에도 그런 손님이 간혹 있었던듯 하다. 그래서일까? 요즘 PC방에서는 "작업 관리자"나 "제어판"을 사용하지 못하게 막아놓는 곳이 있다.

사용자들의 못된(?) 행태를 막기 위한 방법이라고는 하지만, 그로 인해 제어판의 키보드 설정 항목이라던가 일부 항목을 사용해야 하는 사용자의 경우에는 아쉬운감이 있을 수 있다.

뭐 요즘에는 하드디스크 프로텍션 (맞는 용어이려나? -_-;)이라는 툴을 이용해서 컴퓨터를 Cold Booting하면 처음 셋팅한 상태로 되돌려주는 Tool이 있어서 이런 경우는 많이 줄었다고 볼 수 있다.

자 그럼 이제 본론으로 들어가서.... 제어판을 사용 못하게 해놓았을때 제어판 사용을 하려면 어떻게 해야하는가?
그 부분에 대해서 알아보도록 하자.

1. 시작 -> 실행 -> gpedit.msc -> 확인



2. 사용자 구성 -> 관리 템플릿 -> 제어판 -> 제어판의 액세스 금지 -> 더블 클릭


3. 사용 -> 확인


위와 같이 설정하게 되면 윈도우즈의 시작 메뉴에 있는 제어판 메뉴가 사라져 제어판에 접근할 수 없게 된다.

사용자 삽입 이미지

설정 전 : 제어판 메뉴가 보인다.

사용자 삽입 이미지

설정 후 : 제어판 메뉴가 사라졌다.


Posted by 1010
98..Etc/Etc...2009. 6. 27. 01:33
반응형
▣ (ActiveX) 테스트 인증서 만들기 (Ver 0.1)

▷ 준비물
    - makecert.exe : 개인 키 파일(*.pvk), X.509 형식의 보안 인증서(Certification) 파일을 만든다.
    - cert2spc.exe : X.509 형식의 보안 인증서(Certification) 파일을 PKCS #7 인증서 파일(*.spc)로 변환한다.
    - root.cer     : 루트 인증 기관의 인증서. 인증 경로 표시를 위해 필요.

▷ 작업순서
    1. makecert -sv "mycert.pvk" -n "CN=EnjoyDev" "mycert.cer"
       ; 개인 키 파일(mycert.pvk)과 테스트 인증서(mycert.cer) 파일을 만든다.
       ; "CN=EnjoyDev"는 인증서에서의 게시자 정보를 의미한다.
       ; 위 문장을 실행시키면 2개의 입력 상자가 나타나는데,
       ; 첫번째 "개인 키 암호 만들기" 입력 상자에서는 개인 키 파일에서 사용할 암호를 입력한다.
       ; 두번째 "개인 키 암호 입력"에서는 테스트 인증서에서 사용 할 개인 키 파일의 암호를 입력한다.
         즉, 첫번째에서 입력한 암호를 동일하게 입력한다.

    2. cert2spc root.cer mycert.cer mycert.spc
       ; 위에서 만든 인증서 파일(mycert.cer)을 이용해서 PKCS #7 인증서 파일(mycert.spc)을 만든다.
       ; 인증 경로 표시를 위해 루트 인증서(root.cer)를 포함시킨다.

▷ 결과물
    ; 위 과정을 거치면 "mycert.pvk", "mycert.cer", "mycert.spc" 세 개의 파일이 만들어지는데
      ActiveX(OCX, DLL, ...), EXE 프로그램에 디지털 서명 작업을 하기 위해서는 "mycert.pvk", "mycert.spc" 2개의 파일만 있으면된다.


▣ 참고
    ; ActiveX 배포 관련 강좌 등의 문서에 위 과정이 언급되어있는데,
      간혹 ActiveX 배포 과정의 일부로 생각하고 배포 작업을 할 때마다 반복해야하는 것으로 오인하는 경우가 종종있다.
      인증서는 프로그램 배포자 정보를 담고 있는 파일이므로 인증서 만드는 작업은 한 번만 진행해도 무관하다.


▣ Ver 0.1
    ; ActiveX 배포 관련 내용을 정리하다보니 많은 부분과 연결되고 있어 부분적으로 나누고 있습니다.
      추가적으로 정리되는 부분은 위 내용을 기본으로 살을 붙여가도록 하겠습니다.


☞ 본문 출처 : http://www.enjoydev.com/blog/70

☞ 본인의 글 입니다. 이 글을 다른 곳에 게재하는 경우 본문 출처를 밝혀주시기 바랍니다.

☞ 위 내용은 정식 문서 번역이 아닌, 실무 적용에 따른 경험을 바탕으로 어느정도 자의적인 설명이 포함되어있습니다.
   잘못된 내용이 있는 경우 지적 바랍니다.


▣ 참고 사이트
    * Signing and Checking Code with Authenticode
       ; http://msdn.microsoft.com/workshop/secu … ning.asp
    * .cab 파일 서명 단계
       ; http://support.microsoft.com/kb/247257/ko
Posted by 1010
반응형

[javascript] 입력 문자 한글 체크


function koreanCheck(str) {
    var i;
    var ch;
   
    for (i=0;i<str.length;i++) {
        ch = escape(str.charAt(i));        //ISO-Latin-1 문자셋으로 변경

        if (strCharByte(ch) != 2) { //한글이 아닐 경우
            return;
        }
    }
}

function strCharByte(chStr) {
    if (chStr.substring(0, 2) == '%u') {
        if (chStr.substring(2,4) == '00')
            return 1;
        else
            return 2;        //한글
    } else if (chStr.substring(0,1) == '%') {
        if (parseInt(chStr.substring(1,3), 16) > 127)
            return 2;        //한글
        else
            return 1;
    } else {
            return 1;
    }
}


출처 : http://ingenuity.egloos.com/2789643

Posted by 1010
01.JAVA/Java2009. 6. 27. 01:19
반응형
public boolean sendMail(String filePath,String host, String receiver, String sender, String subject, String contents, InquireFile[] files){
 
  boolean flag = false;
 
  Properties prop = new Properties();
 
  prop.put("mail.smtp.host" , host);
 
  Session mailSession = Session.getDefaultInstance(prop, null);
 
  try{
   
   InternetAddress from = new InternetAddress(sender);
   
   Message msg = new MimeMessage(mailSession);
   
   msg.setFrom(from);
   
   msg.setRecipient(Message.RecipientType.TO, new InternetAddress(receiver));
   
   msg.setSubject(subject);
   
   Multipart multi = new MimeMultipart();      
   
   MimeBodyPart mbp = new MimeBodyPart();
   
   mbp.setContent(contents, "text/html; charset=ms949");
   
   multi.addBodyPart(mbp);
   
   if(files != null){
   
    for(int i = 0; i < files.length; i++){
     
     if(files[i] == null ) continue;
     
     DataSource fds = new FileDataSource(filePath + "/" + files[i].getFileName() );
     
     MimeBodyPart m = new MimeBodyPart();
     
     m.setDataHandler(new DataHandler(fds));
 
     m.setFileName(  toEng(fds.getName() ) );
     
     multi.addBodyPart(m);
     
    }
   }
   
   msg.setContent(multi);
   
   msg.setSentDate(new Date());
   
   Transport.send(msg);
   
   
   flag = true;
   
   
  }catch(Exception e){
   
   Logger logger = Logger.getLogger(this.getClass());  
   
   logger.error(this.getClass().getName() + " : " + e);
   
  }
 
  return flag;
 
 }

 public static String toEng(String origin) throws Exception{
 
 
  return new String(origin.getBytes(), "ISO-8859-1");
 }


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


재미 있는건  한글 변환 부분 에서 new String(한글.getBytes("KSC5601"), "ISO-8859-1") 처럼 안해두 된다는것임...


다운로드시 한글 변환도 위와 같이 하면 URLEncoding 을 안해도 됨 ㅡㅡ


daum.net , naver.com, hotmail.com, outlook express 에서 테스트 함


테스트 환경 : Win xp , tomcat 4.1.30 , Apache 2.0.49 , j2sdk 1.4.2_05


사용 디비 :  MySQL, Informix , Oracle

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:18
반응형

Tomcat 에서 Oracle 연결 기준입니다.

 

첫번째! -------------------------------------------------------------------

ojdbc14.jar (ojdbc14.zip 파일이 아니다!) 를 <CATALINA_HOME>/common/lib 에 복사한다.

 

 


두번째! -------------------------------------------------------------------

server.xml 파일을 수정한다. <GlobalNamingResources></GlobalNamingResources> 사이에 다음의 내용을 추가한다.

 

<Resource name="jdbc/<alias>"
               auth="Container"
               type="javax.sql.DataSource"
               driverClassName="oracle.jdbc.driver.OracleDriver"
               factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
              
url="jdbc:oracle:thin:@<server>:<port>:<sid>"
               username="<user>"
              
password="<password>"
               maxActive="20"
               maxIdle="10"
               maxWait="-1" />

 

 

 

세번째! -------------------------------------------------------------------

context.xml 파일을 수정한다. <Context></Context> 사이에 다음의 내용을 추가한다.

 

<ResourceLink global="jdbc/<alias>" name="jdbc/<alias>" type="javax.sql.DataSource"/>

 

 

네번째! -------------------------------------------------------------------

web.xml 파일을 수정한다. <web-app></web-app> 사이에 다음의 내용을 추가한다.

<resource-ref>
    <description>Oracle Development Datasource</description>
    <res-ref-name>jdbc/<alias></res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

 

 

 

사용법! -------------------------------------------------------------------

[JAVA]

Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/<alias>");

 

[JSP]

<%
    com.microdeveloper.db.jndi.ConnectionPool ocp =

                                  new com.microdeveloper.db.jndi.ConnectionPool();
    ocp.init();
%>

<h2>Results</h2>
Message: <%= ocp.getMessage() %>

 

 

 

Eclipse! -------------------------------------------------------------------

 

사용자 삽입 이미지

 
 
 
1) context.xml
Eclipse 에서 Tomcat 을 연결해서 사용하는 경우 context.xml 파일이 존재하지 않는다.
따라서, 프로젝트의 서버 설정 부분에 context.xml 파일을 복사하면 된다.
 
2) web.xml
Tomcat server 설정부분의 web.xml 파일을 수정하는 것이 아니라 생성한 웹 프로젝트의
WEB-INF 폴더에 있는 web.xml 파일을 수정해야 한다.
 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:17
반응형

Tomcat 에서 Oracle 연결 기준입니다.

 

첫번째! -------------------------------------------------------------------

ojdbc14.jar (ojdbc14.zip 파일이 아니다!) 를 <CATALINA_HOME>/common/lib 에 복사한다.

 

 


두번째! -------------------------------------------------------------------

<ContextName.xml> 파일을 추가한다.

파일 추가 경로 : ${CATALINA_HOME}\conf\Catalina\localhost

ContextRoot 와 같은 이름의 파일을 생성하고 다음의 내용을 추가한다.

 

<Context docBase="<ContextDocBase>"
             path="<ContextPath>"
             reloadable="true"
             debug="5"
             crossContext="true">

 

    

    <Resource name="jdbc/<alias>"
                   auth="Container"
                   type="javax.sql.DataSource"
                   driverClassName="oracle.jdbc.driver.OracleDriver"
                   factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
                  
url="jdbc:oracle:thin:@<server>:<port>:<sid>"
                   username="<user>"
                  
password="<password>"
                   maxActive="20"
                   maxIdle="10"
                   maxWait="-1"

                   removeAbandoned="true"
                   removeAbandonedTimeout="60"
                   logAbandoned="true"/>

</Context>

 

 

 

세번째! -------------------------------------------------------------------

web.xml 파일을 수정한다. <web-app></web-app> 사이에 다음의 내용을 추가한다.

<resource-ref>
    <description>Oracle Development Datasource</description>
    <res-ref-name>jdbc/<alias></res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

 

 

                     

JNDI 방법과 다른점은 server.xml 파일에 추가되어야 할 내용을 ${CATALINA_HOME}\conf\Catalina\localhost 에 Context 이름의 XML 파일을 생성하여 넣는다는 것!

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:16
반응형

Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용

 

 

 

이미 눈치 채셨겠지만, 요즘 내가 RDBMS 배우기에 열을 올리고 있다.
지금까지는 JSP/Servlet에서 직접 커넥션을 맺거나, 컨텍스트내에 커넥션 라이브러리를 두고 호출에서 사용했는데, 바꿔야겠다.
JNDI
통한 커넥션 사용은 J2EE 표준이고, 현존하는 거의 모든 컨테이너가 지원한다고 한다.

 

JNDI 서버에 설정하는 방법은 WAS 별로 다르지만, 사용하는 것은 모두 동일하므로 호환성에 문제도 없다.

 

글은 Jakarta DBCP 커넥션 Tomcat JNDI 설정을 통해 데이터베이스 커넥션 풀을 사용하는 방법이다.

 

JNDI 커넥션 풀에 관한 자세한 설명이 JavaServer Pages 3rd ed. 실려있다. 너무 좋다. 읽어보라고 강력하게 권하고 싶다.

 

기본적으로 필요한 라이브러리

  • commons-dbcp.jar
  • commons-collections.jar
  • commons-pool.jar

예제 JDBC 드라이버

  • Oracle 9i classes12.jar

JNDI Naming Resource 설정

1.       라이브러리들을 $CATALINA_HOME/common/lib 복사한다. 이외 디렉토리에 두면 안된다. ZIP 파일은 JAR 확장자를 바꿔야 한다. 톰캣은 JAR파일만 클래스패스에 추가한다.

2.       Connection 풀을 이용할 경우에는 ResultSet Connection 객체를 필히 직접 닫아 줘야만 한다.

3.       $CATALINA_HOME/conf/server.xml 혹은 컨텍스트별 XML 파일의 <Context> 자식 요소로 다음을 추가한다.

4.                <Resource name="jdbc/forumDb" auth="Container" type="javax.sql.DataSource"/>

5.                <!-- Resource name 속성을 이용해서 어플리케이션에서

6.                                javax.sql.DataSource 객체를 얻어가게 된다. -->

7.               

8.               

9.                <!-- 자세한 파라미터 설정은

10.               http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasource-examples-howto.html 참조 -->

11.            <ResourceParams name="jdbc/forumDb">

12.              <parameter>

13.                <name>factory</name>

14.                <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

15.              </parameter>

16.           

17.              <parameter>

18.                <name>maxActive</name>

19.                <value>100</value>

20.              </parameter>

21.           

22.              <parameter>

23.                <name>maxIdle</name>

24.                <value>30</value>

25.              </parameter>

26.           

27.              <parameter>

28.                <name>maxWait</name>

29.                <value>10000</value>

30.              </parameter>

31.           

32.                              <!-- DB 사용자명과 비밀번호 설정 -->

33.              <parameter>

34.               <name>username</name>

35.               <value>dbuser</value>

36.              </parameter>

37.              <parameter>

38.               <name>password</name>

39.               <value>dbpasswd</value>

40.              </parameter>

41.           

42.                              <!-- JDBC 드라이버 클래스 -->

43.              <parameter>

44.                 <name>driverClassName</name>

45.                 <value>oracle.jdbc.driver.OracleDriver</value>

46.              </parameter>

47.             

48.                              <!-- JDBC 접속 URL -->

49.              <parameter>

50.                <name>url</name>

51.                <value>jdbc:oracle:thin:@dbhost:1521:ORA</value>

52.              </parameter>

53.           

54.                  <!-- 커넥션에 문제 없는지 테스트하는 쿼리 -->

55.              <parameter>

56.                <name>validationQuery</name>

57.                <value>select sysdate</value>

58.              </parameter>

59.            </ResourceParams>

 

60.    어플리케이션의 web.xml파일에 다음을 추가하여 JNDI 리소스를 사용할 있도록 한다.

61.                              <resource-ref>

62.                                                   <description>Forum DB Connection</description>

63.                                                   <!-- 다음이 바로 리소스의 이름 -->

64.                                                   <res-ref-name>jdbc/forumDb</res-ref-name>

65.                                                   <res-type>javax.sql.DataSource</res-type>

66.                                                   <res-auth>Container</res-auth>

67.                              </resource-ref>

 

JSP/Servlet 에서 사용하기

이제 다음과 같이 JNDI 이용해 DataSource 객체를 얻고, 객체에서 커넥션을 얻어오면 된다.

 

다음은 서블릿을 작성하고, 서블릿에서 DB커넥션을 얻고, 쿼리를 날린 , 결과를 JSP 파일에 포워딩하여 JSTL 이용해 출력하는 것이다.

 

1.       예제 테이블과 데이터 SQL - 오라클 계정으로 다음과 같은 데이터를 생성했다고 가정하면

2.              create table test (

3.                                  num NUMBER NOT NULL,

4.                                  name VARCHAR2(16) NOT NULL

5.              );

6.               

7.              truncate table test;

8.               

9.              insert into test values(1,'영희');

10.          insert into test values(2, '철수');

11.          insert into test values(3, '미숙');

12.          commit;

 

13.    test.JndiDataSourceTestServlet 소스

14.          package test;

15.           

16.          import java.io.IOException;

17.          import java.sql.Connection;

18.          import java.sql.ResultSet;

19.          import java.sql.SQLException;

20.          import java.sql.Statement;

21.          import java.util.ArrayList;

22.          import java.util.HashMap;

23.          import java.util.List;

24.          import java.util.Map;

25.           

26.          import javax.naming.Context;

27.          import javax.naming.InitialContext;

28.          import javax.naming.NamingException;

29.          import javax.servlet.RequestDispatcher;

30.          import javax.servlet.ServletException;

31.          import javax.servlet.http.HttpServlet;

32.          import javax.servlet.http.HttpServletRequest;

33.          import javax.servlet.http.HttpServletResponse;

34.          import javax.sql.DataSource;

35.           

36.          public class JndiDataSourceTestServlet extends HttpServlet {

37.           

38.              protected void doGet(HttpServletRequest request,

39.                      HttpServletResponse response) throws ServletException, IOException {

40.           

41.                  Connection conn = null;

42.                  ResultSet rs = null;

43.                  Statement stmt = null;

44.           

45.                  try {

46.                      // 커넥션을 얻기 위한 전초작업. 부분을 메소드화 하면 되겠다. ------------

47.                      Context initContext = new InitialContext();

48.                      Context envContext = (Context)initContext.lookup("java:/comp/env");

49.                      DataSource ds = (DataSource)envContext.lookup("jdbc/forumDb");

50.                     

51.                      // 커넥션 얻기

52.                       conn = ds.getConnection();

53.                      //------------------------------------------------------------------

54.                     

55.                      String sql = "SELECT * from test";

56.                      stmt = conn.createStatement();

57.                     

58.                      rs = stmt.executeQuery(sql);

59.                     

60.                      List results = new ArrayList();

61.                     

62.                      while (rs.next()) {

63.                          Map row = new HashMap();

64.                         

65.                          row.put("num", rs.getString("num"));

66.                          row.put("name", rs.getString("name"));

67.                         

68.                          results.add(row);

69.                      }

70.                     

71.                      request.setAttribute("results", results);

72.                     

73.                      RequestDispatcher rd = request.getRequestDispatcher("/dbtest.jsp");

74.                      rd.forward(request, response);

75.                     

76.                  } catch (NamingException e) {

77.                      throw new ServletException("JNDI 부분 오류", e);

78.                  } catch (Exception e) {

79.                      throw new ServletException("뭔가 다른 부분 오류", e);

80.                  } finally {

81.                      // 리소스를 필히 반환할 !

82.                      if (rs != null) { try { rs.close(); } catch (Exception ignored) {} }

83.                      if (stmt != null) { try { stmt.close(); } catch (Exception ignored) {} }

84.                      if (conn != null) { try { conn.close(); } catch (Exception ignored) {} }

85.                  }

86.              }

87.          }

88.    web.xml 서블릿 등록

89.                              <servlet>

90.                                                   <servlet-name>dbtest.svl</servlet-name>

91.                                                   <servlet-class>test.JndiDataSourceTestServlet</servlet-class>

92.                              </servlet>

93.                              <servlet-mapping>

94.                                                   <servlet-name>dbtest.svl</servlet-name>

95.                                                   <url-pattern>/dbtest.svl</url-pattern>

96.                              </servlet-mapping>

97.    /dbtest.jsp 소스

98.          <%@ page contentType="text/html" pageEncoding="EUC-KR" %>

99.          <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

100.       <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>

101.        

102.       <!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">

103.       <html>

104.       <head>

105.       <title>JNDI DataSource Test</title>

106.       </head>

107.                        <body                  bgcolor="#FFFFFF">

108.                           <h2>Results</h2>

109.                          

110.                           <c:forEach var="row" items="${results}">

111.                                                                    NUM : ${row.num}<br />

112.                                                                    Name : ${row.name}<br />

113.                                                                    <hr />

114.                           </c:forEach>

115.       </body>

116.       </html>

 

117.이제 브라우저에서 "/dbtest.svl" 호출해보면 결과를 있다.

 

전역적인 JNDI 리소스 이용

<Resource> <ResourceParams> 요소를 server.xml <GlobalNamingResources> 자식노드로 옮기면 특정 어플리케이션이 아니라, 톰캣에 설치된 전체 어플리케이션에서 사용 있게 된다. 하지만 어플리케이션 "<Context>" 다음과 같은 설정을 해야 한다.

                    <ResourceLink

                                         name="jdbc/forumDb"

                                         global="jdbc/forumDb"

                                         type="javax.sql.DataSource"

                      />

 

아니면 server.xml에서 <Host> 요소의 자식으로 다음을 추가하면 컨텍스트별 설정 필요없이 전체 어플리케이션 컨텍스트에서 GlobalNamingResources 지정된 JNDI 리소스를 사용할 있다.

 

                    <DefaultContext>

                                         <ResourceLink

                                                             name="jdbc/forumDb"

                                                             global="jdbc/forumDb"

                                                             type="javax.sql.DataSource"

                                           />

        </DefaultContext>

 

문제가 생겼어요!

1.       DB 커넥션이 간혹 끊어져요.
Tomcat
작동중인 JVM 가비지 컬렉션을 , 시간이 JNDI Resource 파라미터로 설정한 maxWait보다 길게 경우 DB 커넥션이 끊어질 있다.
CATALINA_OPTS=-verbose:gc
옵션을 주면 $CATALINA_HOME/logs/catalina.out 가비지 컬렉션 상황이 기록된다. 거기에 GC 작업에 걸린 시간도 나오니 그것을 참조로 maxWait 파라미터를 늘려주면 된다. 보통 10~15초로 주면 된다.
GC
시간은 거의 99% 이상 1 이내에 끝나야 하나보다..

2.       무작위로 커넥션이 close 되요.
그건.. Connection 객체를 이상 close 했기 때문이다.
DB Connection Pool
close() 호출할 정말로 닫는 것이 아니라, 단지 재사용할 있다고 표시만 뿐이다.
커넥션을 사용하다가 close()하면 다른 쓰레드이서 커넥션을 있는데, 이걸 현재 쓰레드에서 계속 잡고 있다가 다시 close() 해버리면, 다른 쓰레드에서 사용중에 close()됐다고 나와 버리게 되는 거다.

3.                  conn.close();

4.                  conn = null;

위와 같이 커넥션을 close() 뒤에 바로 null 설정하여 절대로 다시 사용할 없게 만들면 이런 실수는 생기지 않을 것이다.

Tomcat 5.5 예제

        <Resource name="jdbc/myDbResource" auth="Container" type="javax.sql.DataSource"

               maxActive="10" maxIdle="5" maxWait="10000"

               username="ao" password="ao"

               driverClassName="com.mysql.jdbc.Driver"

               url="jdbc:mysql://localhost:3306/myWebApp"

 

               removeAbandoned="true"

               removeAbandonedTimeout="60"

               logAbandoned="true"

               validationQuery="select 1"

               testOnBorrow="true"

               testWhileIdle="true"

               timeBetweenEvictionRunsMillis="10000"

               minEvictableIdleTimeMillis="60000"

       />

 

저기서 removeAbandoned 리소스 반환에 실패한 (혹은 안한) 커넥션을 자동으로 닫아주는 것이다.

 

validationQuery 커넥션이 살아 있는지 테스트하는 코드이다.

 

MySQL, Connector/J Tomcat 5 예제

http://dev.mysql.com/doc/connector/j/en/cj-tomcat-config.html 나온 내용임.

<Context ....>

 

  ...

 

  <Resource name="jdbc/MySQLDB"

               auth="Container"

               type="javax.sql.DataSource"/>

 

  <!-- The name you used above, must match _exactly_ here!

 

       The connection pool will be bound into JNDI with the name

       "java:/comp/env/jdbc/MySQLDB"

  -->

 

  <ResourceParams name="jdbc/MySQLDB">

    <parameter>

      <name>factory</name>

      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

    </parameter>

 

    <!-- Don't set this any higher than max_connections on your

         MySQL server, usually this should be a 10 or a few 10's

         of connections, not hundreds or thousands -->

 

    <parameter>

      <name>maxActive</name>

      <value>10</value>

    </parameter>

 

        <!-- You don't want to many idle connections hanging around

         if you can avoid it, onl    y enough to soak up a spike in

         the load -->

 

    <parameter>

      <name>maxIdle</name>

      <value>5</value>

    </parameter>

 

    <!-- Don't use autoReconnect=true, it's going away eventually

         and it's a crutch for older connection pools that couldn't

         test connections. You need to decide if your application is

         supposed to deal with SQLExceptions (hint, it should), and

         how much of a performance penalty you're willing to pay

         to ensure 'freshness' of the connection -->

 

    <parameter>

      <name>validationQuery</name>

      <value>SELECT 1</value>

    </parameter>

 

   <!-- The most conservative approach is to test connections

        before they're given to your application. For most applications

        this is okay, the query used above is very small and takes

        no real server resources to process, other than the time used

        to traverse the network.

 

        If you have a high-load application you'll need to rely on

        something else. -->

 

    <parameter>

      <name>testOnBorrow</name>

      <value>true</value>

    </parameter>

 

   <!-- Otherwise, or in addition to testOnBorrow, you can test

        while connections are sitting idle -->

 

    <parameter>

      <name>testWhileIdle</name>

      <value>true</value>

    </parameter>

 

    <!-- You have to set this value, otherwise even though

         you've asked connections to be tested while idle,

         the idle evicter thread will never run -->

 

    <parameter>

      <name>timeBetweenEvictionRunsMillis</name>

      <value>10000</value>

    </parameter>

 

    <!-- Don't allow connections to hang out idle too long,

         never longer than what wait_timeout is set to on the

         server...A few minutes or even fraction of a minute

         is sometimes okay here, it depends on your application

         and how much spikey load it will see -->

 

    <parameter>

      <name>minEvictableIdleTimeMillis</name>

      <value>60000</value>

    </parameter>

 

    <!-- Username and password used when connecting to MySQL -->

 

    <parameter>

     <name>username</name>

     <value>someuser</value>

    </parameter>

 

    <parameter>

     <name>password</name>

     <value>somepass</value>

    </parameter>

 

    <!-- Class name for the Connector/J driver -->

 

    <parameter>

       <name>driverClassName</name>

       <value>com.mysql.jdbc.Driver</value>

    </parameter>

 

    <!-- The JDBC connection url for connecting to MySQL, notice

         that if you want to pass any other MySQL-specific parameters

         you should pass them here in the URL, setting them using the

         parameter tags above will have no effect, you will also

         need to use & to separate parameter values as the

         ampersand is a reserved character in XML -->

 

    <parameter>

      <name>url</name>

      <value>jdbc:mysql://localhost:3306/test</value>

    </parameter>

 

  </ResourceParams>

</Context>

 

Oracle 만을 위한 JNDI 설정

원문 : http://www.microdeveloper.com/html/JNDI_Orcl_Tomcat1p.html

 

1) Modify the server.xml file
In<CATALINA_HOME>/conf/server.xml between <GlobalNamingResources> and </GlobalNamingResources> add the following

   <Resource name="jdbc/<alias>"

   auth="Cont   ainer"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@<host>:<port>:<sid>"

   [user=<user>]

   [password=<password>]

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

   

 

Example

<!-- Global JNDI resources -->

 <GlobalNamingResources>

 

 <!-- Test entry for demonstration purposes -->

 <Environment name="simpl   eVal   ue" type="java.lang.Integer" value="30"/>

 

 <!-- Editable user database that can also be used by

   UserDatabaseRealm to authenticate users -->

 <Resource name="UserDatabase" auth="Container"

   type="org.apache.catalina.UserDatabase"

   description="User database that can be updated and saved"

   factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

   pathname="conf/tomcat-users.xml" />

    <!-- Every connection to 'db1' uses the same user -->

 <Resource name="jdbc/db1"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db1"

   user="scott"

   password="tiger"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

    <!-- Every connection to 'db2' must provide a username and password -->  <Resource name="jdbc/db2"

   auth="Container"

   type="oracle.jdbc.pool.OracleDataSource"

   driverClassName="oracle.jdbc.driver.OracleDriver"

   factory="oracle.jdbc.pool.OracleDataSourceFactory"

   url="jdbc:oracle:thin:@oracle.microdeveloper.com:1521:db2"

   maxActive="20"

   maxIdle="10"

   maxWait="-1" />

</GlobalNamingResources>

 

2) Modify the context.xml file
In <CATALINA_HOME>/conf/context.xml between <Context> and </Context> add the following for each entry in the JNDI resource list:

<ResourceLink global="jdbc/<alias>" name="jdbc/<alias>" type="oracle.jdbc.pool.OracleDataSource"/>

 

Example

<!-- The contents of this file will be loaded for each web application -->

 <Context>

 

 <!-- Default set of monitored resources -->

 <WatchedResource>WEB-INF/web.xml</WatchedResource>

 <WatchedResource>META-INF/context.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->

 <!--

 <Manager pathname="" />

   -->

 <ResourceLink global="jdbc/db1" name="jdbc/db1" type="oracle.jdbc.pool.OracleDataSource"/>

 <ResourceLink global="jdbc/db2" name="jdbc/db2" type="oracle.jdbc.pool.OracleDataSource"/>

 </Context>

 

3) Modify the context's web.xml file (5.0.x step only - not necessary for 5.5.x)
In the <CONTEXT>/WEB-INF/web.xml between <web-app> and </web-app> add the following:

<resource-ref>

   <description><Your Description></description>

   <res-ref-name>jdbc/<alias></res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

Example

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db1</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

<resource-ref>

   <description>Oracle Development Datasource</description>

   <res-ref-name>jdbc/db2</res-ref-name>

   <res-type>oracle.jdbc.pool.OracleDataSource</res-type>

   <res-auth>Container</res-auth>

</resource-ref>

 

 

4) Restart Tomcat

 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:15
반응형

Apache 2 + Tomcat 5.x mod_jk 1.2 연동시 한글 문제


Apache 2 + Tomcat 5.x mod_jk 1.2 연동시 GET 방식으로 넘어온 파라미터의 한글이 몽땅 깨져버리는 문제가 발생합니다.

이 문제의 해결 책은

<Connector port="8009"
enableLookups="false" redirectPort="8443" debug="0"
protocol="AJP/1.3" URIEncoding="euc-kr"/>

server.xml의 jk 커넥터 부분에도 URIEncoding을 추가해주는 것입니다. 

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:14
반응형

1. $TOMCAT_HOME/conf/server.xml(Tomcat4) or

    $TOMCAT_HOME/conf/Catalina/host/context.xml(Tomcat5)


   <Resource name="jdbc/obcon" auth="Container" type="javax.sql.DataSource"/>
   <ResourceParams name="jdbc/obcon">
        <parameter>
            <name>username</name>
            <value>club</value>
        </parameter>
        <parameter>
            <name>password</name>
            <value>obcl</value>
        </parameter>
        <parameter>
            <name>driverClassName</name>
            <value>oracle.jdbc.driver.OracleDriver</value>
        </parameter>
        <parameter>
            <name>url</name>
            <value>jdbc:oracle:thin:@172.16.1.17:1526:ORA8</value>
        </parameter>
        <parameter>
            <name>removeAbandoned</name>
            <value>true</value>
        </parameter>
        <parameter>
            <name>removeAbandonedTimeout</name>
            <value>60</value>
        </parameter>
        <parameter>
            <name>logAbandoned</name>
            <value>true</value>
        </parameter>
        <parameter>
            <name>maxActive</name>

            <value>20</value>
        </parameter>
        <parameter>
            <name>maxIdle</name>
            <value>10</value>
        </parameter>
        <parameter>
            <name>minIdle</name>
            <value>5</value>
         </parameter>
        <parameter>
            <name>maxWait</name>
            <value>10000</value>
        </parameter>
    </ResourceParams>


2. $WEB_ROOT/WEB-INF/web.xml


    <resource-ref>
        <res-ref-name>jdbc/obcon</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>


** jdbc jar 파일이 $TOMCAT_HOME/common/lib 에 위치할 것.

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:06
반응형

DBCP의 POOL 상태를 모니터링 하는 페이지

톰캣에 default 로 설치된 dbcp 라이브러리를 이용하면 org.apache.tomcat.dbcp.dbcp.*

이고 일반적인 dbcp를 다운받아 사용할경우 org.apache.commons.dbcp.* 로 import 하도록 한다.


<%@ page language="java" contentType="text/html; charset=EUC-KR" %>
<%@ page import="
    javax.naming.*,
    javax.sql.*,
    org.apache.tomcat.dbcp.dbcp.*"
%>
<%
 Context initContext = new InitialContext();
 Context envContext  = (Context)initContext.lookup("java:/comp/env");
 DataSource ds   = (DataSource)envContext.lookup("jdbc/mydb");
 
 BasicDataSource bds = (BasicDataSource)ds;
 String dbname  = "caelum";
 
 try {
   int bdsNumActive  = bds.getNumActive();
   int bdsMaxActive  = bds.getMaxActive();
   int bdsNumIdle   = bds.getNumIdle();
   long bdsMaxWait  = bds.getMaxWait();
   
   String fontcolor  = "";
   
   if (bdsNumActive <= 400) {
    fontcolor = "<font color='green'>";
   } else if (bdsNumActive > 400 && bdsNumActive <= 500) {
    fontcolor = "<font color='orange'>";
   } else {
    fontcolor = "<font color='red'>";
   }
%>
   <table cellpadding='3' cellspacing='0' border='1'>
    <tr>
     <td colspan='4' align='center'><b><%=dbname%></b> DataSource</td>
    </tr>
    <tr>
     <td height='24' align='center' alt='connections that are processing'># Active Connections</td>
     <td height='24' align='center' alt='total size of pool'>Maximum Active Connections</td>
     <td height='24' align='center' alt='connections that are idle in the pool'># of Idle Connections</td>
     <td height='24' align='center'>Maxium Wait period before timeout</td>
    </tr>
    <tr>
     <td align='right'><%=fontcolor%><%=bdsNumActive%></font></td>
     <td align='right'><%=bdsMaxActive%></td>
     <td align='right'><%=bdsNumIdle%></td>
     <td align='right'><%=bdsMaxWait%></td>
    </tr>
   </table>
<%
 } catch(Exception e) {
  out.println(e.toString());
 }
%>

Posted by 1010
98..Etc/Tomcat2009. 6. 27. 01:05
반응형

Tomcat 5.5에서는 기존에 사용하던 ResourceParams 태그를 지원하지 않습니다.

대신 다음과 같이 설정합니다.


- server.xml

 <Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"
   maxActive="100"
   maxIdle="30"
   maxWait="10000"
   username="test"
   password="1234"
   driverClassName="com.mysql.jdbc.Driver"
   url="jdbc:mysql://localhost:3306/test?autoReconnect=true"
   removeAbandoned="true"
   removeAbandonedTimeout="60"
   logAbandoned="true"
 />

<Context ~>

<ResourceLink name="jdbc/mydb" global="jdbc/mydb" type="javax.sql.DataSource"/>

</Context>


-web.xml

  <resource-ref>
   <description>Oracle Datasource example</description>
   <res-ref-name>jdbc/mydb</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
 </resource-ref>

Posted by 1010
01.JAVA/Java2009. 6. 27. 00:41
반응형

1. 배열 요소의 사용을 자제하라.
   - JVM은 배열의 Index에 대해 경계검사(bound-checking)을 하므로, 부하가 커진다.

접기

  for (int i=0; i<Repeat; i++)
    countArr[0] += 10;
  ==>

  count = countArr[0];
  for(int i=0; i<Repeat; i++)
    count+=10;
  countArr[0]=count;

접기


2. 메소드의 호출로 반복문을 종료하지 마라.

접기

 for(int i=0; i<collection.size(); i++)
  ==>

  int max = collection.size();
  for(int i=0; i<max; i++)

접기


3. 인덱스 변수에는 int형을 사용하라
  - JVM은 int형에 최적화되어있다, 다른형을 사용할 경우 int로 암시적 캐스팅을 유발한다.

더보기


4. 효율적인 비교
   - JVM은  -1,0,1,2,3,4,5로 비교하는것에  최적화 되어있다

더보기

 5. 숏서킷 연산을 앞쪽에 두어라
   - a || b,  a && b 연산자는 앞의 조건을 통과해야 뒤의 조건절도 수행한다.

더보기


6. 반복문 안에서는 리플렉션(java.lang.reflect)의 사용을 자제하라  
   ==> 직접 메소드를 실행하는 경우에 비해서 느리다

※ 참고 : 자바 퍼포먼스 튜닝 : 성능 향상을 위한 205가지 핵심 기법
             7장. 반복문,스위치,재귀

Posted by 1010
반응형


2004년에 만들어 사용했던거...
Posted by 1010
카테고리 없음2009. 6. 27. 00:15
반응형


지금 보니 좀 유치하긴 하다..ㅎㅎ

서비스로 사업계획서 작성 가이드 라인 파일들...






Posted by 1010
반응형
Posted by 1010
02.Oracle/DataBase2009. 6. 26. 23:54
반응형
Posted by 1010
01.JAVA/Java2009. 6. 26. 23:14
반응형
1. 프로그램의 최적화 원칙

q        80/20 : 이것은 프로그램 수행 시간의 80% 실제 프로그램 코드의 20% 잡아먹는다는 것을 의미합니다. 때문에 실제 프로그램 코드 수행 시간의 80% 차지하는 일부 코드를 찾는 일이 중요하다는 것입니다.

q       빠른 알고리즘: 같은 프로그램이라도 수행하는 프로그램을 번만 수행해도 되도록 코딩 한다면 훨씬 빠르겠죠. 평소에 다양한 로직으로 프로그램을 보고, 어떻게 하면 간결하고 빠르게 돌아가는 코드를 만들 있을지를 많이 궁리해야 하겠습니다.

q       가벼운 데이터 구조: 리소스를 적게 사용하는 것이 훨씬 빠르게 작동한다는 것은 당연한 이치일 것입니다. 불필요하게 메모리를 많이 쓰는 코딩은 지양합니다.

q       가독성과 최적화: 프로그램의 최적화를 중요시 할지, 가독성을 중요시 할지를 판단해야 합니다. 다음 예제 1 가독성과 최적화의 딜레마라 있습니다.

   예제 1

   x >> 2 또는 x / 4,

   x << 1 또는 x * 2

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 


 

1.1.  자바에서 String 생성되면 변하지 않는 성질(immutable) 가지고 있습니다.

따라서 스트링들 사이에 + 연산을 수행하면 새로운 스트링을 생성하고,

양쪽 스트링의 내용을 복사한 후 앞의 스트링을 가비지 컬렉션합니다.

이에 따른 부하가 많아지므로 스트링의 연산이 필요할 경우,

String 대신 고정적이지 않은 StringBuffer를 사용하는 것이 좋습니다

(String 결합은 과도한 쓰레기와 array 복사를 일으킨다.)

 

q     String s = “hi ” + “Mr. ” + “ ” + “Buddy!”;

문자열을 컴파일할 때 완전히 결정 할 수 있다면, 연결연산자가 StringBuffer 사용보다 효율적입니다.

컴파일 할 때 결정할 수 없다면(런타임시 결정) StringBuffer를 이용하는 것이 효율적입니다.

 

q     StringBuffer 버퍼 크기 초기값을 생략하면 불필요한 resizing 일으킬 있습니다.

(정확한 크기를 모른다면 그냥 두는 것이 나음)

 

StringBuffer sb = new StringBuffer();

sb.append("aaa" + "\n");

는 불필요한 스트링 연결작업으로  성능을 저하시킵니다

sb.append("aaa").append("\n");

 

sb.append("\n");

String을 추가하는 것보다 char를 추가하는 것이 빠릅니다

sb.append('\n');

 

setLength라는 메쏘드를 통해서 객체를 새로 생성하지 않고서 계속 사용할 수 있습니다.

StringBuffer sb=new StringBuffer();

sb.append("Hello");

System.out.println(sb.toString());

sb.setLength(0);

sb.append("World");

System.out.println(sb.toString());

 

StringBuffer는 동기 StringBuilder는 비동기방식이다

 

q     문자열을 분석해서 분할해야하는 경우. 보통은  StringTokenizer 객체를 쓰게된다. 하지만 클래스는 내부적으로.. 굉장히 무거운 클래스이다.. 왜냐하면. 이전에 분할한 정보를 가지고 있기 때문이다.. 따라서 단순히 앞으로 나가면서 잘라내기만을 시도할 문자열은 간단히 스스로 구현하여 쓰도록 하자


 

스트링비교할때

 

if (name.compareTo("John") == 0) ...

if (name == "John") ...

if (name.equals("John")) ...

if ("".equals(name)) ...

 

위의 비교중 잘못된 것은 없지만 좋은것도 없다.

q     compareTo 메소드는 너무 거창하고 장황하다.

q     == 연산자는 object identity 테스트하는 것으로 (--> 동일한 object인지 체크) 아마도 여러분이 원하는 것이 아닐 것이다.

q     equals 메소드가 가야할 길이지만, 상수와 변수를 거꾸로하면 name null 때도 안전하며 추가로 loop안에서 사용될 경우 equals 메소드가 항상 동일한 object에서 호출되기 때문에 속도상의 이점을 있다.

q     빈문자열을 테스트할 때는 길이가 0인지 체크하는 것이 빠르다. 이는 equals에서 처음에 hash value 먼저 계산할수도 있기 때문이다.

(--> Sun JDK에서는 길이를 먼저 체크한 후 문자열의 char를 비교하며 hash값을 체크하지 않는다.)

 

if ("John".equals(name)) ...

if (name.length() == 0) ...

 

 

 

 

 

 

 


 

1.2.  for 루프에서 객체를 생성금지. 재사용 매개변수를 보내는 것이 중요하다.

 

임시 객체를 빠른 캐시에 저장하는 C C++와 달리, 자바에서는 메모리의 힙 영역에 객체를 저장합니다.

따라서 임시 객체를 생성할 때마다 힙에 액세스해야 하므로 속도가 느려집니다.

또한 임시 객체에 대한 가비지 컬렉션의 오버헤드가 큽니다.

 

가능한 루프안에서는 객체를 생성하지 말라

스트링 객체를 더하지도 말라 같은 오버헤드가 발생한다

 

루프문이나 자주 불리워지는 메쏘드에서의 객체 생성을 피합니다.

한 개의 employee 객체에 계속 값을 할당하고 지우고 하는 식으로 사용합니다.

for ( int i = 0; i < 100; i++ ) {

             Employee employee = new Employee();

             list.add( employee );

} // end for i

 

Employee employee = null;

for ( int i = 0; i < 100; i++ ) {

             employee = new Employee();

             list.add( employee );

} // end for i

 

 

for 문의 증가값이나. 기본적인 정수의 사용에 있어 int 보다 작은 byte, char, short

사용할려는 경향이 있다 하지만 이것은 오산이다.

 

또한 반복문 내의 비교 상대값을 메쏘드 호출해서 계산해 오는 것이라면 다음처럼 미리 지역 변수에 그 값을 저장한 후에 그것을 사용하는 것이 좋습니다.

for(int k=0; k< s.length(); k++) 보다는

int limit = s.length();

for(int k=0; k < limit; k++)

 

 

 

 

 

1.3. 기타 등등

1.3.1.  Overkill initialization

public class B {

    private String name = null;

}

이 프로그래머는 C로 코딩하는데 익숙하다. 그래서 자연스럽게 모든 변수가 적절하게 초기화되기를 원했다. 하지만 이는 필요하지 않다. 자바 언어 명세서는 멤버 변수가 항상 0이나 null, false 등의 특정 값으로 자동으로 초기화되는 것을 보장한다. 이를 명시적으로 선언함으로써 프로그래머는 constructor에 앞서 클래스 initializer에서 수행되도록 만든다. 이는 불필한 과잉행동으로 피해야한다.

public class B {

    private String name;

}

 

1.3.2. Converting numbers to Strings

"" + set.size()

new Integer(set.size()).toString()

Set.size() 메소드의 반환형은 int이다. 여기서는 String으로 변환하고자 한다. 위의 두 예제는 사실상 변환을 하고 있다. 하지만 첫번째는 불필요한 String 연결 작업을 수행하고, 두번째는 임시로 Integer 래퍼를 생성한다. 변환을 하는 바른 방법은 아래와 같다.

String.valueOf(set.size())

 

1.3.3. Not taking advantage of immutable objects

zero = new Integer(0);

return Boolean.valueOf("true");

Boolean Integer는 불편값이다. 따라서 같은 값을 표시하는 다수의 개체를 생성하는 것은 의미없는 일이다. 이러한 클래스들은 내부에 자주 사용되는 인스턴스에 대한 캐쉬를 가지고 있다. Boolean의 경우 단지 두 개의 인스턴스만이 존재한다. 프로그래머는 이러한 사실을 활용할 수 있다.

zero = Integer.valueOf(0);

return Boolean.TRUE;

 

1.3.4.  etcetera

q     Strength reduction : Shift 연산은 비트 단위로 값을 이동하는 것입니다. 좌로 1비트 이동하면 곱하기 2, 우로 1비트 이동하면 나누기 2 됩니다. 이때 곱하기나 나누기보다 Shift 연산이 훨씬 빠릅니다

x >> 2 또는 x / 4, x << 1 또는 x * 2

(증감연산은 ++ -- +1, -1보다 훨씬 빠르고, shift 연산이 곱셈이나 나눗셈보다 빠릅니다.)

q     Unrolling loops: 반복문 내에서 이상의 연산을 수행함으로써 반복 회수를 줄여 반복 제어의 부하를 줄여 주는 것을 말합니다. 다음예제에서 x배열은 항상 2 배수이기 때문에 제어변수 i 2 증가시키면서 내부에서는 연산을 2 수행합니다. 이는 결과적으로 연산 회수는 같으나 반복제어 회수가 줄어든다는 이점이 있습니다.

double picosy = Math.PI * Math.cos(y);

for (int i = 0; i < x.length; i += 2) {

x[i] *= picosy;

x[i+1] *= picosy;

}

q     new 통한 생성자 호출대신 static 메쏘드를 사용합니다. 다음의 예제 9에서는 Integer 클래스를 생성한 다음 string에서 정수 값을 추출해냈습니다. 예제 10에서는 Object Instance 필요없는 static 메쏘드를 사용했습니다.

 

예제 9

String string="55";

int theInt=new Integer(string).intValue();

 

예제 10

String string="55";

int theInt=Integer.parseInt(string);

 

q     캐스팅의 지향

캐스팅을 하면 컴파일 시간에 그 타입이 결정될 수 없기 때문에 실행 시간을 느리게 만듭니다. 인터페이스를 캐스팅할 경우 더욱 많은 실행 시간을 필요로 하게 됩니다. 이를 위해서 같은 객체를 여러 번 캐스팅할 필요가 있을 경우 지역 변수에 저장해서 사용합니다. 캐스팅을 될 수 있는 한 피하고, 가장 빠른 변수 타입은 int이기 때문에 불가피한 경우를 제외하고는 int를 사용하는 것이 좋습니다.

 

q     빠른 변수 타입의 사용

변수의 성능은 그것의 범위와 타입에 의해서 결정됩니다. 가장 빠른 변수는 지역 메쏘드 변수이며, 가장 빠른 변수 타입은 int와 참조 변수입니다. 또한 어떻게 배열을 초기화시킬지가 중요한 요소가 됩니다. 다차원 배열로 정의할 경우 매번 생성자를 호출하기 때문에 꼭 필요한 경우가 아니면 다차원 배열로 정의하지 않습니다. 배열이 지역변수일 경우 메쏘드 호출시 매번 초기화를 수행하므로, 배열을 static으로 선언하면 초기화가 반복되는 것을 제거할 수 있습니다

 

 

1.4.  Collection 객체의 크기를 필요한 만큼 크게 잡는다

Ex) Vector의 크기를 증가하는 방법은

더 큰 크기의 내부 배열 객체를 생성 -> 이전 배열에서 새로운 배열로 새롭게 복제

 -> 이전 배열을 삭제

하는 방법으로 크기를 증가 시킨다 따라서 Colloection 을 가능한 큰 크기로 잡아두는 것이 좋다

 

 

1.5.  참조변수 유지보다 고정변수?

 

1.6. Thread Connection  오버헤드가 매우크므로 스레드풀과 커넥션풀을 사용하라
- VectorPoolManager - Collection
재사용

 

 

1.7.  Vector 사용후 Size 0으로 설정한다. 참조가 없기때문에 레퍼런스가 제거된다.

 

 

1.8.  객체의 정규화

  - 많은 객체의 사본을 몇 개의 객체로 대체한다.

  - Boolean의 정규화

  - 자주 사용하는 Integer의 정규화

  - "" 공백 또는 요소없는 배열, Date 객체

  - String.intern()을 통하여 정규화가 가능하다.

 

 

 

1.9.  Reference 객체 사용.

  - WeakReference를 사용하여 메모리가 부족하면 레퍼런스 객체는 가비지 컬렉션되면서 초기화된다.

  - 가비지 컬렉션이 되었다면 그 객체는 null이 된다.

  - 재사용하고 싶으나 곧바고 필요하지 않는 객체를 메모리에 유지할 수 있다 하지만 부족해지면

    우선적으로 가비지 컬렉션 된다.

 

1.10.  상수는 정수로 사용하자.

 

1.11.  String 정수를 int 변환시 객체 생성이 아닌 ParseInt 사용하자.

 

1.12.  자료형을 변환할때

 

"" + set.size()

new Integer(set.size()).toString()

 

Set.size() 메소드의 반환형은 int이다. 여기서는 String으로 변환하고자 한다.  위의 두 예제는 사실상 변환을 하고 있다.

하지만 첫번째는 불필요한 String 연결 작업을 수행하고,

두번째는 임시로 Integer 래퍼를 생성한다. (참고. Integer.toString() 함수는 static 함수가 아니다)

 

String.valueOf(set.size())

 

 

zero = new Integer(0);

return Boolean.valueOf("true");

 

Boolean Integer는 불편값이다. 따라서 같은 값을 표시하는 다수의 개체를 생성하는 것은 의미없는 일이다.

이러한 클래스들은 내부에 자주 사용되는 인스턴스에 대한 캐쉬를 내부에 가지고 있다.

Boolean의 경우 단지 두 개의 인스턴스만이 존재한다. 프로그래머는 이러한 사실을 활용할 수 있다.

 

zero = Integer.valueOf(0);

return Boolean.TRUE;

(이 메소드(valueOf) 가 빈번하게 요구되는 값을 캐쉬하므로 new Integer보다 비용이 훨씬 적음)

 

 

1.13.  기타등등

 

public class B {

    private int count = 0;

    private String name = null;

    private boolean important = false;

}

이 프로그래머는 C로 코딩하는데 익숙하다. 그래서 자연스럽게 모든 변수가 적절하게 초기화되기를 원했다.

하지만 이는 필요하지 않다. 자바 언어 명세서는 멤버 변수가 항상 0이나 null, false 등의 특정 값으로 자동으로 초기화되는 것을 보장한다.

이를 명시적으로 선언함으로써 프로그래머는 constructor에 앞서 클래스 initializer에서 수행되도록 만든다.

이는 불필한 과잉행동으로 피해야한다.

public class B {

    private int count;

    private String name;

    private boolean important;

}

 

 

Collection l = new Vector();

for (...) {

   l.add(object);

}

Vector는 동기화된 ArrayList이다. 그리고 Hashtable은 동기화된 HashMap이다. 두 클래스는 동시 접근이 필요한 경우만 사용되어야 한다.

만약 이러한 컬렉션 클래스가 로컬 변수로 일시적으로 사용될 때는 동기화가 필요없으며, 이는 성능을 저하시킬 수 있다.

Collection l = new ArrayList();

for (...) {

   l.add(object);

}

 

 

// returns [1]: Location, [2]: Customer, [3]: Incident

bject[] getDetails(int id) {...

 

설령 문서화되었다 해도, 이런 종류의 메소드의 값 반환은 다루기 난처하고 에러를 쉽게 유발한다.

여러분은 반드시 이 값들을 담는 작은 클래스를 선언해서 사용해야 한다. 이는 C struct와 유사하다.

Details getDetails(int id) {...}

 

private class Details {

    public Location location;

    public Customer customer;

    public Incident incident;

}

 

 

1.14. 성능 확인표

대부분의 제안은 병목점을 확인한 후에만 적용이 가능하다.

. 메모리 문제가 있는지 확인한다.

. 특히 루프에서 사용하는 임시 객체의 개수를 줄인다.

- 자주 사용하는 메소드에서 임시 객체의 생성을 피한다.

- 컬렉션 객체의 크기를 미리 설정한다.

- 가능하면 객체를 재사용한다.

- 재사용하기 전에 컬렉션 객체를 비운다(너무 크지 않다면 용량을 줄일 필요

는 없다) .

- 데이터 타입간의 변환에서 임시 객체의 생성을 줄일 수 있는 메소드를 사

용한다(특히 스트링과 스트림) .

- 메소드가 객체를 리턴하기 보다는 재사용 가능한 객체를 매개변수로 받도

록 정의한다.

- 가능하면객체를 정규화한다.'=='연산자로 정규화한 객체를비교한다.

- (그 개수가 별로 많지 않다면) 클래스가 필요한 개수의 객체만 생성한다.

- 스트링과 다른 객체를 int 상수로 대체한다. '=='연산자로 비교한다.

- 객체 대신에 원시 데이터 타입을 사용한다.

- 메소드를 사용하기 위해 객체 생성하는 것을 피한다.

- 내포하는 객체를 줄이기 위해 여러 객체를 묶는다.

- 큰 사이즈의 객체 컬렉션은 배열을 사용하여 미리 할당한다.

- 스트링 연결 연산자(+) 대신에S t r i n g B u ff e r를 사용한다.

- 사본을 생성하지 않고 직접 객체를 변경하는 메소드를 사용한다.

- 원시 데이터 타입을 직접 사용하는 클래스를 사용한다.

? T h r e a d L o c a l을 사용하여 싱글톤에 접근하는 것을 고려한다.

? f i n a l을 사용하여 변수의 변경을 방지한다.

? We a k R e f e r e n c e를 사용하여 정규화용 테이블을 유지한다(캐시는 S o f t R e f e r e n c e를 사용한다) .

? 객체 생성 병목점을 객체 생성 방식을 변경하여 줄인다.

─ 생성자를 간단하게 유지하고 상속을 너무 깊이 하지 않는다.

─ 한 번 이상의 변수 초기화를 피한다.

c l o n e() 메소드를 사용하여 생성자의 사용을 피한다.

─ 배열의 생성이 더 빨라질 수 있다면 복제한다.

─ 간단한 배열은 초기화가 더 빠르고, 복잡한 배열은 복제가 더 빠르다.

? 객체 생성에 의한 성능 저하는 생성 시간을 변경하여 제거한다.

─ 객체를 미리 생성하여 필요할 때까지 유지한다.

─ 사용하지 않는 객체나 변수가 있거나 나누어서 생성할 필요가 있을 경우

에는 추후 초기화 기법을 사용한다.

─ 디자인에서 필요하거나 추후 초기화로 성능을 향상시킬 수 있을 경우에만

추후 초기화를 사용한다.

Posted by 1010