728x90

예전 카페에서 폐지 공지가 와서 자료를 옮겨 놓습니다.

이때도 찾는 귀찮니즘에 적어 놓았던거 같네요.

 

누계를 얻고자 할때 사용
 
select
   web
   ,sum(web) over (order by rownum) as web_inc_sum
from
   webPageCnt
728x90
728x90

예전 카페에서 폐지 공지가 와서 자료를 옮겨 놓습니다.

 

여러 테이블을 사용한 레코드 처리
 
join 하나 이상의 테이블에서 동시에 검색
intersect 검색된 결과에서 공통된 레코드 검색
minus 검색된 결과에서 서로 공통된 레코드 삭제
union 검색된 결과에서 모든 레코드의 종류 검색
union all 검색된 결과에서 모든 레코드 검색
 
사용가능한 함수
1. 일반함수
ascii ()	해당문자를 ascii코드값으로 변환
chr()	ascii 코드값에 해당하는 문자로 변환
concat ()	문자열의 결합
Greatest()	가장 작은 값 출력
initcap()	첫글자만 대문자로 출력
least()	가장 작은 값 출력
length()	문자열의 크기 출력
lower()	소문자로 변환
lpad()	왼쪽을 기준으로 임의의 문자열 추가
ltrim()	왼쪽을 기준으로 임의의 문자열 삭제
replace()	임의의 문자열을 다른 문자열로 변환
rpad()	오른쪽을 기준으로 임의의 문자열 추가
rtrim()	오른쪽을 기준으로 임의의 문자열 삭제
substr()	임의의 위치에서 임의의 길이만큼의 무자열 삭제
upper()	대문자로 변환
vsize()	문자열의 크기 출력
2.날짜함수
add_months() 월의 덧셈 기능
last_day() 해당 월의 마지막 일자 출력
months_between() 임의의 날짜 사이의 차이값 출력
next_day 임의의 날짜에서 다음주의 특정 일자 출력
sysdate() 현재 시스템의 날짜
728x90
728x90

예전 카페에서 폐지 공지가 와서 자료를 옮겨 놓습니다.

 

<<<<<<<<<<<<<<<< Any >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
select ~ from ~ where ~ 컬럼 = any ( select 문장 )
select ~ from ~ where ~ not 컬럼 = any ( select 문장 )
 
select usmo, usmame, usrarea
   from forumusrlist
 where usrkindcode = any (select kindcode from forumtbl );
 
<<<<<<<<<<<<<<<< Exists >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
select ~ from ~ where ~ exists ( select문장 )
 
select usmo. usmame fromforumusrlist
 where exists (select * from forumtb );
 
<<<<<<<<<<<<<<<< Some >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
select ~ from ~ where ~ 컬럼 = some ( select 문장 )
 
<<<<<<<<<<<<<<<< Case>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
select
(case 필드명
when 1 then '01'
 else '02'
 end) as pcard_stat
from table_name
<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CREATE TABLE test
(
  MEMBER_ID       VARCHAR2(20 BYTE)             NOT NULL,
  REGIST_DTIME    VARCHAR2(14 BYTE),
  CCC_WEB_ID      VARCHAR2(20 BYTE),
  CCC_WEB_PASSWD  VARCHAR2(45 BYTE)
)

ALTER TABLE test RENAME COLUMN CCC_WEB_ID TO WEB_ID
ALTER TABLE test RENAME COLUMN CCC_WEB_PASSWD TO WEB_PASSWD
 
ALTER TABLE test  drop column REGIST_DTIME;
728x90
728x90

예전 카페에서 폐지 공지가 와서 자료를 옮겨 놓습니다.

오래된 자료라 출처가 정확하게 남아 있지 않은 부분도 있고 현행화가 안되어 있으니 참고 바랍니다.

문제가 되는 글이 있다면 알려주시기 바랍니다.

 

 

데이터 마이닝

더보기

데이터 마이닝  

데이터마이닝 데이터웨어하우스(Datawarehouse)라는 것이 있다. 이를 축소한 개념으로 보면 이해하기 편할 것 같다. 나 자신도 이에 대해선 잘 알지 못하므로 정보공유차원에서 이해하기 쉽게 설명한 글이 있어 적어본다. 이 글은 pcLine 98년 8월호의 해외뉴스란에 실렸던 글이다. 이에 대한 좀더 자세한 내용은 마이크로소프트웨어 99년 8월호를 참고하면 도움이 될 것이다.

데이터마이닝 기술은 기업정보 전략의 핵심 기존의 이른바 데이터베이스는 재고관리나 수주 발주 등 주로 기업의 기간업무를 위한 틀짜기를 정비해서 데이터를 모아왔다. 이런 방식은 복수의 온라인 단말기에서 데이터를 추가하거나 갱신하는 트랜잭션 처리를 강화하고, 대량의 데이터를 신속하게 일괄 처리가 가능한 장점이 있었다. 다만, 목적에 대응해서 개별시스템으로 나눠져 구축되기 때문에 담당 부문이나 상품, 시기, 지역이라는 자유로운 구분 단위로 데이터를 추출하고, 종합적으로 분석하는 이용형태로 대응하기에는 무리가 있었다. 이에 배해 요즘 유행하고 있는 데이터 웨어하우스(datawarehouse)는 틀짜기에 불문하고 사용자 자신이 필요한 정보를 자유자재로 추출하고 분석하는 것을 주목적으로 하고 있다. 데이터의 형식이나 구조를 누구라도 알 수 있게 정리해두고, 즉 마케팅이나 경영전략에서도 의사결정 지원을 위한 특화된 데이터베이스가 데이터 웨어하우스라고 할 수 있다. 데이터 웨어하우스에는 일상의 기업활동에서 발생하는 각종의 데이터들이 시간 단위로 보존된다. 정기적으로 기간 데이터베이스의 데이터를 재편성해서 전송하거나 또는 인터넷을 통해서 수집한 고객정보 등도 집약되어 과거에서 현재에 이르는 데이터가 축적되는 것이다. 그리고, 그 용량은 수뱍 기가에서 테라바이트 급에 이르는 경우가 다반사다.그렇지만 이 정도로 데이터의 용량이 거대해지면 이를 어떻게 분석할 것인지가 큰 문제로 대두된다. 경영이나 마케팅에 도움이 되는 전략을 얼마나 기능적으로 이끌어 낼 것인가? 문제의 핵심은 이용 기술에 있다. 이 가운데 가장 주목을 끄는 것이 바로 데이터 마이닝(data mining)기술이다.

맥주와 일회용 기저귀를 같이 사는 남성 고객
'데이터 마이닝'은 광산에서 금속의 광맥을 채굴(mining)하는 작업에서 유래된 단어이다. 대량의 데이터 속에서 명확하게 보이지 않는 법칙성이나 데이터 사이에 인과 고나계를 발견하자는 것이 데이터 마이닝의 목적이다. 즉, 이를 이용하면 대량의 매상 정보중에서 '5만 엔 이상의 상품중 동시에 구입될 가능성이 큰 것은 어떤 상품인가?'라는 비지니스법칙을 자동으로 추출할 수 있다는 뜻이다.
물론, 초대용량의 데이터에서 분석을 다양하게 행하거나 숨겨져 있는 인과 관계를 발견하는 것은 기종의 분석가들도 해왔던 작업이다. 그러나 이제까지는 가설을 세우고 입증하는 작업을 몇 번씩 반복하지 않으면 안되었고, 대단히 번거로운 일이 아닐 수 없었다. 거기에 데이터 마이닝을 적용하는 것으로 가설을 세운 과정을 반자동화하는 것이 가능하고, 이제까지 일부의 전문가빡에 할 수 없었던 고도의 분석을 누구라도 할 수 있게 된다. 게다가 분석 전문가들조차도 파악하지 못했던 사실을 발견할 수 있을지도 모른다.
이해하기 쉽게 예를 들자면(타이핑하는 사람왈: 이해하기 쉽구나!! ) 수퍼마켓의 영수증에 입력된 데이터를 분석한 결과 퇴근길의 남성고객이 맥주와 일회용 아기 기저귀를 동시에 구입해서 돌아가는 경우가 예상 외로 빈도수가 옾았다. 이런 가능성이 높은 곡개층을 추출해 다이렉트 메일의 접속률을 높인다거나 취소에 따른 고객 감소를 예측해서 사전에 대책을 강구한다는, 여러 가지 대응 방법을 생각할 수 있다.
또한, 데이터 마이닝의 새로운 동향으로 기간 데이터 베이스에서 추출한 수치 중심의 데이터뿐만 아니라 문서정보를 분석하는 것을 목적으로 한 데이터 마이닝도 등장하고 있다. 본래 문서중에는 각종 지식이 내재돼 있다. 이것을 다차원 공간에 전개하는 것에 의해 단어간의 관련도를 분석하는 것이다.
예를 들면 신문 1년치 문서정보에는 약 10만 개 정도의 키워드가 포함돼 있고, O-157의 문제를 다룬 기사 중에서는 병원성 대장균이나 식중독, 학교 급식이라는 단어가 자주 출현하는 것을 알 수 있다. 이렇게 해서 연상게임처럼 관련 있는 깊은 어군을 시스템이 자동적으로 학습해가는 것이다.
이를 마케팅에 활용한다면 전화센터에서 받은 곡개으로부터 문의 전화의 이력이나 앙케이트등을 자동으로 분석할 수 있다. 알고 싶었던 것에 대해서 곡개이 어떤 단어나 표현을 사용해서 접근했는지를 파악하는 것이 가능하다. 게다가 날짜와 시간의 데이터를 분류의 축으로 더해서 시같대별의 변화를 읽어 내거나 고객의 개인정보를 적용하는 것에 의해 '어떤 속성을 가진 고객이 무엇을 알고 싶어하는가'를 신속하게 분석할 수 있다.
예컨대, 곡개의 '살아있는 소리'를 짚어가면서 거기에 묻혀 있는 의도나 필요를 두드러지게 할 수 있는 것이다. 경영자나 마케팅 담당자는 그 결과를 다음 경영방향으로 이끌어갈 수 있다. 앞으로의 기업 전략을 지탱하는 정보 기술(Information Technology)의 핵심으로 데이터 마이닝이 더더욱 그 자리매김을 확실히 해나갈 것임은 자명하다.

PL/SQL코드 숨기기(wrap유틸리티 사용)

더보기

PL/SQL코드 숨기기(wrap유틸리티 사용)

작성자: 강명규
OS: Linux 2.4.18
Oralce: Oracle EE 8.1.7

보통 패키지 스펙의 정의(create or replace package..)는 .sql로,
패키지 body의 정의(create or replace package body ..)는 .plb확장자를 가지며 존재한다.
여기서 .sql은 당연히 pl/sql코드이다. 그러면 .plb는 무엇일까?
이것은 wrap유틸리티에 의해 pl/sql의 소스코드가 암호화(encrypt)된 것을 의미한다.
wrap에 의해 처리되더라도 실제 text로 되어 볼 수는 있지만, 암호화되어 있으므로 소스를 파악할 수는 없다.

C언어에 연관하여 보면, include파일은 일반 텍스트로 되어 있어 함수들의 선언부를 통해 제공되는
함수가 어떤 것들이 있는지 파악할 수 있다. 하지만, 함수의 정의부분인 C소스파일은 컴파일후 라이브러리로
만들어 소스의 내용을 감추는 것과 같다고 하겠다. 

따라서, .sql파일에 패키지 스펙의 정의부분을 두어 제공되는 프로시저, 함수들을 사용자들이 알 수 있게 하고,
패키지 body의 소스부분은 wrap으로 감추어 사용자는 단지 제공되는 패키지의 함수나 프로시저에 대한 사용만
하면 되는 것이다.

왜 암호화하는 것이 필요한 것일까? 다음과 같은 이유가 있을 것이다.

1. 다른 개발자의 PL/SQL 소스변경으로 발생할 수 있는 껀덕지(^^) 제거
2. 사용된 알고리즘을 보여주고 싶지 않다.


설명이 길어졌는데(?) 예를 통해 알아보자.
우선, 간단한 pl/sql코드를 가지고 테스트하겠다.

[kang@ns oracle]$ cat test.sql
create or replace procedure proc_dbakorea_test
is
begin
 dbms_output.put_line('This sample comes from dbakorea.pe.kr');
end;
/ 
[kang@ns oracle]$ wrap iname=test

PL/SQL Wrapper: Release 8.1.7.0.0 - Production on Thu Sep 26 17:44:17 2002

Copyright (c) Oracle Corporation 1993, 2000.  All Rights Reserved.

Processing test.sql to test.plb
[kang@ns oracle]$ sqlplus xxxxx/xxxxx

SQL*Plus: Release 8.1.7.0.0 - Production on Thu Sep 26 17:44:23 2002

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SQL> @test.plb

Procedure created.

SQL> set serveroutput on
SQL> exec proc_dbakorea_test;
This sample comes from dbakorea.pe.kr

PL/SQL procedure successfully completed.

SQL> 

wrap은 상위호환성을 가지므로 하위버전의 오라클에서 컴파일된 plb파일도 상위버전에게 적용될 수 있다. 
즉, 8.1.5에서 컴파일된 plb파일도 8.1.7에서 사용될 수 있다는 것이다.
그럼, 실제 패키지에 대해 간단하게 적용해 보자. 이전에 설명된 pkg_dbakorea패키지를 그대로 사용하겠다.

[kang@ns oracle]$ cat > pkg_dbakorea.sql
create or replace package pkg_dbakorea
as
procedure insert_test(v_id IN TEST.ID%type, v_name IN TEST.NAME%type); 
function print_date return varchar;
end;
/
[kang@ns oracle]$ cat > pkg_dbakorea_body.sql
create or replace package body pkg_dbakorea
as
 procedure insert_test
 (                                                
  v_id    IN TEST.ID%type,  -- ID                 
  v_name  IN TEST.NAME%type  -- 이름              
 )                                                
 is                                               
 begin                                            
  insert into test(id, name) values(v_id, v_name);
  commit;                                         
 end;                                             
 
 function print_date return varchar is
  cur_date varchar(15);                                         
 begin                                                          
  select to_char(sysdate, 'YYYY-MM-DD') into cur_date from dual;
  return cur_date;                                              
 end print_date;                                                

end;
/
[kang@ns oracle]$ wrap iname=pkg_dbakorea_body.sql oname=pkg_dbakorea.plb

PL/SQL Wrapper: Release 8.1.7.0.0 - Production on Thu Sep 26 17:50:22 2002

Copyright (c) Oracle Corporation 1993, 2000.  All Rights Reserved.

Processing pkg_dbakorea_body.sql to pkg_dbakorea.plb
[kang@ns oracle]$ sqlplus xxxxx/xxxxxx

SQL*Plus: Release 8.1.7.0.0 - Production on Thu Sep 26 17:50:34 2002

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SQL> @pkg_dbakorea.sql

Package created.

SQL> @pkg_dbakorea.plb

Package body created.

SQL> select pkg_dbakorea.print_date() from dual;

PKG_DBAKOREA.PRINT_DATE()

 

패키지/함수/프로시저

더보기

패키지/함수/프로시저

작성자: 강명규
OS: Linux 2.4.18
Oralce: Oracle EE 8.1.7


여기서 설명할 것은 패키지하는 방법과 사용법이다.
일반적으로 그냥 프로시저만을 사용하는 경우가 많으나(나도 그렇지만..), 패키지하여 사용하는 것이
여러 부분에서 우월하므로 왠만하면 패키지화하는 습관을 들이는 것이 좋겠다. 뒷부분에 설명하겠다.


함수의 생성과 사용
프로시저는 뭐고 함수는 또 뭔가?
함수는 리턴값이 있고, 프로시저는 없다. 사실 프로시저도 리턴값을 패러미터로 받을 순 있다.
C언어에서의 call by reference정도로 생각하면 되겠다.

현재시간을 알아보게 싶게 2002-9-19과 같이 리턴하는 함수를 만들어 보자.

SQL> create or replace function print_date return varchar is
  2   cur_date varchar(15);
  3  begin
  4   select to_char(sysdate, 'YYYY-MM-DD') into cur_date from dual;
  5   return cur_date;
  6  end print_date;
  7  /

함수가 생성되었습니다.

SQL> select print_date() from dual;

PRINT_DATE()
-------------------------------------
2002-09-19


함수는 위와 같이 사용하면 되겠다. 별다른 설명은 필요없으리라 본다.
그럼 프로시저를 보자.


프로시저의 생성과 사용
test라는 테이블에 데이터를 insert하는 프로시저를 생성하자.
프로시저는 insert, update, delete등에 사용하면 적절하겠다.

SQL> create table test
  2  (id varchar(10), name varchar(10));

테이블이 생성되었습니다.

SQL> create or replace procedure insert_test
  2  (
  3   v_id    IN TEST.ID%type,  -- ID
  4   v_name  IN TEST.NAME%type  -- 이름
  5  )
  6  is
  7  begin
  8   insert into test(id, name) values(v_id, v_name);
  9   commit;
 10  end;
 11  /

프로시저가 생성되었습니다.

SQL> exec insert_test('maddog', '강명규');

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select * from test;

ID         NAME
---------- ----------
maddog     강명규

SQL> rollback;

롤백이 완료되었습니다.

SQL> select * from test;

선택된 레코드가 없습니다.

SQL> 

데이터입력값의 유효성체크와 이에 따른 commit,rollback등 에러처리 추가해 주면 더욱 좋을 것이다.
전체 테이블컬럼을 참조한다면 위의 type대신 rowtype을 사용하는 것도 고려해볼만 하겠다.
예제라 간단하게 했는데, 부족함을 느낀다면 .. 음.. 스스로 하도록 하자.


패키지의 사용
위에서 만든 함수와 프로시저를 하나의 패키지에 담도록 하자.
사실 관련있는 놈들끼리 패키지화 해야 하는데.. 어디까지나 예제이므로 그냥 해 보겠다.

SQL> create or replace package pkg_dbakorea
  2  as
  3  procedure insert_test(v_id IN TEST.ID%type, v_name IN TEST.NAME%type); 
  4  function print_date return varchar;
  5  end;
  6  /

패키지가 생성되었습니다.

SQL> create or replace package body pkg_dbakorea
  2  as
  3   procedure insert_test
  4   (                                                
  5    v_id    IN TEST.ID%type,  -- ID                 
  6    v_name  IN TEST.NAME%type  -- 이름              
  7   )                                                
  8   is                                               
  9   begin                                            
 10    insert into test(id, name) values(v_id, v_name);
 11    commit;                                         
 12   end;                                             
 13   
 14   function print_date return varchar is
 15    cur_date varchar(15);                                         
 16   begin                                                          
 17    select to_char(sysdate, 'YYYY-MM-DD') into cur_date from dual;
 18    return cur_date;                                              
 19   end print_date;                                                
 20  
 21  end;
 22  /

패키지 본체가 생성되었습니다.

그럼, 생성된 패키지내의 프로시저와 함수를 어떻게 사용하는지 보자.

SQL> exec pkg_dbakorea.insert_test('dbakorea','강명규');

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select * from test;

ID         NAME
---------- ----------
maddog     강명규
dbakorea   강명규

SQL> select pkg_dbakorea.print_date() from dual;

PKG_DBAKOREA.PRINT_DATE()
---------------------------------------------------
2002-09-26

SQL> 




오라클 매거진 영문판 2002 1월/2월호를 참고했습니다.

프로시저에 비해 패키지가 왜 우월한가 의문을 가지고 따질 사람이 있을 수 있으므로 함 따져보자.

모듈화
애플리케이션 디자인 용이함
Information Hiding
추가된 기능성
더 좋은 성능


프로시저A는 프로시저B를 호출하는 코드를 가진다고 하자.
그런데 프로시저B의 코드가 변경되면 어떻게 되는가?
프로시저A는 프로시저B의 변경에 영향을 받으므로 재컴파일되어야 한다. 귀찮겠다.
그럼, 패키지를 사용하면 어떻길래? 따지냐.. --; 이주일씨의 명복을 빕니다.

프로시저A를 포함한 패키지PKG_A와 프로시저B를 가진 패키지PKG_B가 있고
PKG_A는 PKG_B의 스펙에 대한 의존성을 가진다고 하자.
이 경우에서, PKG_B의 스펙이나 인터페이스에 대한 변경이 아니라면 PKG_B의 BODY는 PKG_A에 상관없이 변경될 수 있다.

SQL> create or replace procedure B
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> 


위에서 보듯, 프로시저A는 프로시저B를 호출하고 있다. 즉, 의존성을 가지고 있겠다.
당연히, 프로시저B를 먼저 생성한 다음 프로시저A를 생성해야 한다. 반대로 해볼까?


SQL> drop procedure B;

프로시저가 삭제되었습니다.

SQL> drop procedure A;

프로시저가 삭제되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

경고: 프로시저 생성시 컴파일 오류가 발생했습니다.

SQL> drop procedure a;

프로시저가 삭제되었습니다.

SQL> 


위에서 보듯이 안된다.
그럼.. 무엇을 말하려고? 음.. 패키지는 그렇지 않다는 것이다.


SQL> create or replace package pkg_a
  2  as
  3   procedure a;
  4  end;
  5  /

패키지가 생성되었습니다.

SQL> create or replace package pkg_b
  2  as
  3   procedure b;
  4  end;
  5  /

패키지가 생성되었습니다.

SQL> 


위에서 패키지에 대한 스펙을 생성했다.
스펙의 생성순서는 상관이 없고 서로 의존성도 가지지 않는다.
그럼 패키지 body를 생성해 보자.

SQL> create or replace package body pkg_a
  2  as
  3   procedure a
  4   is
  5   begin
  6    pkg_b.b;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.

SQL> create or replace package body pkg_b
  2  as
  3   procedure b
  4   is
  5   begin
  6    null;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.


설명 필요없겠다. 위에서 보듯 생성순서는 상관이 없다.
패키지A에 있는 프로시저A는 패키지B의 프로시저B를 호출하고 있지만,
이 시점에서 패키지B의 프로시저B는 존재하지 않는다. 하지만, 상관없다는 것을 알 수 있다.
다시 말하면, 패키지의 스펙에 의존하지만, 패키지의 body에는 의존하지 않음을 알 수 있다.


SQL> col object_type format a15
SQL> col object_name format a10
SQL> col status format a10
SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

선택된 레코드가 없습니다.

SQL> 


그럼 실제 프로시저와 패키지가 변경해서 위에서 말한 내용이 사실인지 확인해 보자.


SQL> create or replace procedure B
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure A
  2  as
  3  begin
  4   B;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> create or replace procedure b
  2  as
  3  begin
  4   null;
  5  end;
  6  /

프로시저가 생성되었습니다.

SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

OBJECT_TYPE     OBJECT_NAM STATUS
--------------- ---------- ----------
PROCEDURE       A          INVALID

SQL> create or replace package body pkg_b
  2  as
  3   procedure b
  4   is
  5   begin
  6    null;
  7   end;
  8  end;
  9  /

패키지 본체가 생성되었습니다.

SQL> select object_type, object_name, status
  2  from user_objects
  3  where status = 'INVALID'
  4  order by object_type, object_name;

OBJECT_TYPE     OBJECT_NAM STATUS
--------------- ---------- ----------
PROCEDURE       A          INVALID

SQL> 

위에서 보듯이 프로시저는 변경에 대해 민감하고(?), 패키지는 둔하다.
고로 패키지가 더 flexible하다 할 수 있겠다.

 

Net8 설정

더보기

Net8 설정

작성자: 강명규

간단한 것인데 이외로 자주 질문되는 부분이이서 이 기회에 정리했다.
오라클 8i를 기준으로 설명하겠다.
오라클이 회사에 설치되어 있고, 집에서 연결하여 사용한다고 하자.
편의상 회사의 컴퓨터(리눅스)를 S, 집에 있는 컴퓨터(윈도)를 C라고 하겠다.

[S의 환경]
OS: Linux 2.4.18
Oralce: Oracle EE 8.1.7
ORACLE_HOME : /u01/app/oracle/product/8.1.7
ORACLE_SID  : db
SERVICE_NAME: db.dbakorea.pe.kr

[C의 환경]
OS: Windows 2000
Oralce: Oracle EE 8.1.7
ORACLE_HOME : C:\oracle\ora81



#####################
S - 서버측(회사)
#####################
오라클 DBMS가 설치된 곳에 $ORACLE_HOME/network/admin/listener.ora를 확인한다.
이 파일은 netca(Net8 configuration Assistant)명령으로도 만들수 있으나, 
수동으로 생성하는 습관을 들이는 것이 좋겠다.
없다면 생성해주면 된다.

우선 initSID.ora파일의 설정을 확인해보자.


[/u01/app/oracle/product/8.1.7/network/admin/initdata.ora]의 일부
db_name = "db"
db_domain = dbakorea.pe.kr
instance_name = db
service_names = db.dbakorea.pe.kr



[oracle@ns admin]$ cat /u01/app/oracle/product/8.1.7/network/admin/listener.ora 
LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 61.74.120.193)(PORT = 1521))
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (ORACLE_HOME = /u01/app/oracle/product/8.1.7)
      (SID_NAME = db)
    )
  )


위에서 수정해줄 부분은 다음과 같다.

HOST : 회사의 컴퓨터 IP주소 (도메인으로 지정하면 문제가 될 수 있으므로 IP주소로 하도록 한다.)
ORACLE_HOME : 오라클이 설치된 홈디렉토리
SID_NAME : ORACLE_SID를 지정한다.


위와 같이 설정했으면 lsnrctl명령으로 리스너를 실행해준다.
물론 오라클도 실행되어 있어야 하겠다.

[oracle@ns admin]$ lsnrctl start

LSNRCTL for Linux: Version 8.1.7.0.0 - Production on 27-JUL-2002 02:47:43

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

Starting /u01/app/oracle/product/8.1.7/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 8.1.7.0.0 - Production
System parameter file is /u01/app/oracle/product/8.1.7/network/admin/listener.ora
Log messages written to /u01/app/oracle/product/8.1.7/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=61.74.120.193)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=61.74.120.193)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 8.1.7.0.0 - Production
Start Date                27-JUL-2002 02:47:43
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  OFF
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/8.1.7/network/admin/listener.ora
Listener Log File         /u01/app/oracle/product/8.1.7/network/log/listener.log
Services Summary...
  db            has 1 service handler(s)
The command completed successfully

자, 이제 서버단에는 모든 준비가 되었다.


#####################
C - 클라이언트측(집)
#####################
집에서 회사의 오라클에 연결하기 위해선 우선 자신의 컴퓨터에도 오라클 클라이언트가 설치되어야 한다.
정확히 말해서 Net8(오라클 7에서는 SQL*NET)이 설치되어야 한다.
오라클 설치시 클라이언트로 설치하면 깔리므로 심각하게 생각할 필요는 없다.

$ORACLE_HOME/network/admin/tnsnames.ora


[C:\oracle\ora81\network\ADMIN\tnsnames.ora]
DBAKOREA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 61.74.120.193)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = db.dbakorea.pe.kr)
    )
  )
    
HOST : 회사의 IP주소
SERVICE_NAME : 서버측 initdata.ora의 service_name패러미터값을 지정


이제 SQL*PLUS에서 DBAKOREA라는 dbalis로 연결하면 되겠다.

D:\>sqlplus scott/tiger@dbakorea



고정IP가 아닌 환경에서의 설정
로컬에 오라클 띄우고 toad로 연결하려면 Net8을 통해 연결해야 합니다.
제가 집에서 사용하는 설정입니다.

[C:\oracle\ora92\network\admin\sqlnet.ora]
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (HOSTNAME)

[C:\oracle\ora92\network\admin\listener.ora]
LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = maddog)(PORT = 1521))
      )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (ORACLE_HOME = C:\oracle\ora92)
      (SID_NAME = maddog)
    )
  )

[C:\oracle\ora92\network\admin\tnsnames.ora]
MADDOG =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SID = maddog)
  )


추가(2002-12-14 3:31오전)
다음은 내가 집에서 설정한 예제이다.
사설IP 192.168.0.2를 가지고 DB는 Oracle 9.2 윈도버전이다.

[listener.ora]
# LISTENER.ORA Network Configuration File: C:\oracle\ora92\network\admin\listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.2)(PORT = 1521))
      )
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = win912db.world)
      (ORACLE_HOME = C:\oracle\ora92)
      (SID_NAME = win912db)
    )
  )


[tnsnames.ora]
WIN912DB =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.2)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = WIN912DB.WORLD)
    )
  )

Oracle Database 생성(8.1.7)

더보기

Oracle Database 생성(8.1.7)

작성자  : 강명규
OS      : LINUX kernel 2.4.18(x86)
ORACLE  : 8i(8.1.7) EE

이번에 DB생성은 8i환경에서 다른 설치옵션(InterMedia, JServer,..)을 모두 제거한 상태에서
svrmgrl에서 수행했다. 기존에 작성한 글은 오라클 8버전을 기준으로 했기 때문에 현재 많이
사용하고 있는 8i버전에 대해 재작성한 것이다.

본인이 테스트용도로 생성하는 DB이기 때문에 되도록 리소스절약을 위주로 설정하여 설치했다.
설치시 환경은 다음과 같다.

메모리: 160MB
CPU   : Celeron (Mendocino) 400
DISK  : Free Space 950MB

ORACLE_BASE: /u01/app/oracle
ORACLE_HOME: /u01/app/oracle/product/8.17
ORACLE_SID : db

보다시피 상당히 서버라고 하기엔 열악하다.
설치시 1GB의 디스크 여유공간을 요구하는 dbassist를 사용하면 위의 환경에서 DB생성은 불가하다.
나는 dbassist를 사용하여 db생성 스크립트를 만들었고, 그 결과로 다음과 같은 파일이 생성되었다.

initdb.ora

dbcreate.sh

dbrun.sh

dbrun1.sh

dbrun2.sh

dbalterTablespace.sh


사실 위의 내용이 전부고 별달리 설명할 것은 없다.
그냥 쉘상에서 dbcreate.sh를 수행해주면 된다.
각 파일이 하는 내용을 보자.


dbcreate.sh
환경변수 ORACLE_SID, ORACLE_HOME를 설정
dbrun.sh -> dbrun1.sh -> dbrun2.sh -> dbalterTablespace.sh순으로 실행


dbrun.sh
create database문 수행
$ORACLE_BASE/admin/db/create/crdb1.log에 실행로그가 기록됨
system tablespace의 datafile 크기를 260MB에서 150MB로 변경했음


dbrun1.sh
$ORACLE_HOME/rdbms/admin/catalog.sql 수행
system 테이블스페이스의 저장옵션 변경
system 을 제외한 나머지 테이블스페이스 생성(system 테이블스페이스는 create database시 수행됨)
롤백세그먼트생성
sys, system사용자의 임시 tablespace를 TEMP tablespace로 설정
$ORACLE_BASE/admin/db/create/crdb2.log에 실행로그가 기록됨

RBS tablespace의 datafile 크기를 516MB에서 50MB로 변경
TEMP tablespace의 datafile 크기를 68MB에서 50MB로 변경
USERS tablespace의 datafile 크기를 104MB에서 50MB로 변경
INDX tablespace의 datafile 크기를 54MB에서 10MB로 변경
USERS,INDX는 사실 필수로 생성해야할 tablespace는 아니다. 내키지 않으면 설치하지 않아도 상관없다.


dbrun2.sh
/u01/app/oracle/admin/db/create/crdb3.log에 실행로그가 기록됨

sys유저로 아래의 스크립트 수행
$ORACLE_HOME/rdbms/admin/catproc.sql
$ORACLE_HOME/rdbms/admin/caths.sql  
$ORACLE_HOME/rdbms/admin/otrcsvr.sql

system유저로 아래의 스크립트 수행
$ORACLE_HOME/sqlplus/admin/pupbld.sql


dbalterTablespace.sh
system사용자의 default tablespace를 tools, temporary tablespace를 temp로 설정



[수행과정]
dbcreate.sh만 실행하면 나머지 과정은 알아서 처리한다.
시스템에 따라 다르겠지만, 1시간정도 걸리니 다른 일을 하고 있는 것이 좋을 것이다.
(나의 경우 30분 정도 걸렸다.)
MS-SQL, MySQL, DB2등 다른 DBMS에 비해 오라클은 DB생성시간이 수십배 걸린다.

[oracle@ns install]$ ./dbcreate.sh



[마무리 작업]
오라클환경변수 설정
/etc/profile.d/myset.sh라는 파일을 만들어 755권한으로 실행가능하도록 변경하고
다음의 내용으로 설정하면 다음 로그인부터 자동으로 오라클 환경설정이 이루어진다.
# Setting for Oracle
export ORACLE_SID=db
export ORACLE_OWNER=oracle
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/8.1.7
export ORACLE_DOC=$ORACLE_HOME/doc
export NLS_LANG=AMERICAN_AMERICA.KO16KSC5601
export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
export TNS_ADMIN=$ORACLE_HOME/network/admin
export EDITOR=vi
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib

system,sys사용자의 암호를 변경, 사용자 생성과 테이블 생성
[oracle@ns 8.1.7]$ sqlplus sys/change_on_install

SQL*Plus: Release 8.1.7.0.0 - Production on Sun Apr 28 15:26:53 2002

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SQL> password
Changing password for SYS
Old password: 
New password: 
Retype new password: 
SQL> conn system/manager
Connected.
SQL> password
Changing password for SYSTEM
Old password: 
New password: 
Retype new password: 
SQL> create user kang identified by xxxxxx
  2  default tablespace users
  3  temporary tablespace temp;

User created.

SQL> grant connect,resource to kang;

Grant succeeded.

SQL> conn kang/xxxxxx
Connected.
SQL> create table test
  2  (        
  3  id varchar(10),
  4  name varchar(10)
  5  );

Table created.

SQL> insert into test values('maddog', '강명규');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test;

ID         NAME
---------- ----------
maddog     강명규

SQL> quit
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production
[oracle@ns 8.1.7]$ 

이상으로 오라클 8i에서 간단한 DB생성을 다루었다.
실제 여러가지 설치옵션을 제거한 것이므로 이를 고려하기를 바란다.

External Table

더보기

External Table

작성자: 강명규
OS: Windows 2000 Advanced Server
Oracle: 9.0.1.0.1
참조문서: Oralce Magazine 2002 1/2월호 EXPERT ADVICE코너의 External Tables: More Than an ETL TOOL

오라클에서 flat file을 테이블처럼 처리하도록 할 수 있게 해주는 것이 external table이다.
flat file이란 그냥 raw data만 있다고 생각하면 되겠다. CSV(Comma Separated Values)파일도 이에 해당한다.
External Table은 9i부터 지원되므로 9i이전에서는 organization external에서 에러가 발생한다.

특징:
virtual read-only table
인덱스 사용 못함(파일처리가 빠르기때문에 필요없음)
OS명령을 통해 insert, update, delete수행
external table간의 조인 가능, external-regular table간의 조인 가능

[e:\etable\emp.dat]
7369,SMITH,CLERK,20
7499,ALLEN,SALESMAN,30
7521,WARD,SALESMAN,30
7566,JONES,MANAGER,20
7654,MARTIN,SALESMAN,30
7698,BLAKE,MANAGER,30
7782,CLARK,MANAGER,10
7788,SCOTT,ANALYST,20
7839,KING,PRESIDENT,10
7844,TURNER,SALESMAN,30
7876,ADAMS,CLERK,20
7900,JAMES,CLERK,30
7902,FORD,ANALYST,20
7934,MILLER,CLERK,10

SQL> conn system/manager
연결되었습니다.
SQL> create directory test_dir as
  2  'e:\etable';

디렉토리가 생성되었습니다.

SQL> create table emp_external
  2  (               
  3   empno char(4),
  4   ename char(10),
  5   job char(9),
  6   deptno char(2)
  7  )
  8  organization external
  9  (
 10   type oracle_loader
 11   default directory test_dir  
 12   access parameters
 13   (
 14    fields terminated by ','
 15    (empno, ename, job, deptno)
 16   )
 17   location ('emp.dat')
 18  );

테이블이 생성되었습니다.

SQL> desc emp_external
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 EMPNO                                              CHAR(4)
 ENAME                                              CHAR(10)
 JOB                                                CHAR(9)
 DEPTNO                                             CHAR(2)

SQL> select * from emp_external;

EMPN ENAME      JOB       DE
---- ---------- --------- --
7369 SMITH      CLERK     20
7499 ALLEN      SALESMAN  30
7521 WARD       SALESMAN  30
7566 JONES      MANAGER   20
7654 MARTIN     SALESMAN  30
7698 BLAKE      MANAGER   30
7782 CLARK      MANAGER   10
7788 SCOTT      ANALYST   20
7839 KING       PRESIDENT 10
7844 TURNER     SALESMAN  30
7876 ADAMS      CLERK     20
7900 JAMES      CLERK     30
7902 FORD       ANALYST   20
7934 MILLER     CLERK     10

14 개의 행이 선택되었습니다.

SQL> select count(*) from emp_external;

  COUNT(*)
----------
        14

SQL> select * from emp_external
  2  where empno=7521;

EMPN ENAME      JOB       DE
---- ---------- --------- --
7521 WARD       SALESMAN  30


조인시의 분석
테이블 A와 테이블 B는 각각 동일하게 20만개의 로우(row)를 가지고 있다.
테이블 A에 조건을 준 select시 20개의 레코드가 반환되고, B또한 동일하다. 
테이블 A와 테이블 B에 대한 조인은 4백만개의 로우수를 access하여 400개의 로우수를 반환한다.
이때 걸린 시간은 3초였다고 한다. - 20만개 레코드를 만들기 귀찮아서 그냥 넘어간다.

emp2_external테이블은 emp2.dat를 참조한다.

SQL> create table emp2_external
  2  (
  3   empno char(4),
  4   ename char(10),
  5   job char(9),
  6   deptno char(2)
  7  )
  8  organization external
  9  (
 10   type oracle_loader
 11   default directory test_dir
 12   access parameters
 13   (
 14    fields terminated by ','
 15    (empno, ename, job, deptno)
 16   )
 17   location ('emp2.dat')
 18  );     

테이블이 생성되었습니다.

SQL> select a.empno, b.job, a.job
  2  from emp_external a, emp_external b
  3  where a.empno = b.empno
  4  and a.empno = 7900
  5  and b.empno = 7900;

EMPN JOB       JOB
---- --------- ---------
7900 CLERK     CLERK


[external table - regular table간의 조인]

SQL> create table emp_regular  
  2  (                           
  3   empno char(4),             
  4   ename char(10),            
  5   job char(9),               
  6   deptno char(2)             
  7  );

테이블이 생성되었습니다.

SQL> insert into emp_regular values(7900, '명규', 'DBA', 50);

1 개의 행이 만들어졌습니다.

SQL> select a.empno, b.job, a.job       
  2  from emp_external a, emp_regular b
  3  where a.empno = b.empno            
  4  and a.empno = 7900                 
  5  and b.empno = 7900;                

EMPN JOB       JOB
---- --------- ---------
7900 DBA       CLERK

하나의 호스트에 2개의 DB인스턴스 실행

더보기

하나의 호스트에 2개의 DB인스턴스 실행

작성자: 강명규
OS: Linux 2.2.14
Oracle: Oracle 8.1.5

dev, dev2 2개의 Database가 있다.
기존 dev라는 DB가 있는 상황에서 dev2를 생성했다.
이는 ORACLE_SID만 주의해서 생성하면 되므로 이에 대한 설명은 생략한다.
설명 요청하면 다시 여기에 적도록 하겠습니다.

리스너설정
[oracle@dev2 admin]$ cat listener.ora
# LISTENER.ORA Configuration File:/u01/app/oracle/product/8.1.5/network/admin/listener.ora
# Generated by Oracle Net8 Assistant

LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dev2.dbakorea.pe.kr)(PORT = 1521))
    (PROTOCOL_STACK =
      (PRESENTATION = TTC)
      (SESSION = NS)
    )
  )

sid_list_listener=
(sid_list=
        (sid_desc=
                (global_dbname=dev.dbakorea.pe.kr)
                (sid_name=dev)
                (oracle_home=/u01/app/oracle/product/8.1.5)
        )
        (sid_desc=
                (global_dbname=dev2.dbakorea.pe.kr)
                (sid_name=dev2)
                (oracle_home=/u01/app/oracle/product/8.1.5)
        )
)

클라이언트측 설정(동일 호스트라 크게 의미는 없다)
[oracle@dev2 admin]$ cat tnsnames.ora 
# TNSNAMES.ORA Configuration File:/u01/app/oracle/product/8.1.5/network/admin/tnsnames.ora
# Generated by Oracle Net8 Assistant

DEV =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev.dbakorea.pe.kr)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = dev.dbakorea.pe.kr)
    )
  )

DEV2 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev2.dbakorea.pe.kr)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = dev2.dbakorea.pe.kr)
    )
  )

DEV2_MTS =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev2.dbakorea.pe.kr)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = dev2.dbakorea.pe.kr)
      (SERVER=SHARED)
    )
  )
  

DB ALIAS(tnsnames.ora - Net8을 이용한 접속)를 이용하여 접속시
[oracle@dev2 admin]$ echo $ORACLE_SID
dev
[oracle@dev2 admin]$ sqlplus system/xxxxxx@dev

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Sep 17 21:06:18 2001

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


Connected to:
Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SQL> select name from v$database;

NAME
---------
DEV

SQL> quit
Disconnected from Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

[oracle@dev2 admin]$ echo $ORACLE_SID
dev
[oracle@dev2 admin]$ sqlplus system/xxxxxx@dev2

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Sep 17 21:07:43 2001

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


Connected to:
Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SQL> select name from v$database;

NAME
---------
DEV2

SQL> 




DB ALIAS없이 접속시(Net8이용하지 않음)
[oracle@dev2 admin]$ echo $ORACLE_SID;         
dev
[oracle@dev2 admin]$ sqlplus system/xxxxxx

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Sep 17 21:10:29 2001

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


Connected to:
Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SQL> select name from v$database;

NAME
---------
DEV

SQL> quit
Disconnected from Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production
[oracle@dev2 admin]$ export ORACLE_SID=dev2
[oracle@dev2 admin]$ echo $ORACLE_SID
dev2
[oracle@dev2 admin]$ sqlplus system/xxxxxx

SQL*Plus: Release 8.1.5.0.0 - Production on Mon Sep 17 21:10:54 2001

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


Connected to:
Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SQL> select name from v$database;

NAME
---------
DEV2

SQL> 




PS>
리스너를 각각 다른 포트로 사용하고 싶으면 다음과 같이 한다.
김영선님꼐서 질문하신 내용이었습니다.


[listener.ora의 내용]

HAHA =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dev.dbakorea.pe.kr)(PORT = 1522))
  )

sid_list_HAHA =
(sid_list=
        (sid_desc=
                (global_dbname=dev.dbakorea.pe.kr)
                (sid_name=dev)
                (oracle_home=/u01/app/oracle/product/8.1.5)
        )
)

HOHO =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev2.dbakorea.pe.kr)(PORT = 1521))
    )
  )


sid_list_HOHO =
(sid_list=
        (sid_desc=
                (global_dbname=dev2.dbakorea.pe.kr)
                (sid_name=dev2)
                (oracle_home=/u01/app/oracle/product/8.1.5)
        )
)



[리스너 기동]

lsnrctl start HAHA
lsnrctl start HOHO


[tnsnames.ora] 의 내용

DEV =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev.dbakorea.pe.kr)(PORT = 1522))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = dev.dbakorea.pe.kr)
    )
  )

DEV2 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = dev2.dbakorea.pe.kr)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = dev2.dbakorea.pe.kr)
    )
  )



[접속]
sqlplus kang/maddog@dev
sqlplus kang/maddog@dev2

 

redo log파일이름 변경

더보기

redo log파일이름 변경

작성자: 강명규
OS: Linux 2.2.14
Oracle: Oracle 8.1.5

새로운 DB를 생성하다가 실수로 redo log file의 이름을 맞지 않게 지정했다.
사용에 지장은 없으나 나의 파일이름에 대한 열망은 참을 수 없었다. ^^


[oracle@dev2 dev]$ pwd
/u01/app/oracle/oradata/dev

기존의 로그파일을 새로운 파일이름으로 미리 복사를 해둔다.
[oracle@dev2 dev]$ cp redotest02.log redodev02.log
[oracle@dev2 dev]$ cp redotest01.log redodev01.log
[oracle@dev2 dev]$ cp redotest03.log redodev03.log

나의 경우는 미리 변경될 이름으로 복사복을 만들어야 rename이 가능했다.
그렇지 않을 경우 다음과 같은 에러가 발생했다.

SVRMGR> alter database rename file '/u01/app/oracle/oradata/dev/redotest02.log' to '/u01/app/oracle/oradata/dev/redodev02.log';
alter database rename file '/u01/app/oracle/oradata/dev/redotest02.log' to '/u01/app/oracle/oradata/dev/redodev02.log'
*
ORA-01511: error in renaming log/data files
ORA-01512: error renaming log file /u01/app/oracle/oradata/dev/redotest02.log - new file /u01/app/oracle/oradata/dev/redodev02.log not found
ORA-27037: unable to obtain file status
Linux Error: 2: 그런 파일이나 디렉토리가 없음
Additional information: 3




[oracle@dev2 dbs]$ svrmgrl

Oracle Server Manager Release 3.1.5.0.0 - Production

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

Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SVRMGR> connect internal
Connected.
SVRMGR> startup mount   
ORACLE instance started.
Total System Global Area                         73997712 bytes
Fixed Size                                          64912 bytes
Variable Size                                     6651904 bytes
Database Buffers                                 67108864 bytes
Redo Buffers                                       172032 bytes
Database mounted.

SVRMGR> alter database rename file '/u01/app/oracle/oradata/dev/redotest02.log' to '/u01/app/oracle/oradata/dev/redodev02.log';
Statement processed.
SVRMGR> alter database rename file '/u01/app/oracle/oradata/dev/redotest01.log' to '/u01/app/oracle/oradata/dev/redodev01.log';
Statement processed.
SVRMGR> alter database rename file '/u01/app/oracle/oradata/dev/redotest03.log' to '/u01/app/oracle/oradata/dev/redodev03.log';
Statement processed.
SVRMGR> select * from v$logfile;
GROUP#     STATUS  MEMBER                                                                          
---------- ------- --------------------------------------------------------------------------------
         1         /u01/app/oracle/oradata/dev/redodev01.log                                       
         2         /u01/app/oracle/oradata/dev/redodev02.log                                       
         3         /u01/app/oracle/oradata/dev/redodev03.log                                       
3 rows selected.
SVRMGR> quit
Server Manager complete.

기존의 로그파일 제거
[oracle@dev2 dev]$ rm redotest0*

 

실수로 데이터파일 삭제시 처리방안

더보기

실수로 데이터파일 삭제시 처리방안

작성자: 강명규
OS: Windows 2000 (intel)
Oracle: Oracle 8.1.7


정석(?)은 full backup을 restore하는 방법입니다.
full backup이 한달전이라면 .. 끔직하죠?
차선의 방안은 해당 데이터파일이 속한 테이블스페이스를 Drop하는 것입니다.
해당 테이블스페이스내의 데이터는 어쩔 수 없습니다. 날라간 거죠
참고로 테이블스페이스내의 데이터파일만 삭제하는 것은 temporary tablespace가 아닌이상 안됩니다.

1. alert.log, DBWR trace file파일을 보면 에러메시지가 있으므로 에러내용을 확인합니다.
   파일삭제로 인한 문제라는 것은 알고 있으므로 그냥 확인만 합니다.
2. svrmgrl를 실행해 connect internal로 로그인합니다.
3. db를 shutdown합니다.
4. db를 startup mount로 시동합니다.
5. alter database datafile '데이터파일이름' offline drop;을 수행합니다.
6. database를 open합니다.
7. 데이터파일이 속한 tablespace를 drop합니다.



다음은 실제 예제입니다.

삭제한 데이터파일:   d:\dd_temp.dbf
해당 테이블스페이스: dd_temp

오라클DB가 shutdown상태에서(온라인상태면 윈도의 경우 데이터파일을 OS에서 삭제할 수 없습니다. 유닉스계열은 삭제가능합니다.) 
그리고 DB를 startup을 합니다. alert.log에는 에러내용이 기록되고, DBWR trace file파일에 좀더 세부적인 에러내용이
기록됩니다. SQL*PLUS연결시 다음과 같은 에러가 발생합니다.

SQL*Plus: Release 8.1.6.0.0 - Production on 월 Sep 17 16:19:13 2001

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


Connected to:
Oracle8i Release 8.1.5.0.2 - Production
With the Java option
PL/SQL Release 8.1.5.0.0 - Production

SQL> connect system/xxxxxx
ERROR:
ORA-01033: ORACLE initialization or shutdown in progress


경고: 이제는 ORACLE에 연결되어 있지 않습니다.
SQL> 


해결방법
이제 oracle계정에서 다음과 같이 합니다.


C:\Documents and Settings\Administrator>svrmgrl

Oracle Server Manager Release 3.1.6.0.0 - Production

Copyright (c) 1997, 1999, Oracle Corporation.  All Rights Reserv

Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SVRMGR> connect internal
암    호:
접속되었습니다.
SVRMGR> shutdown
ORA-01109: 데이터베이스가 개방되지 않습니다
데이터베이스가 마운트 해제되었습니다.
ORACLE 인스턴스가 종료되었습니다.
SVRMGR> startup mount
ORACLE 인스턴스가 시작되었습니다.
시스템 글로벌 영역                         46298380 바이트 합계
Fixed Size                                          70924 바이트
Variable Size                                    20549632 바이트
Database Buffers                                 25600000 바이트
Redo Buffers                                        77824 바이트
데이터베이스가 마운트되었습니다.
SVRMGR> alter database datafile 'd:\dd_temp.dbf' offline drop;
명령문이 처리되었습니다.
SVRMGR> alter database open;
명령문이 처리되었습니다.
SVRMGR> drop tablespace dd_temp including contents;
명령문이 처리되었습니다.
SVRMGR>

모든 것이 정상적(?)으로 되었습니다.

PS>
음.. index tablespace 나 temporary tablespace등과 같이 실제 데이터와는 무관한 테이블스페이스는
위에서 설명한 방식으로 처리한 다음 재생성해주면 좋을 것 같습니다.

 

초간단 트리거강좌

더보기

초간단 트리거강좌

트리거는 insert, update, delete등의 질의가 올때 이의 전/후에서 어떤 작업을 할지
지정할 수 있는 수단을 제공해준다. 뭐 꼭 insert,update,delete뿐 아니라 다른 것에도
되지만.. 일단 이 부분만 보는것이 이해하기에 좋을것 같다.
일단 간단한 예를 보자.

SQL> desc test;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 NAME                                               VARCHAR2(10)
 AGE                                                NUMBER

SQL> desc test2;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 NAME                                               VARCHAR2(10)

SQL> create or replace trigger test_insert_t1
  2  after 
  3  insert or delete or update on test 
  4  for each row
  5  
  6  begin
  7  
  8  if INSERTING then
  9      INSERT INTO test2 values (:new.name);
 10  end if;
 11  
 12  if DELETING then
 13      DELETE FROM test2 where test2.name = :old.name;
 14  end if;
 15  
 16  if UPDATING then
 17      UPDATE test2 set name = :new.name where name = :old.name;
 18  end if;
 19  
 20  end;
 21  /

트리거가 생성되었습니다.

SQL> insert into test values ('강명규', 28);

1 개의 행이 만들어졌습니다.

SQL> select * from test;

NAME              AGE
---------- ----------
강명규             28

SQL> select * from test2;

NAME
----------
강명규

SQL> update test set name='홍길동' where name='강명규';

1 행이 갱신되었습니다.

SQL> select * from test;

NAME              AGE
---------- ----------
홍길동             28

SQL> select * from test2;

NAME
----------
홍길동

SQL> delete from test;

1 행이 삭제되었습니다.

SQL> select * from test;

선택된 레코드가 없습니다.

SQL> select * from test2;

선택된 레코드가 없습니다.

SQL> 


설명
쉬운 예제라 설명할 것이 별로 없다.
test, test2테이블이 있다.
test에 insert, update, delete문이 사용될때, 이를 test2테이블에도 반영한다.

:new
새로 변경되는 데이터(insert시는 새로 insert되는 데이터, update시 변경된 데이터)

:old
기존의 데이터(update, delete시)


트리거의 종류
row, statement
before, after
instead of

user_triggers

 

Recovery Catalog를 위한 DB생성

더보기

Recovery Catalog를 위한 DB생성

-- 이미지가 다수 깨져서 자료를 이해하기 어려운 부분이 있으니 참고 바랍니다.

환경:
Windows Advanced Server(With Service pack 1)
Intel Pentium III 450
Oracle EE 8.1.6
Production DB와 Recovery Catalog DB는 물리적으로 하나의 서버에 위치
Production DB는 C드라이브, Recovery Catalog DB는 D드라이브에 위치함

recovery manager는 사용하는 backup정보를 recovery repository라는 곳에 저장한다
recovery repository는 다음 2개중 하나로 지정된다. 이는 사용자의 선택옵션이다.

1. production database(현재 서비스중인 DB)의 control file
2. Recovery Catalog DB

오라클에서 권장하는 것은 recovery catalog를 사용하는 것이다.
control file을 사용할 경우, 별도로 recovery를 위한 DB를 생성할 필요가 없으나,
몇 가지 부분에서 제한이 있다.

production database(현재 서비스중인 DB)의 control file을 이용할 경우 rman(Recovery Manager의 
OS명령어)에서 다음과 같이 연결하여 사용할 수 있다.

C:\>rman nocatalog

복구 관리자: 릴리즈 8.1.6.0.0 - Production

RMAN> connect target sys/xxxxxx

RMAN-06005: 대상 데이터베이스에 접속합니다: MADDOG (DBID=3533467536)
RMAN-06009: 복구 카타로그 대신 대상 데이터베이스 제어 파일을 사용합니다

RMAN> report schema;

RMAN-03022: 명령어 컴파링: report
데이터베이스 스키마의 리포트
파일 킬로바이트 테이블스페이스           RB segs 이름
---- ---------- -------------------- ------- -------------------
1        242432 SYSTEM               ***     C:\ORACLE\ORADATA\MADDOG\SYSTEM01.DBF
2         71680 RBS                  ***     C:\ORACLE\ORADATA\MADDOG\RBS01.DBF
3         20480 USERS                ***     C:\ORACLE\ORADATA\MADDOG\USERS01.DBF
4         20480 TEMP                 ***     C:\ORACLE\ORADATA\MADDOG\TEMP01.DBF
5         10240 TOOLS                ***     C:\ORACLE\ORADATA\MADDOG\TOOLS01.DBF
6         20480 INDX                 ***     C:\ORACLE\ORADATA\MADDOG\INDX01.DBF
7         20480 DRSYS                ***     C:\ORACLE\ORADATA\MADDOG\DR01.DBF
8          5120 TS_KANG              ***     C:\ORACLE\ORADATA\MADDOG\TS_KANG1.DBF
9         35848 OEM_REPOSITORY       ***     C:\ORACLE\ORADATA\MADDOG\OEM_REPOSITORY.ORA
10         5120 TS_INDEX             ***     C:\ORACLE\ORADATA\MADDOG\TS_INDEX.DBF
11         5120 TS_KANG              ***     C:\ORACLE\ORADATA\MADDOG\TS_KANG2.DBF
12         2048 TS_TEST              ***     C:\ORACLE\ORADATA\MADDOG\TS_TEST1.DBF
13         5120 TS_KANG              ***     C:\ORACLE\ORADATA\MADDOG\TS_KANG3.DBF

RMAN> exit


복구 매니저가 완성되었습니다.

C:\>

여기서는 Recovery Repository로 2번째 방법인 Recovery catalog를 이용하는 것을 설명한다.
이번 글에서는 recovery catalog(이하 RC)를 위한 DB를 생성하고, recovery manager(이하 rman)를
위한 schema, tablespace를 설정, 백업할 데이터베이스를 등록하는 것까지만 설명한다.

Recovery Catalog를 위한 DB에 대해 오라클에서 제시하는 것은 다음과 같다.

Typical Recovery Catalog Space Requirements for 1 Year
Type of Space Space	Requirement
System	50 megabytes
Temp	5 megabytes
Rollback	5 megabytes
Recovery catalog	10 megabytes
Online redo logs	1 megabyte each (3 groups, each with 2 members)



수동으로 RC DB를 만들 수 있으나, 본인이 귀찮은 관계로 DB Configuration Assistant를 이용하여
생성하겠다.









사용자 정의로 선택한다.




그냥 다목적으로 사용하자.




디폴트로 15개지만 5개만 하자




RC DB를 mts로 사용할 일은 없다.




RC DB에 부가적인 기능은 필요없다.
최소한의 기능만(DB자체만 있으면 된다) 있으면 OK




전역 DB명(패러미터파일의 service_names패러미터값)은 rcat.kang.com으로 하겠다. 
RC를 위한 저장위치는 D의 rc_data폴더를 사용한다
이하 모든 데이터파일들의 위치는 d:\rc_data이하 폴더에 위치하게 설정한다.




제어파일(control file)위치 지정




각각의 테이블스페이스에서 위치와 크기만 다음과 같이 변경하고
나머지 값은 디폴트로 사용한다.





tablespace	datafile	size
시스템	d:\rc_data\oradata\rcat\system01.dbf	50MB
도구	d:\rc_data\oradata\rcat\tools01.dbf	5MB
사용자	d:\rc_data\oradata\rcat\users01.dbf	5MB
롤백	d:\rc_data\oradata\rcat\rbs01.dbf	5MB
인덱스	d:\rc_data\oradata\rcat\indx01.dbf	3MB
임시	d:\rc_data\oradata\rcat\temp01.dbf	5MB


redo log file설정








db_block_size만 4096byte로 변경








만일 수동으로 스크립트를 실행해 DB생성을 하고 싶다면
일괄처리파일에 정보 저장을 선택해서 맘에 안드는 부분은 수정하도록 하세요
여기서는 바로 DB생성을 하겠습니다.




Recovery Catalog Database 생성화면




DB생성 끝




그냥 수동으로 DB를 만들걸 그랬다.
이 페이지에 그림 무지하게 들어가네..


이제 RC를 위한 DB도 생성되었으니, 이젠 RC를 위한 schema(사용자), tablespace를 설정해주고
production DB를 등록해주는 과정이 남아있다.

우선 listener.ora와 tnsnames.ora에 변경된 부분과 서비스에 rcat DB가 등록된 것을 확인하고 넘어가자

서비스에 등록된 rcat DB




rcat이 추가되어진 listener.ora
# LISTENER.ORA Network Configuration File: C:\Oracle\Ora81\network\admin\listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521))
      )
    )
    (DESCRIPTION =
      (PROTOCOL_STACK =
        (PRESENTATION = GIOP)
        (SESSION = RAW)
      )
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 2481))
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = C:\Oracle\Ora81)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = maddog.kang.com)
      (ORACLE_HOME = C:\Oracle\Ora81)
      (SID_NAME = maddog)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = rcat.kang.com)
      (ORACLE_HOME = C:\Oracle\Ora81)
      (SID_NAME = rcat)
    )
  )


rcat이 추가되어진 tnsnames.ora
# TNSNAMES.ORA Network Configuration File: C:\Oracle\Ora81\network\admin\tnsnames.ora
# Generated by Oracle configuration tools.

EXTPROC_CONNECTION_DATA.KANG.COM =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )

RCAT.KANG.COM =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = rcat.kang.com)
    )
  )

MADDOG.KANG.COM =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = maddog.kang.com)
      (SERVER = DEDICATED)
    )
  )

MADDOG_MTS.KANG.COM =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = maddog.kang.com)
      (SERVER = SHARED)
    )
  )


여기서 주의할 점이 있다.
현재 DB가 2개로 각각 instance도 하나씩 실행된 상태이다.
그러면 이 놈의 윈도우는 마지막에 생성한 DB의 sid를 레지스트리에 저장해 버린다.
흠.. 그러면 기존DB(예제에서는 maddog)의 sid는 없어져 버린다.
대부분이 기존의 production DB(테스트용인데 production이라고 하니 뭐 하군..)를 우선
사용할 것이므로 이를 이전 sid로 되돌려 놓자.
이렇게 하지 않으면 이전에 생성된 DB에 연결시, 수동으로 oracle_sid를 set하여 sql*plus로 들어가야 한다.

그림을 참고하세요(rcat이라고 되어 있는 부분을 다시 maddog이라고 변경한다)




물론 위와 같이 하면, 이젠 RC DB에 접속할때마다 oracle_sid를 rcat으로 지정한 후, 연결해야 한다.

참.. 생성된 rcat DB의 데이터파일은 다음과 같다.




흠.. DB를 2개나 올려놓으니 300MB인 메모리가 거의 남지 않는다.
역시, 오라클 무거운 거 알아줘야 한다.

환경이 된다면 테스트라 하더라도 물리적으로 분리된 서버에 production DB와 recovery catalog DB를 
생성하세요. -_-;


recovery catalog database설정

이미 production DB(이하 maddog), RC DB(이하 rcat)의 instance가 실행중임을 확인한다.
위에서 레지스트리에 있는 oracle_sid값을 수정했으므로 '명령 프롬프트'상에서 oracle_sid를 명시하면서
sql*plus를 이용해 rcat DB에 접속한다. 

catalog를 위한 tablespace의 이름은 cattbs로 하고 크기를 10m로 잡았다.
recovery catalog schema(rman 사용자)를 생성하고, 이 schema에 recovery_catalog_owner권한을 준다.

C:\>set oracle_sid=rcat

C:\>sqlplus sys/change_on_install

SQL*Plus: Release 8.1.6.0.0 - Production on 목 Feb 15 22:45:23 2001

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SQL> create tablespace cattbs
  2  datafile 'D:\rc_data\oradata\rcat\ts_cat01.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> create user rman identified by rman
  2  default tablespace cattbs
  3  temporary tablespace temp
  4  quota unlimited on cattbs;

사용자가 생성되었습니다.

SQL> grant connect, resource to rman;

권한이 부여되었습니다.

SQL> grant recovery_catalog_owner to rman;

권한이 부여되었습니다.

SQL> quit
Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production에서 분리되었습니다.


recovery catalog 생성
오라클 8버전에서는 cat_rman.sql이라는 스크립트를 돌려서 recovery catalog를 생성했지만,
오라클 8i로 오면서, create catalog라는 명령으로 catalog를 생성한다.

C:\>rman catalog rman/rman@rcat

복구 관리자: 릴리즈 8.1.6.0.0 - Production

RMAN-06008: 복구 카타로그 데이터베이스에 접속
RMAN-06428: 복구 카탈로그가 설치되지 않았습니다

RMAN> create catalog tablespace cattbs;

RMAN-06431: 복구 카탈록그가 작성되었습니다

RMAN> exit


복구 매니저가 완성되었습니다.

C:\>


recovery catalog에 target database를 등록

이젠, production DB를 recovery catalog에 등록해 주는 과정만 남았다.
참고로, rman에서는 백업대상인 production DB를 target DB라고 부른다.
하나의 recovery catalog에는 여러개의 target database가 등록될 수 있다.

호환버전확인
C:\>sqlplus rman/rman

SQL*Plus: Release 8.1.6.0.0 - Production on 목 Feb 15 23:07:03 2001

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SQL> select value from config where name='compatible';

VALUE
------------------------------------------------------------------------

080106

SQL> exit
Oracle8i Enterprise Edition Release 8.1.6.0.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production에서 분리되었습니다.


여기서 주의해야 할 부분이다.
oracle_sid는 동시에 2개가 존재할 수 없으므로 catalog나 target 2개중 하나는 net8을 
이용하여 접속해야 한다는 것이다. 여기서는 oracle_sid를 target DB로 설정하고 RC는 
net8을 이용하여 접속했다. target DB는 mount나 open상태여야 한다.
archived redo logs에 대한 정보는 target DB의 control file으로부터 자동으로 얻어진다.

C:\>set oracle_sid=maddog

C:\>rman target sys/xxxxxx catalog rman/rman@rcat

복구 관리자: 릴리즈 8.1.6.0.0 - Production

RMAN-06005: 대상 데이터베이스에 접속합니다: MADDOG (DBID=3533467536)
RMAN-06008: 복구 카타로그 데이터베이스에 접속

RMAN> register database;

RMAN-03022: 명령어 컴파링: register
RMAN-03023: 명령어 수행: register
RMAN-08006: 복구 카타로그에 데이터베이스가 등록되었습니다
RMAN-03023: 명령어 수행: full resync
RMAN-08029: 기본값으로 스냅샷 제어파일 이름을 설정합니다: %ORACLE_HOME%\DATABASE\SNCF%ORACLE_SID%.ORA
RMAN-08002: 모든 복구 카타로그의 resync를 시작합니다
RMAN-08004: 모든 resync가 완성되었습니다

RMAN> report schema;

RMAN-03022: 명령어 컴파링: report
데이터베이스 스키마의 리포트
파일 킬로바이트 테이블스페이스           RB segs 이름
---- ---------- -------------------- ------- -------------------
1        242432 SYSTEM               YES     C:\ORACLE\ORADATA\MADDOG\SYSTEM01.DBF
2         71680 RBS                  YES     C:\ORACLE\ORADATA\MADDOG\RBS01.DBF
3         20480 USERS                NO      C:\ORACLE\ORADATA\MADDOG\USERS01.DBF
4         20480 TEMP                 NO      C:\ORACLE\ORADATA\MADDOG\TEMP01.DBF
5         10240 TOOLS                NO      C:\ORACLE\ORADATA\MADDOG\TOOLS01.DBF
6         20480 INDX                 NO      C:\ORACLE\ORADATA\MADDOG\INDX01.DBF
7         20480 DRSYS                NO      C:\ORACLE\ORADATA\MADDOG\DR01.DBF
8          5120 TS_KANG              NO      C:\ORACLE\ORADATA\MADDOG\TS_KANG1.DBF
9         35848 OEM_REPOSITORY       NO      C:\ORACLE\ORADATA\MADDOG\OEM_REPOSITORY.ORA
10         5120 TS_INDEX             NO      C:\ORACLE\ORADATA\MADDOG\TS_INDEX.DBF
11         5120 TS_KANG              NO      C:\ORACLE\ORADATA\MADDOG\TS_KANG2.DBF
12         2048 TS_TEST              NO      C:\ORACLE\ORADATA\MADDOG\TS_TEST1.DBF
13         5120 TS_KANG              NO      C:\ORACLE\ORADATA\MADDOG\TS_KANG3.DBF

RMAN>

오늘은 여기까지 설명하고 마치겠다.
다음에는 recovery manager사용에 대해 다루겠다.

 

data file이름 변경

더보기

data file이름 변경

SQL> select t.name, d.status, d.name from v$tablespace t, v$datafile d
  2  where t.ts# = d.ts#;

NAME                           STATUS  NAME
------------------------------ ------- ---------------------------------------------
SYSTEM                         SYSTEM  C:\ORACLE\ORADATA\MADDOG\SYSTEM01.DBF
RBS                            ONLINE  C:\ORACLE\ORADATA\MADDOG\RBS01.DBF
USERS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\USERS01.DBF
TEMP                           ONLINE  C:\ORACLE\ORADATA\MADDOG\TEMP01.DBF
TOOLS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\TOOLS01.DBF
INDX                           ONLINE  C:\ORACLE\ORADATA\MADDOG\INDX01.DBF
DRSYS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\DR01.DBF
KANG                           ONLINE  C:\ORACLE\ORADATA\MADDOG\TS_KANG01.DBF
MYRBS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\RBS02.DBF
OEM_REPOSITORY                 ONLINE  C:\ORACLE\ORADATA\MADDOG\OEM_REPOSITORY.ORA

10 개의 행이 선택되었습니다.

SQL> alter tablespace kang offline;

테이블 영역이 변경되었습니다.

os로 돌아가서 ts_kang01.dbf를 kang01.dbf로 rename한다.
DB로 돌아와 데이터파일의 변경상황을 알려준다.

SQL> alter tablespace kang
  2  rename datafile
  3  'C:\ORACLE\ORADATA\MADDOG\TS_KANG01.DBF'
  4  to
  5  'C:\ORACLE\ORADATA\MADDOG\KANG01.DBF';

테이블 영역이 변경되었습니다.

SQL> alter tablespace kang online;

테이블 영역이 변경되었습니다.

만일 OS에서 rename하지 않은 상태에서 데이터파일의 변경상황을 알려주지 않으면 
다음과 같은 에러를 뱉는다.

SQL> alter tablespace kang online;
alter tablespace kang online
*
1행에 오류:
ORA-01157: 데이터 8 파일을 식별 또는 잠금 할 수 없습니다- DBWR 추적 파일을 보십시오
ORA-01110: 8 데이터 파일: 'C:\ORACLE\ORADATA\MADDOG\TS_KANG01.DBF'


데이터파일 크기도 변경하려면 다음과 같이 한다.

alter database 
datafile 'C:\ORACLE\ORADATA\MADDOG\KANG01.DBF' resize 50m;

SQL*LOADER

더보기

SQL*LOADER

일반 text file(오라클에서는 flat file이라고 부른다.)의 데이터를 오라클DB에
넣기 위한 방법은 2가지가 있다. 고정길이레코드를 가진 데이터와
가변길이레코드를 가진 데이터

고정길이 레코드 데이터
백지영 80  80  80
한심해 20  20  30
조신한 50  80  90
여자면 30  100 98
이런일 80  90  65
없었지 65  95  85

가변길이 레코드 데이터
myunggyu, 강명규, 750509, 남자, 프로그래머
piruks, 강병욱, 730301, 남자, 수학자
gildong, 홍길동, 700101, 남자, 도둑님

flat파일로부터 데이터를 삽입하기 위한 테이블을 생성하자.
SQL> connect kang/xxxxxx
연결되었습니다.

SQL> create table fix_table
  2  (
  3  name varchar2(6),
  4  국어 number,
  5  영어 number,
  6  수학 number
  7  );

테이블이 생성되었습니다.

SQL> create table var_table
  2  (
  3  id varchar2(15),
  4  name varchar2(10),
  5  birth char(7),
  6  sex char(5),
  7  vocation varchar2(15)
  8  );

테이블이 생성되었습니다.

SQL>

테이블이 생성되었습니다.






고정 레코드


제어파일에 데이터파일의 내용이 함께 존재할 경우


fix_togather.ctl이라는 파일의 내용이다.

load data
infile *
append into table fix_table
(
name position(1:6)   char,
국어 position(8:10)  integer external,
영어 position(12:14) integer external,
수학 position(16:19) integer external
)

begindata
백지영 80  80  80
한심해 20  20  30
조신한 50  80  90
여자면 30  100 98
이런일 80  90  65
없었지 65  95  85



OS에서 작업
아래 명령에 실행후, 결과로그가 fix_togather.log파일에 기록된다.
만일 테이블의 정의에 벗어나는 형식의 데이터(레코드)는 bad file에 저장된다.
아래와 같은 경우 fix_togather.bad라는 파일에 적합하지 않는 레코드들이 저장된다.

E:\>sqlldr userid=kang/xxxxxx control=fix_togather

SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 14:59:21 2000

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

커밋 시점에 도달 - 논리 레코드 개수 5
커밋 시점에 도달 - 논리 레코드 개수 6

E:\>
fix_togather.log파일의 내용

SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 14:59:21 2000

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

제어 파일:    fix_togather.ctl
데이터 파일:    fix_togather.ctl
  잘못된 파일: fix_togather.bad
  폐기 파일:    지정 사항 없음

 (모든 폐기된 레코드 허용)

로드할 건수: ALL
생략 건수:  0
허용 오류수:  50
바인드 배열:  64 행, 최대 65536 바이트
계속:    지정 사항 없음
사용된 경로:      규약

테이블 FIX_TABLE, 로드되었습니다 개개의 논리 레코드로부터
이 테이블에 적당한 Insert 옵션: APPEND

   열 이름                        위치    Len   Term Encl 데이터유형
------------------------------ ---------- ----- ---- ---- ---------------------
NAME                                  1:6     6           CHARACTER
국어                                 8:10     3           CHARACTER
영어                                12:14     3           CHARACTER
수학                                16:19     4           CHARACTER

테이블 FIX_TABLE:
  6 행들 로드되었습니다.
  데이터 오류 때문에 0 행들(이)가 로드되지 않았습니다
  모든 WHEN절이 실패하여 0 행들(이)가 로드되지 않았습니다
  모든 필드가 NULL이어서 0 행들(이)가 로드되지 않았습니다


바인드 배열에 할당된 영역:              1664바이트(64 행)
바인드 배열외에 메모리에 할당된 영역:        0 바이트

생략된 논리 레코드의 합계:         0
읽어낸 논리 레코드의 합계:         6
거부된 논리 레코드의 합계:         0
폐기된 논리 레코드의 합계:         0

목 Nov 30 14:59:21 2000에 실행 개시
목 Nov 30 14:59:26 2000에 실행 종료

경과 시간:        00:00:05.39
CPU 시간:         00:00:00.08



SQL> select * from fix_table;

NAME         국어       영어       수학
------ ---------- ---------- ----------
백지영         80         80         80
한심해         20         20         30
조신한         50         80         90
여자면         30        100         98
이런일         80         90         65
없었지         65         95         85

6 개의 행이 선택되었습니다.

나중의 테스트를 위해 삽입된 데이터를 지운다.
SQL> delete from fix_table;

6 행이 삭제되었습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL>







제어파일과 데이터파일이 분리된 경우

제어파일(fix_data.ctl)의 내용
load data
infile 'fix_data.dat'
badfile 'fix_data.bad'
discardfile 'fix_data.dsc'
insert into table fix_table
(
name position(1:6)   char,
국어 position(8:10)  integer external,
영어 position(12:14) integer external,
수학 position(16:19) integer external
)

데이터파일(fix_data.dat)의 내용
백지영 80  80  80
한심해 20  20  30
조신한 50  80  90
여자면 30  100 98
이런일 80  90  65
없었지 65  95  85

E:\>sqlldr userid=kang/xxxxxx control=fix_data

SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 15:10:49 2000

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

커밋 시점에 도달 - 논리 레코드 개수 5
커밋 시점에 도달 - 논리 레코드 개수 6

E:\>

fix_data.log파일의 내용
SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 15:10:49 2000

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

제어 파일:    fix_data.ctl
데이터 파일:    fix_data.dat
  잘못된 파일: fix_data.bad
  폐기 파일:   fix_data.dsc
 (모든 폐기된 레코드 허용)

로드할 건수: ALL
생략 건수:  0
허용 오류수:  50
바인드 배열:  64 행, 최대 65536 바이트
계속:    지정 사항 없음
사용된 경로:      규약

테이블 FIX_TABLE, 로드되었습니다 개개의 논리 레코드로부터
이 테이블에 적당한 Insert 옵션: INSERT

   열 이름                        위치    Len   Term Encl 데이터유형
------------------------------ ---------- ----- ---- ---- ---------------------
NAME                                  1:6     6           CHARACTER
국어                                 8:10     3           CHARACTER
영어                                12:14     3           CHARACTER
수학                                16:19     4           CHARACTER

테이블 FIX_TABLE:
  6 행들 로드되었습니다.
  데이터 오류 때문에 0 행들(이)가 로드되지 않았습니다
  모든 WHEN절이 실패하여 0 행들(이)가 로드되지 않았습니다
  모든 필드가 NULL이어서 0 행들(이)가 로드되지 않았습니다


바인드 배열에 할당된 영역:              1664바이트(64 행)
바인드 배열외에 메모리에 할당된 영역:        0 바이트

생략된 논리 레코드의 합계:         0
읽어낸 논리 레코드의 합계:         6
거부된 논리 레코드의 합계:         0
폐기된 논리 레코드의 합계:         0

목 Nov 30 15:10:49 2000에 실행 개시
목 Nov 30 15:10:54 2000에 실행 종료

경과 시간:        00:00:04.64
CPU 시간:         00:00:00.08




가변레코드

가변길이 레코드는 필드구분자로 레코드내의 필드를 구분한다.
보통 ,로 구분자를 쓰는 경우가 많다.

제어파일에 데이터파일의 내용이 함께 존재할 경우
var_togather.ctl이라는 파일의 내용이다.

load data
infile *
append into table var_table
fields terminated by ","
( id, name, birth, sex, vocation)

begindata
myunggyu, 강명규, 750509, 남자, 프로그래머
piruks, 강병욱, 730301, 남자, 수학자
gildong, 홍길동, 700101, 남자, 도둑님

E:\>sqlldr userid=kang/xxxxxx control=var_togather

SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 15:28:23 2000

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

커밋 시점에 도달 - 논리 레코드 개수 2
커밋 시점에 도달 - 논리 레코드 개수 3

E:\>


SQL> select * from var_table;

ID              NAME       BIRTH   SEX   VOCATION
--------------- ---------- ------- ----- ---------------
myunggyu         강명규     750509  남자  프로그래머
piruks           강병욱     730301  남자  수학자
gildong          홍길동     700101  남자  도둑님

SQL>

마찬가지로 결과로그는 var_togather.log에 저장된다.



제어파일과 데이터파일이 분리된 경우
제어파일(var_data.ctl)의 내용
load data
infile 'var_data.dat'
badfile 'var_data.dat'
discardfile 'fix_data.dsc'
append into table var_table
fields terminated by ","
( id, name, birth, sex, vocation)



데이터파일(var_data.dat)의 내용
myunggyu, 강명규, 750509, 남자, 프로그래머
piruks, 강병욱, 730301, 남자, 수학자
gildong, 홍길동, 700101, 남자, 도둑님


위에서 삽입된 데이터들을 일단 지우자

SQL> delete from var_table;

3 행이 삭제되었습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL>

E:\>sqlldr userid=kang/xxxxxx control=var_data

SQL*Loader: Release 8.1.6.0.0 - Production on 목 Nov 30 15:36:12 2000

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

커밋 시점에 도달 - 논리 레코드 개수 2
커밋 시점에 도달 - 논리 레코드 개수 3

E:\>

SQL> select * from var_table;

ID              NAME       BIRTH   SEX   VOCATION
--------------- ---------- ------- ----- ---------------
gildong          홍길동     700101  남자  도둑님
myunggyu         강명규     750509  남자  프로그래머
piruks           강병욱     730301  남자  수학자

SQL>


SQL*LOADER 1편 끝

COPY사용법

더보기

COPY사용법

copy는 외부의 DB에서 데이터를 가져오는 방법중의 하나이다.
보통 export/import, create table .. as select.., copy등을 사용하여 외부DB로부터 데이터를 가져올 수 있다.
그외, 데이터베이스링크로 스냅샵을 생성하여 가져올 수도 있겠죠?
거두절미 어떻게 하는지 예를 보자.

SQL> copy
사용법: COPY FROM <db> TO <db> <opt> <table> { (<cols>) } USING <sel>
  <db>   : 데이터베이스 문자열, e.g., scott/tiger@d:chicago-mktg
  <opt>  : 다음 키워드중 하나: APPEND, CREATE, INSERT or REPLACE
  <table>: 수신지 테이블의 이름
  <cols> : 쉼표로 구분된 수신지 열의 별명 목록
  <sel>  : 적당한 SQL SELECT 문
누락된 FROM 혹은 TO 절이 현재의 SQL*Plus 연결에 사용합니다.

SQL> connect kang/xxxxxx@piruks
연결되었습니다.
SQL> drop table test;

테이블이 삭제되었습니다.

SQL> create table test (
  2  name varchar2(10),
  3  age number(3));

테이블이 생성되었습니다.

SQL> insert into test values('&x', 27);
x의 값을 입력하십시오: 강명규
구   1: insert into test values('&x', 27)
신   1: insert into test values('강명규', 27)

1 개의 행이 만들어졌습니다.

SQL> /
x의 값을 입력하십시오: 홍길동
구   1: insert into test values('&x', 27)
신   1: insert into test values('홍길동', 27)

1 개의 행이 만들어졌습니다.

SQL> /
x의 값을 입력하십시오: 임꺽정
구   1: insert into test values('&x', 27)
신   1: insert into test values('임꺽정', 27)

1 개의 행이 만들어졌습니다.

SQL> select * from test;

NAME                        AGE
-------------------- ----------
강명규                       27
홍길동                       27
임꺽정                       27

SQL> connect kang/xxxxxx@maddog
연결되었습니다.
SQL> copy from kang/xxxxxx@piruks to kang/xxxxxx@maddog create test using select * from test;

배열의 인출/바인드 크기는 15입니다. (배열 크기는 15)
작업이 완성되면 커밋됩니다. (복사 완료: 0)
최대 긴 크기는 80 입니다. (롱 80)
테이블 TEST가 생성되었습니다.

   3 행이 선택되었습니다(kang@piruks 로부터).
   3 행이 입력되었습니다(TEST 에).
   3 행이 TEST으로 완료되었습니다(kang@maddog 의).

SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
TEST                           TABLE

SQL> select * from test;

NAME              AGE
---------- ----------
강명규             27
홍길동             27
임꺽정             27

복사대상이 현재 연결된 계정이라면 위의 copy문은 다음과 같이 대상부분을 지정하지 않아도 된다.

copy from kang/xxxxxx@piruks create test using select * from test;


SQL> connect kang/xxxxxx@maddog
연결되었습니다.
SQL> copy from kang/xxxxxx@piruks to kang/xxxxxx@maddog insert test using select * from test where age=30;

배열의 인출/바인드 크기는 15입니다. (배열 크기는 15)
작업이 완성되면 커밋됩니다. (복사 완료: 0)
최대 긴 크기는 80 입니다. (롱 80)
   1 행이 선택되었습니다(kang@piruks 로부터).
   1 행이 입력되었습니다(TEST 에).
   1 행이 TEST으로 완료되었습니다(kang@maddog 의).

SQL> select * from test;

NAME              AGE
---------- ----------
강명규             27
홍길동             27
임꺽정             27
강감찬             30

SQL>


[2003-07-30추가]
사용할 수 있는 명령은 다음과 같다. 

insert : 데이터를 insert. 테이블이 존재하지 않으면 에러
append : 데이터를 insert. 테이블이 존재하지 않으면 생성
create : 테이블이 생성후, 데이터 insert. 이미 테이블이 존재하면 에러
replace: 이미 테이블이 존재하면 제거후, 데이터 insert


copy명령수행시 보이는 3가지는 set명령으로 설정될 수 있는 내용이다.

배열크기(arraysize) : 한번에 처리할 레코드수. 이를 batch라고 칭한다.
copycommit : commit이 발생할 batch수를 지정
long : 컬럼타입으로 long타입이 존재하면, long값의 길이제한.

SQL> show copycommit arraysize
copycommit 1
arraysize 15
SQL> set arraysize 100
SQL> copy from kang/xxxxxx@linuxdb replace test using select * from test;

배열의 인출/바인드 크기는 100입니다. (배열 크기는 100)
배열 바인드 발생시마다 커밋됩니다. (복사 완료: 1)
최대 긴 크기는 80 입니다. (롱 80)
테이블 TEST가 삭제되었습니다.

테이블 TEST가 생성되었습니다.

   5001 행이 선택되었습니다(kang@linuxdb 로부터).
   5001 행이 입력되었습니다(TEST 에).
   5001 행이 TEST( DEFAULT HOST 연결의)으로 커밋되었습니다.

SQL>

스냅샵의 사용

더보기

스냅샵의 사용

스냅샵은 보통 원격지DB의 내용을 자신의 로컬 DB에 저장하려는 목적으로 사용된다.
한마디로 DB의 복사본이라고 생각하면 된다.
이 스냅샵은 생성시 옵션으로 주기적으로 refresh할 수 있다.

보통 원격지의 DB는 master 라고 한다.
스냅샵은 long컬럼을 가질 수 없다.

스냅샵은 2가지 형태가 있다.
simple, complex

simple snapshot
single remote table에 기반한다.
혹은 제한된 서브쿼리의 형태를 사용하여 많은 테이블에 정의된다.

simple 스냅샵이 포함할 수 없는 것.
group by
connect by
distinct or aggregate functions
joins
set operations

complex snapshot
많은 master databases에 있는 많은 master tables에 기반할 수 있다.

Refresh Mode지정
마스터 DB에 변경상황이 발생했을 경우 이를 스냅샵에 갱신해줘야 한다.
이는 3가지 모드가 있다.

fast
complete
refresh


FAST
오라클은 snapshot log에 기록된 마스터 테이블의 변화가 생기면 snapshot을 갱신한다.
다음의 모든 상황이 만족할때만 fast refresh를 수행할 수 있다.

1. simple snapshot
2. 스냅샵의 마스터 테이블이 snapshot log를 가지고 있다.
3. snapshot의 마지막 갱신/생성 이전에 snapshot log가 생성되었을때


COMPLETE
요놈은 어떻게 보면 상당히 비효율적이다.
스냅샵을 생성하기 위한 질의를 다시 실행한다.

fast refresh는 complete refresh보다 빠르다.
왜냐하면, 말 그대로 fast가 complete보다 더 적은 양의 데이터를 전송하기 때문이다.
fast refresh는 last refresh이후, 마스터테이블 데이터의 변경부분만 전송한다.
반면, complete refresh는 스냅샵 쿼리의 완전한 결과를 전송한다.


FORCE
오라클이 어떻게 스냅샵을 갱신할지를 지정한다.
만일 fast refresh가 가능하면 오라클은 fast refresh를 수행한다.
fast refresh가 가능하지 않다면 오라클은 complete refresh를 수행한다.
# 스냅샵 로그
FAST REFRESH를 사용하기 위해선 remote DB에 snapshot log를 생성해야 한다.
스냅샵로그는 스냅샵의 마스터 테이블과 연관된 테이블이다.
마스터 테이블 데이터에 변경상황이 발생하면 오라클은 이 변경상황들을 설명하는 row들을
스냅샵로그에 기록한다. 나중에 오라클은 마스터테이블에 기반한 스냅샵을 갱신하기위해 이 row들을
사용할 수 있다. 이를 fast refresh라고 한다. 스냅샵로그가 없다면, 오라클은
스냅샵을 갱신하기위해 스냅샵쿼리를 다시 실행해야만 한다. 이를 complete refresh라고 한다.

tip> 스냅샵로그는 AFTER row trigger를 이용한다.

스냅샵로그는 마스터 데이터베이스에 존재한다.
마스터 테이블에 대해 단지 하나의 스냅샵로그만이 필요하다.

예제 1)
EMP테이블에 생성된 simple primary-key 스냅샵에 fast refresh를 수행하기 위해
이 스냅샵로그를 사용할 수 있다.

create snapshot log on emp
pctfree 5
tablespace users
storage (inital 10k next 10k pctincrease 50);

오라클이 primary-key 스냅샵을 수행하기 위해, 마스터 테이블에 있는 update된 row들의
프라이머리키는 스냅샵로그에 기록되어야 한다.
비슷하게, rowid스냅샵에서, rowid는 스냅샵로그에 기록되어야 한다.
primary-key 스냅샵, rowid스냅샵은 같이 저장될 수도 있다.

다음의 예는 갱신된 row들의 primary-key만을 저장하는 스냅샵로그를 생성한다.

create snapshot log on emp;
create snapshot log on emp with primary key;

다음은 primary-key와 rowid 둘다 저장한다.

create snapshot log on sales with rowid, primary key;

다음은 primary-key와 필터컬럼ZIP을 기록하는 스냅샵로그를 생성한다.

create snapshot log on address with (zip)

Automatic Refresh를 하기 위해 다음을 지정한다. (2는 정확한 내용을 모르겠다)
1. start with와 next패러미터를 create snapshot문장의 refresh절에 지정한다.

2. 1이상의 queue processes를 패러미터파일에서 enable한다.
snapshot_refresh_interval = 60
snapshot_refresh_processes = 1
snapshot_refresh_keep_connections = true
원격지 DB
[kang@dev kang]$ sqlplus kang/xxxxxx

SQL*Plus: Release 8.1.6.0.0 - Production on Mon Nov 6 21:13:35 2000

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SQL> select * from test;

NAME              AGE BIRTH
---------- ---------- --------
강명규             27 19740509

SQL> create snapshot log on test;
create snapshot log on test
*
ERROR at line 1:
ORA-12014: table 'TEST' does not contain a primary key constraint

snapshot log가 사용할 테이블은 primary key가 존재해야 한다.
SQL> desc test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 NAME                                               VARCHAR2(10)
 AGE                                                NUMBER(2)
 BIRTH                                              VARCHAR2(8)

SQL> alter table test
  2  add constraints test_pk primary key (name);

Table altered.

SQL> create snapshot log on test;

Materialized view log created.

SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
MLOG$_TEST                     TABLE
RUPD$_TEST                     TABLE
TEST                           TABLE

초기에는 이 2놈은 비어있다. 변경사항이 없으므로..
SQL> select * from mlog$_test;

no rows selected

SQL> select * from rupd$_test;

no rows selected


로컬 DB
SQL> connect sys/xxxxxx
연결되었습니다.
SQL> grant create snapshot to kang;

권한이 부여되었습니다.

SQL> connect kang/xxxxxx
연결되었습니다.

SQL> create database link dev.kang.com
  2  connect to kang identified by xxxxxx
  3  using 'dev'

아래의 스냅샵생성문에서는 start with가 지정되어 있지 않기 때문에 지금으로부터 7일후 첫번째 refresh가 발생한다.
이후 7일마다 주기적으로 refresh가 발생한다.
SQL> create snapshot test_sf
  2  pctfree 5 pctused 60
  3  tablespace users
  4  storage (initial 50k next 50k)
  5  refresh fast next sysdate+7
  6  as
  7  select name from kang.test@dev.kang.com;

구체화된 뷰가 작성되었습니다.

SQL> drop snapshot test_sf;

구체화된 뷰가 삭제되었습니다.

테스트시에는 너무 긴 시간이므로 5분으로 refresh시간을 줄여서 다시 생성하자
SQL> create snapshot test_sf
  2  pctfree 5 pctused 60
  3  tablespace users
  4  storage (initial 50k next 50k)
  5  refresh fast next sysdate+(1/288)
  6  as
  7  select name from kang.test@dev.kang.com;

구체화된 뷰가 작성되었습니다.

SQL> select * from test_sf;

NAME
----------
강명규


원격지 DB
데이터를 하나 넣어 변경사항을 만들자.
SQL> insert into test values('강병욱', 29, '19730103');

1 row created.

SQL> commit;

Commit complete.

SQL> desc mlog$_test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 NAME                                               VARCHAR2(10)
 SNAPTIME$$                                         DATE
 DMLTYPE$$                                          VARCHAR2(1)
 OLD_NEW$$                                          VARCHAR2(1)
 CHANGE_VECTOR$$                                    RAW(255)

변경사항은 mlog$_test에 저장된다.
SQL> select * from mlog$_test;

NAME       SNAPTIME$ D O
---------- --------- - -
CHANGE_VECTOR$$
--------------------------------------------------------------------------------
강병욱     01-JAN-00 I N
FE

SQL> select * from rupd$_test;

no rows selected

5분후, mlog$_test의 row들은 원격지의 snapshot이 refresh되면서 없어진다.
SQL> select * from mlog$_test;

no rows selected


5분후 로컬 DB에서 확인
SQL> select * from test_sf;

NAME
----------
강명규

SQL> set time on
21:37:53 SQL> /

NAME
----------
강명규

21:37:55 SQL> select * from test_sf;

NAME
----------
강명규

5분후에 데이터가 로컬의 snapshot에 추가된 것을 알 수 있다.
21:38:01 SQL> /

NAME
----------
강명규
강병욱


원격지 DB
SQL> drop snapshot log on test;

Materialized view log dropped.

SQL> create snapshot log on test with (age, birth);

Materialized view log created.


로컬 DB
원격지 테이블의 모든 컬럼을 지정하게 snapshot을 변경한다.
21:51:56 SQL> set time off
SQL> create snapshot test_sf
  2  pctfree 5 pctused 60
  3  tablespace users
  4  storage (initial 50k next 50k)
  5  refresh fast next sysdate+(1/288)
  6  as
  7  select * from kang.test@dev.kang.com;

구체화된 뷰가 작성되었습니다.

SQL> select * from test_sf;

NAME              AGE BIRTH
---------- ---------- --------
강명규             27 19740509
강병욱             29 19730103

SQL> drop snapshot test_sf;

구체화된 뷰가 삭제되었습니다.



원격지 DB
SQL> drop snapshot log on test;

Materialized view log dropped.









[complex snapshot]
아래의 예에서는 3대의 DB서버가 필요하다.
dev와 dev2 서버에서 가져온 각각의 데이터를 통합하여 로컬DB의 테이블에 저장하는 예이다.

dev서버에서 emp테이블을 생성하고 '강명규'라는 데이터를 insert한다.
SQL> connect kang/xxxxxx@dev
연결되었습니다.
SQL> create table emp (
  2  name varchar2(10),
  3  age number);

테이블이 생성되었습니다.

SQL> insert into emp values('강명규', 27);

1 개의 행이 만들어졌습니다.

dev2서버에서 emp테이블을 생성하고 '홍길동'이라는 데이터를 insert한다.
SQL> connect kang/xxxxxx@dev2
연결되었습니다.
SQL> create table emp(
  2  name varchar2(10),
  3  age number);

테이블이 생성되었습니다.

SQL> insert into emp values('홍길동', 28);

1 개의 행이 만들어졌습니다.

로컬DB로 다시 연결하여 dev,dev2를 이용하여 스냅샵을 만들어 주자.
SQL> connect kang/xxxxxx
연결되었습니다.
SQL> create database link dev2.kang.com
  2  connect to kang identified by xxxxxx
  3  using 'dev2';

데이타베이스 링크가 생성되었습니다.

SQL> create snapshot all_emps
  2   pctfree 5 pctused 60
  3   tablespace users
  4   storage (initial 50k next 50k)
  5   using index storage (initial 25k next 25k)
  6   refresh start with round(sysdate+1)+11/24
  7   next sysdate+7
  8  as
  9   select * from kang.emp@dev2.kang.com
 10    union
 11   select * from kang.emp@dev.kang.com;

구체화된 뷰가 작성되었습니다.


SQL> select * from all_emps;

NAME              AGE
---------- ----------
강명규             27
홍길동             28



롤백세그먼트 지정(다음에 하자-skip)
마스터와 로컬 사이트에 refresh동안 사용되는 롤백세그먼트를 지정할 수 있다.
complex 스냅샵이라면 마스터 롤백세그먼트는 무시된다.

dev.kang.com
SQL> create tablespace MYRBS
  2  datafile '/ora8i/oradata/dev/rbs02.dbf' size 50m;

테이블 영역이 생성되었습니다.

SQL> create rollback segment myrbs01
  2  tablespace MYRBS
  3  storage( initial 10k next 10k maxextents unlimited);

롤백 세그멘트가 생성되었습니다.

로컬DB
SQL> create tablespace MYRBS
  2  datafile 'C:\ORACLE\ORADATA\MADDOG\rbs02.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> create rollback segment myrbs01
  2  tablespace MYRBS
  3  storage (initial 10k next 10k maxextents unlimited);

롤백 세그멘트가 생성되었습니다.

SQL> create snapshot temp_test
  2  refresh fast start with sysdate next sysdate+7
  3  using master rollback segment myrbs01
  4  local rollback segment myrbs01
  5  as
  6  select * from test@dev.kang.com;
select * from test@dev.kang.com
       *
6행에 오류:
ORA-23413: "KANG"."TEST" 테이블이 스냅샷 로그를 가지고 있지 않습니다

SQL> connect kang/xxxxxx@dev
연결되었습니다.
SQL> select * from test;

NAME              AGE BIRTH
---------- ---------- --------
강명규             27 19740509
강병욱             29 19730103

SQL> create snapshot log on test;

구체화된 뷰 로그가 작성되었습니다.

음.. 너무 길어진다.
롤백에서는 자꾸 에러가 나서 더 질려버렸다.
다음에 기회가 되면 다시 하겠다.

  1  create snapshot temp_test
  2  refresh fast start with sysdate next sysdate+7
  3  using master rollback segment myrbs01
  4  local rollback segment myrbs01
  5  as
  6* select name from kang.test@dev.kang.com
SQL> /
select name from kang.test@dev.kang.com
       *
6행에 오류:
ORA-06512: 줄 1에서


Primary-key와 rowid스냅샵

Primary-key스냅샵
create snapshot human_genome
 refresh fast start with sysdate next sysdate + 1/4096
 with primary key
as select * from genome_catalog;


rowid스냅샵
cretate snapshot emp_data with rowid
as select * from emp_table73;

Database Link사용법

더보기

Database Link사용법

원격지에 있는 데이터베이스를 link하는 법은 다음과 같다.

원격지의 Database의 Service Name이 piruks.kang.com이다.
나의 tnsnames.ora파일에는 Database alias가 piruks가 잡혀있다.

piruks.kang.com(원격지DB)의 init.ora내용
db_name = "piruks"
db_domain = kang.com
instance_name = piruks
service_names = piruks.kang.com

maddog.kang.com(로컬DB)의 tnsnames.ora내용
PIRUKS =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.102)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = PIRUKS.KANG.COM)
    )
  )





원격지의 패러미터파일(init.ora)에 global_names를 true로 하면 dblink의 이름과 접속하는 db의 이름이
동일하도록 요구한다.

global_names = true [ or false ]

이 설정은 다음과 같이 해서 알 수 있다.
SQL> select name, value from v$parameter where name='global_names';

NAME                 VALUE
-------------------- ------
global_names         FALSE


현재 데이터베이스의 이름은 global_names에 질의함으로써 알 수 있다.

SQL> connect kang/xxxxxx@piruks;
연결되었습니다.
SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------
PIRUKS.KANG.COM



local db에 kang이라는 사용자로 접속한다.
SQL> connect kang/xxxxxx
연결되었습니다.

이제 원격지(piruks.kang.com)의 DB에 kang이라는 사용자로 연결되는 Database link를 생성한다.
여기서 piruks.kang.com은 원격지의 [Database name].[Domain name]이다.
보통 [Database name].[Domain name]는 Service Name이라 불리운다.
하지만 위와 같이 해서 제대로 않되는 경우가 있다.
이럴때는 global_name에 있는 이름을 dblink이름으로 정하면 해결된다.
piruks는 database connect string이다.
SQL> create database link piruks.kang.com
  2  connect to kang identified by xxxxxx
  3  using 'piruks';

데이타베이스 링크가 생성되었습니다.



사용법은 다음과 같다.
보통의 DML문장에 '@piruks.kang.com'을 추가한다.
SQL> select * from tab@piruks.kang.com;

TNAME                                                        TABTYPE         CLUSTERID
------------------------------------------------------------ -------------- ----------
TEST                                                         TABLE

SQL> select * from test@piruks.kang.com;

NAME                        AGE
-------------------- ----------
강명규                       27

SQL> insert into test@piruks.kang.com values('홍길동', 30);

1 개의 행이 만들어졌습니다.

SQL> update test@piruks.kang.com set age=31 where age=30;

1 행이 갱신되었습니다.

SQL> select * from test@piruks.kang.com;

NAME                        AGE
-------------------- ----------
강명규                       27
홍길동                       31

SQL> delete from test@piruks.kang.com where age=31;

1 행이 삭제되었습니다.

데이터베이스링크에서 DDL문장은 적용되지 않는다.
SQL> drop table test@piruks.kang.com;
drop table test@piruks.kang.com
                *
1행에 오류:
ORA-02021: 원격 데이터베이스에 DDL 조작들이 허용되지 않습니다


SQL> drop database link piruks.kang.com;

데이타베이스 링크가 삭제되었습니다.

SQL>


[2003-07-30 추가]
public DB링크와 동의어의 사용
이제껏 설명한 private DB링크와는 달리, public DB링크는 DB내의 모든 사용자가 사용할 수 있다.
이는 일반계정에서는 사용하지 못하므로 system사용자에서 생성해야 한다.
일반계정에서 public DB링크를 생성하려면, 다음의 권한이 필요하다.

DROP PUBLIC DATABASE LINK
CREATE PUBLIC DATABASE LINK

system계정에서 다음의 명령으로 kang계정에 이 권한을 줄 수 있다.

SQL> grant CREATE PUBLIC DATABASE LINK, DROP PUBLIC DATABASE LINK to kang;

권한이 부여되었습니다.


SQL> connect system/xxxxxx
연결되었습니다.
SQL> create public database link db.world
  2  connect to kang identified by xxxxxx
  3  using 'linuxdb';

데이타베이스 링크가 생성되었습니다.
SQL> conn scott/tiger
연결되었습니다.
SQL> select * from v_emp@db.world;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
이하생략

12 개의 행이 선택되었습니다.

SQL> conn kang/xxxxxx
연결되었습니다.
SQL> select * from v_emp@db.world;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
이하생략

12 개의 행이 선택되었습니다.

이와 같이 매번 골뱅이와 DB링크명(@db.world)를 붙이면 불편하므로, 동의어를 사용하여 투명하게 사용할 수도 
있을 것이다. 모든 사용자에게 적용하려면 마찬가지로 system계정에서 public동의어를 생성하면 된다.

SQL> conn kang/xxxxxx
연결되었습니다.
SQL> create synonym v_emp for v_emp@db.world;

동의어가 생성되었습니다.

SQL> select * from v_emp;

     EMPNO ENAME      JOB              MGR HIREDATE        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17        800                    20
      7900 JAMES      CLERK           7698 81/12/03        950                    30
      7521 WARD       SALESMAN        7698 81/02/22       1250        500         30
이하생략

12 개의 행이 선택되었습니다.

SQL>


[2003-07-30 추가]
하나의 SQL명령에서 사용할 수 있는 DB링크수는 초기화 패러미터 open_links에 따라 정해진다.
디폴트는 4개다.
SQL> show parameter open_links

NAME                                 TYPE    VALUE
------------------------------------ ------- ------------------------------
open_links                           integer 4
open_links_per_instance              integer 4


[2003-07-30 추가]
본문에서 잠깐 언급했지만, DB링크가 제대로 생성되었으나 실제 질의시 실패하는 경우가 있다.
이 경우에는, 연결DB의 global_name에 지정된 문자열을 사용하면 해결된다.
원래 초기화패러미터 gloabl_names가 true일 경우에만, 이것을 강제하게 되어 있으나, 
이상한 것은 false일 경우에도 발생했다. 예제를 보면 쉽게 알 수 있을 것이다.

[문제**********]
DB링크는 에러없이 생성되나, 실제 질의가 실패함.
SQL> conn kang/xxxxxx
연결되었습니다.
SQL> create database link linuxdb_link
  2  connect to kang identified by xxxxxx
  3  using 'linuxdb';

데이타베이스 링크가 생성되었습니다.

SQL> select * from tab@linuxdb_link;
select * from tab@linuxdb_link;
                  *
1행에 오류:
ORA-02085: 데이터베이스 링크 LINUXDB_LINK.WORLD가 DB.WORLD에 연결됩니다


SQL> drop database link linuxdb_link;

데이타베이스 링크가 삭제되었습니다.


[해결책********]
원격DB서버의 global_name값을 확인
SQL> connect system/xxxxxx@linuxdb
SQL> show parameter global_names

NAME                                 TYPE    VALUE
------------------------------------ ------- ------------------------------
global_names                         boolean FALSE
연결되었습니다.
SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------------------------------------------------
DB.WORLD

다시 돌아와, DB링크생성시 이름을 위에서 확인한 global_names로 한다.
SQL> conn kang/xxxxxx
연결되었습니다.
SQL> create database link db.world
  2  connect to kang identified by xxxxxx
  3  using 'linuxdb';

데이타베이스 링크가 생성되었습니다.

SQL> select * from tab@db.world;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
A                              TABLE
AA                             TABLE
BONUS                          TABLE
CUSTOMER                       TABLE
DEPT                           TABLE
EMP                            TABLE
FAMILY                         TABLE
HITEL                          TABLE
ILSAN014                       TABLE
INTERIOR                       TABLE
MEMBER                         TABLE
MEMBER_DETAIL                  TABLE
PLAN_TABLE                     TABLE
SALGRADE                       TABLE
SAMWOO                         TABLE
SERVER                         TABLE
TEST                           TABLE
TM_YH                          TABLE
V_EMP                          VIEW

19 개의 행이 선택되었습니다.

SQL>

This article comes from dbakorea.pe.kr (Leave this line as is)

DBVERIFY사용

더보기

DBVERIFY사용

시스템적인 데이터의 무결성 검사는 패러미터파일의 DB_BLOCK_CHECKSUM파라미터를 
TRUE로 설정하거나 DBVERIFY유틸리티를 사용하여 파악할 수 있다.
보통 백업받은 데이터파일을 검사할 때 사용된다.

C:\Oracle\Ora81\BIN>dbv help=y

DBVERIFY: Release 8.1.6.0.0 - Production on 일 Oct 29 23:40:13 2000

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

키워드    설명               (기본)
----------------------------------------------
FILE      검증하기 위한 파일 (NONE)
START     블록 시작          (파일의 첫 블록)
END       마지막 블록        (파일의 최종 블록)
BLOCKSIZE 논리적 블록 크기 (2048)
LOGFILE   출력 로그          (NONE)
FEEDBACK  프로세스 보기      (0)

feedback 100는 출력되는 dot(.)하나당 100페이지를 의미한다.
C:\Oracle\Ora81\BIN>dbv file=C:\Oracle\oradata\maddog\system01.dbf feedback=100

DBVERIFY: Release 8.1.6.0.0 - Production on 일 Oct 29 23:39:08 2000

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

DBVERIFY - 검증 시작 : FILE = C:\Oracle\oradata\maddog\system01.dbf
................................................................................
..........................................................

DBVERIFY - 검증 완성

전체 페이지가 검색되었습니다      : 118976
전체 페이지가 프로세스됨 (데이터) : 81297
전체 페이지가 실패됨     (데이터) : 0
전체 페이지가 프로세스됨    (인덱스): 25224
전체 페이지가 실패됨        (인덱스): 0
전체 페이지가 처리되었습니다 (다른 것): 1922
전체 페이지가 비었습니다          : 10533
전체 페이지에 손상한 것 표시       : 0
전체 페이지 유입                  : 0

사용자의 default tablespace변경

더보기

사용자의 default tablespace변경

kang이라는 tablespace를 생성하자. 이 tablespace는 kang이라는 오라클유저에게
할당할 tablespace이다. 이는 2개의 데이터 파일로 구성되어 있다. 왜 2개의 데이터파일로
만들었을까? 테이블스페이스는 여러개의 데이터파일로 구성될 수 있다는 것을 보이려고 했고,
나중에 hot backup을 설명할때 쓰려고 만들었다. 필자는 요즘 예전에 봤던 내용을 상기하면서
정리하려고 하고 있다. (^_^)

SQL> create tablespace kang
  2  datafile
  3  'c:\oracle\oradata\maddog\kang01.dbf' size 5m,
  4  'c:\oracle\oradata\maddog\kang02.dbf' size 5m;
 
테이블 영역이 생성되었습니다.
 
kang이라는 유저의 디폴트 테이블공간을 kang으로 지정한다.
이 유저는 원래 오라클 설치시 부여되는 users라는 tablespace를 default tablespace로 가지고
있었고 여기에 kang1이라는 테이블을 가지고 있었다.
이렇게 default tablespace를 변경해도 자신이 가진 테이블과 테이블안의 데이터는 유지된다.
SQL> connect kang/xxxxxx
연결되었습니다.
SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
KANG1                          TABLE

SQL> desc kang1;
 이름                                                  널?      유형
 ----------------------------------------------------- -------- ----------------
 ID                                                    NOT NULL NUMBER(5)
 NAME                                                           VARCHAR2(10)
 BIRTH                                                          DATE
 SEX                                                            NUMBER(1)

SQL> select * from kang1;

        ID NAME       BIRTH           SEX
---------- ---------- -------- ----------
         1 강명규     75/01/01          1
         2 강병욱     73/01/03          1

SQL> connect system/xxxxxx
연결되었습니다.
SQL> alter user kang 
  2  default tablespace kang;

사용자가 변경되었습니다.

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> select * from kang1;

        ID NAME       BIRTH           SEX
---------- ---------- -------- ----------
         1 강명규     75/01/01          1
         2 강병욱     73/01/03          1

파티셔닝 이용하기

더보기

파티셔닝 이용하기

하나의 테이블이 여러개의 테이블스페이스를 사용하여 경합(?하하)을 줄이기 위해 사용할 겁니다.
자세한건 매뉴얼을 찾아보세요..
다음은 제가 실습해 본 겁니다.


sys로 로그인
3개의 테이블스페이스를 생성합니다. 
후에 하나의 테이블이 여기서 생성된 3개의 테이블스페이스를 사용합니다.
SQL> create tablespace ts1 
2 datafile 'e:\oracle_tablespace\ts1.dbf'
3 size 5m;

테이블 영역이 생성되었습니다.

SQL> create tablespace ts2
2 datafile 'e:\oracle_tablespace\ts2.dbf'
3 size 5m;

테이블 영역이 생성되었습니다.

SQL> create tablespace ts3
2 datafile 'e:\oracle_tablespace\ts3.dbf'
3 size 5m;

테이블 영역이 생성되었습니다.


kang으로 로그인
실습하기 편하라고 일부로 SQL프롬프트를 제거했습니다. 정말일까?
CREATE TABLE stock_xactions(
stock_symbol CHAR(5),
stock_series CHAR(1),
num_shares NUMBER(10),
price NUMBER(5,2),
trade_date DATE
)
STORAGE (INITIAL 100K NEXT 50K) LOGGING
PARTITION BY RANGE (trade_date)
(
PARTITION sx1992 VALUES LESS THAN (TO_DATE('01-JAN-1993', 'DD-MON-YYYY' )) TABLESPACE ts1 NOLOGGING,
PARTITION sx1993 VALUES LESS THAN (TO_DATE('01-JAN-1994', 'DD-MON-YYYY' )) TABLESPACE ts2,
PARTITION sx1994 VALUES LESS THAN (TO_DATE('01-JAN-1995', 'DD-MON-YYYY' )) TABLESPACE ts3
)
/

insert into stock_xactions(stock_symbol, trade_date) values ('00001', TO_DATE('02-JAN-1992', 'DD-MON-YYYY' ) );
insert into stock_xactions(stock_symbol, trade_date) values ('00001', TO_DATE('03-JAN-1993', 'DD-MON-YYYY' ) );
insert into stock_xactions(stock_symbol, trade_date) values ('00001', TO_DATE('04-JAN-1994', 'DD-MON-YYYY' ) );


음.. 제대로 들어갔군..
SQL> select * from stock_xactions;

STOCK S NUM_SHARES PRICE TRADE_DA
----- - ---------- ---------- --------
00001 92/01/02
00001 93/01/03
00001 94/01/04


sys로 로그인하여 ts1테이블스페이스를 사용못하게 해보자..
SQL> connect sys/xxxxxx
연결되었습니다.
SQL> alter tablespace ts1 offline;

테이블 영역이 변경되었습니다.

SQL> connect kang/kang
연결되었습니다.

당연히 select를 못한다. ts1을 offline상태로 변경했기 때문에
SQL> select * from stock_xactions;
select * from stock_xactions
*
1행에 오류:
ORA-00376: 현재 파일 7를 읽을 수 없습니다
ORA-01110: 7 데이터 파일: 'E:\ORACLE_TABLESPACE\TS1.DBF'

해당 테이블스페이스에 없는 row를 검색하면 select된다. 하하 좋군..
SQL> select * from stock_xactions where trade_date = TO_DATE('03-JAN-1993', 'DD-MON-YYYY' );

STOCK S NUM_SHARES PRICE TRADE_DA
----- - ---------- ---------- --------
00001 93/01/03

다시 ts1 테이블스페이스를 사용가능하게 online으로 변경하자.
SQL> connect sys/xxxxxx
연결되었습니다.
SQL> alter tablespace ts1 online;

테이블 영역이 변경되었습니다.

SQL> connect kang/kang
연결되었습니다.

이제 모든 데이터가 검색된다..
SQL> select * from stock_xactions;

STOCK S NUM_SHARES PRICE TRADE_DA
----- - ---------- ---------- --------
00001 92/01/02
00001 93/01/03
00001 94/01/04

질의가 좀 복잡죠?
쩝.. 실제 데이터가 해당 테이블스페이스를 사용하는가 보고자 하는 겁니다.
금방 사용되는지 알 수 있겠죠?
SQL> l
1 select FILE_NAME as Filename,
2 d.TABLESPACE_NAME as Tablespace,
3 d.BYTES as "Datafile Size",
4 nvl(sum(e.BYTES),0) as "Bytes Used",
5 round(nvl(sum(e.BYTES),0) / (d.BYTES), 4) * 100 as "Percent Used",
6 d.BYTES - nvl(sum(e.BYTES),0) as "Bytes Free"
7 from DBA_EXTENTS e, DBA_DATA_FILES d
8 where d.FILE_ID = e.FILE_ID (+)
9 group by FILE_NAME, d.TABLESPACE_NAME, d.FILE_ID, d.BYTES, STATUS
10* order by d.TABLESPACE_NAME, d.FILE_ID
SQL> /


FILENAME                                 TABLESPACE                     Datafile Size Bytes Used Percent Used Bytes Free
 
---------------------------------------- ------------------------------ ------------- ---------- ---
 
C:\ORANT\ORADATA\KANG\INDX01.DBF         INDX                                60817408          0            0   60817408
 
C:\ORANT\ORADATA\KANG\RBS01.DBF          RBS                                545259520   29360128         5.38  515899392
 
C:\ORANT\ORADATA\KANG\SYSTEM01.DBF       SYSTEM                              88997888   88793088        99.77     204800
 
C:\ORANT\ORADATA\KANG\TEMP01.DBF         TEMP                                75497472          0            0   75497472
 
C:\ORANT\ORADATA\KANG\TOOLS01.DBF        TOOLS                               12582912          0            0   12582912
 
E:\ORACLE_TABLESPACE\TS1.DBF             TS1                                  5242880     122880         2.34    5120000
 
E:\ORACLE_TABLESPACE\TS2.DBF             TS2                                  5242880     122880         2.34    5120000
 
E:\ORACLE_TABLESPACE\TS3.DBF             TS3                                  5242880     122880         2.34    5120000
 
C:\ORANT\ORADATA\KANG\USERS01.DBF        USERS                              113246208    1441792         1.27  111804416
 

 
9 개의 행이 선택되었습니다.
 
Copyleft(C) 명규의 오라클OCP All rights free

SQL Trace / TKPROF 사용

더보기

SQL Trace / TKPROF 사용

작성일  : 2002-03-09
수정일  : 2004-01-10
작성자  : 강명규
OS      : LINUX kernel 2.4.10(x86)
ORACLE  : 9.0.1 EE
참조문서: Oracle8i Designing and Tuning for Performance

수정내용
3가지 패러미터에 대한 세션내의 설정을 모두 timed_statistics 로 한 것을 각각에 맞게 수정.

[SQL Trace]
실행되는 SQL문장에 대해 분석정보를 제공하므로 사용자(프로그래머,..)가 특정 SQL문장을 
어떻게 사용해야겠다는 가이드라인을 제공해준다. EXPLAIN PLAN과 병행하여 사용하는 것이 좋다.

다음과 같은 분석정보를 제공한다.

parse,execute,fetch수
CPU시간/경과된 시간
물리적/논리적 reads
처리된 로우수
라이브러리 캐쉬 misses
파싱이 발생할 때의 사용자
커밋/롤백



SQL_TRACE와 관련된 패러미터는 3가지가 있고, 모두 동적패러미터(dynamic parameter)이다.

timed_statistics   : CPU시간, 실행시간등 시간에 관련된 정보를 표시하기 위해 사용된다.
                     지속적인 설정을 위해 패러미터파일(init.ora)에 설정하거나 
                     세션에서만 임시로 설정하기 위해 alter session set timed_statistics=true 로 사용할 수 있다.

max_dump_file_size : 트레이스파일의 최대 크기(단위: OS블럭수), 문서에는 500이 디폴트라고 했지만 실제로는 unlimited였다.
                     지속적인 설정을 위해 패러미터파일(init.ora)에 설정하거나 
                     세션에서만 임시로 설정하기 위해 alter session set max_dump_file_size=500 로 사용할 수 있다.

user_dump_dest     : 트레이스파일이 생성될 디렉토리
                     여기서는 /u01/app/oracle/admin/dev/udump라고 가정한다.
                     지속적인 설정을 위해 패러미터파일(init.ora)에 설정하거나 
                     인스턴스에서만 임시로 설정하기 위해 alter system set user_dump_dest=/tmp 로 사용할 수 있다.


SQL Trace는 세션레벨 혹은 인스턴스레벨에서 enable될 수 있다.
인스턴스레벨에서 모든 SQL을 트레이스하는 경우는 거의 없으므로
DB응용프로그램에서 사용되는 특정 SQL에 대해서만 트레이스하는 것이 일반적이다.
그리고 트레이스를 enable하는것은 당연히 DB의 부하를 발생하는 것이라 필요할때만
사용하고 평상시의 production환경에서는 disable하는 것이 좋다.

enable : alter session set sql_trace=true 혹은 
         exec dbms_session.set_sql_trace(true)

disable: alter session set sql_trace=false 혹은
         exec dbms_session.set_sql_trace(false)


[TKPROF]
오라클 유틸리티 프로그램으로 OS상에 실행파일로 존재한다.
TKPROF은 SQL Trace가 생성한 트레이스파일을 분석하여 우리가 알아보기 쉬운 출력파일을 생성한다.
SQL문장이 실행될때마다 사용된 리소스량, 시간, 로우수등에 대해 보고한다.


출력예

select * 
from
 t t1 where object_id=55


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.01          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0          4          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.02       0.01          0          4          0           0

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 49  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  TABLE ACCESS BY INDEX ROWID T 
      0   INDEX SKIP SCAN (object id 31310)





SQL Trace 사용예제
우선 USER_DUMP_DEST로 지정된 디렉토리내 모든 TRACE파일들을 삭제한다.
삭제하지 않아도 되지만, 이렇게 하는 이유는 SQL_TRACE를 TRUE로 변경시
생성되는 트레이스파일명이 명확하지 않아서이다.
즉, 파일은 USER_DUMP_DEST에 지정된 디렉토리에 생성되지만, 어떤 파일명을 
가지는지는 오라클이 지맘대로 알아서 정한다.

SQL> create table t
  2  as
  3  select decode(mod(rownum,2),0,'M','F') gender, all_objects.*
  4  from all_objects;

테이블이 생성되었습니다.

SQL> create index t_idx on t(gender, object_id);

인덱스가 생성되었습니다.

SQL> select count(1) from t;

  COUNT(1)
----------
     26878

SQL> analyze table t compute statistics
  2  for table
  3  for all indexes
  4  for all indexed columns;

테이블이 분석되었습니다.

SQL> alter session set timed_statistics=true;

세션이 변경되었습니다.

SQL> alter session set sql_trace=true;

세션이 변경되었습니다.

SQL> select * from t t1 where object_id=55;

선택된 레코드가 없습니다.

SQL> alter session set sql_trace=false;

세션이 변경되었습니다.

SQL> drop table t;

테이블이 삭제되었습니다.

SQL> create table t
  2  as
  3  select chr(mod(rownum,256)) gender, all_objects.*
  4  from all_objects;

테이블이 생성되었습니다.

SQL> create index t_idx on t(gender, object_id);

인덱스가 생성되었습니다.

SQL> analyze table t compute statistics
  2  for table
  3  for all indexes
  4  for all indexed columns;

테이블이 분석되었습니다.

SQL> alter session set sql_trace=true;

세션이 변경되었습니다.

SQL> select * from t t2 where object_id=55;

선택된 레코드가 없습니다.

SQL> alter session set sql_trace=false;

세션이 변경되었습니다.





TKPROF 사용예제
위에서 질의했던 것들은 ora_17994.trc라는 트레이스파일에 기록되어 있다.
트레이스파일명은 앞서 말했듯이 파악하기 힘드므로 자~알 찾아야 한다.
 
[oracle@dev2 udump]$ tkprof ora_17994.trc skip_scan_query_report.txt
[oracle@dev2 udump]$ cat skip_scan_query_report.txt 

TKPROF: Release 9.0.1.0.0 - Production on Fri Mar 8 20:39:22 2002

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

Trace file: ora_17994.trc
Sort options: default

********************************************************************************
count    = number of times OCI procedure was executed
cpu      = cpu time in seconds executing 
elapsed  = elapsed time in seconds executing
disk     = number of physical reads of buffers from disk
query    = number of buffers gotten for consistent read
current  = number of buffers gotten in current mode (usually for update)
rows     = number of rows processed by the fetch or execute call
********************************************************************************

alter session set sql_trace=true


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        0      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.00          0          0          0           0

Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 49  
********************************************************************************

select /*+ rule */ bucket_cnt, row_cnt, cache_cnt, null_cnt, timestamp#, 
  sample_size, minimum, maximum, distcnt, lowval, hival, density, col#, 
  spare1, spare2, avgcln 
from
 hist_head$ where obj#=:1 and intcol#=:2


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute     24      0.00       0.00          0          0          0           0
Fetch       24      0.00       0.00          0         48          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       50      0.00       0.00          0         48          0           0

Misses in library cache during parse: 0
Optimizer goal: RULE
Parsing user id: SYS   (recursive depth: 1)
********************************************************************************

select * 
from
 t t1 where object_id=55


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.01          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0          4          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.02       0.01          0          4          0           0

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 49  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  TABLE ACCESS BY INDEX ROWID T 
      0   INDEX SKIP SCAN (object id 31310)

********************************************************************************

alter session set sql_trace=false


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          0          0           0

Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 49  
********************************************************************************

select * 
from
 t t2 where object_id=55


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.01          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.07       0.06          0        389         18           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.08       0.07          0        389         18           0

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 49  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  TABLE ACCESS FULL T 




********************************************************************************

OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        4      0.03       0.02          0          0          0           0
Execute      6      0.00       0.00          0          0          0           0
Fetch        2      0.07       0.06          0        393         18           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       12      0.10       0.09          0        393         18           0

Misses in library cache during parse: 2


OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute     24      0.00       0.00          0          0          0           0
Fetch       24      0.00       0.00          0         48          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       50      0.00       0.00          0         48          0           0

Misses in library cache during parse: 0

    6  user  SQL statements in session.
    2  internal SQL statements in session.
    8  SQL statements in session.
********************************************************************************
Trace file: ora_17994.trc
Trace file compatibility: 9.00.01
Sort options: default

       1  session in tracefile.
       6  user  SQL statements in trace file.
       2  internal SQL statements in trace file.
       8  SQL statements in trace file.
       5  unique SQL statements in trace file.
     118  lines in trace file.

autotrace사용하기(Windows 2000 + Oracle 8i(8.1.6) )

더보기

autotrace사용하기(Windows 2000 + Oracle 8i(8.1.6) )

autotrace는 옵티마이저의 실행계획을  질의를 실행시마다 함께 보여줍니다.
질의의 실행계획을 알아냄으로써 질의의 성능을 파악하는데 도움이 될 것입니다.

SQL> connect kang/xxxxxxx@kang (자신의 계정으로 실행)
연결되었습니다.

SQL> start c:\orant\rdbms\admin\utlxplan.sql

SQL> connect sys/xxxxxxxx (관리자로 로그인하여 실행)
연결되었습니다.

SQL> start c:\orant\sqlplus\admin\plustrce.sql

SQL> drop role plustrace;
drop role plustrace
*
1행에 오류:
ORA-01919: 롤 'PLUSTRACE'(이)가 존재하지 않습니다


SQL> create role plustrace;

롤이 생성되었습니다.

SQL> 
SQL> grant select on v_$sesstat to plustrace;

권한이 부여되었습니다.

SQL> grant select on v_$statname to plustrace;

권한이 부여되었습니다.

SQL> grant select on v_$session to plustrace;

권한이 부여되었습니다.

SQL> grant plustrace to dba with admin option;

권한이 부여되었습니다.

SQL> 

SQL> set echo off

SQL> grant plustrace to kang;

권한이 부여되었습니다.

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> set autotrace on        질의를 할때마다 실행계획을 보여주게 함
SQL> create table test (
2 name varchar(10),
3 age number(3)
4 );

테이블이 생성되었습니다.

SQL> insert into test values('강명규', 27);

1 개의 행이 만들어졌습니다.


Execution Plan
----------------------------------------------------------
0 INSERT STATEMENT Optimizer=CHOOSE




Statistics
----------------------------------------------------------
2 recursive calls
8 db block gets
2 consistent gets
0 physical reads
664 redo size
851 bytes sent via SQL*Net to client
562 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> select * from test;

NAME AGE
---------- ----------
강명규 27


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'TEST'        음 질의가 테이블 full스캔을 하는군.. 보통 이런 질의를 하는 것은 좋지 않겠죠?




Statistics
----------------------------------------------------------
0 recursive calls
4 db block gets
1 consistent gets
0 physical reads
0 redo size
425 bytes sent via SQL*Net to client
424 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
질의에 대한 Execution Plan은 다음에 설명드리겠습니다.
//========================================================================
실행계획 

수동으로 실행계획을 파악하는 방법을 설명합니다.
사용자가 질의한 것이 어떤식으로 실행될 것인가(실행계획)을 파악한다면
애플리케이션을 코딩하면서 이를 이용하면 질의를 작성하는데 좀더 현명하게 적용할 수 있을 겁니다.

SQL> connect test/xxxxxx@xxxx
연결되었습니다.
SQL> select * from tab;

TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
COUNTER TABLE
COUNTER_CODE TABLE
MEETING TABLE
WREAD TABLE

SQL> start c:\orant\rdbms\admin\utlxplan.sql    이는 plan_table을 생성해줍니다.

테이블이 생성되었습니다.

SQL> select * from tab;

TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
COUNTER TABLE
COUNTER_CODE TABLE
MEETING TABLE
PLAN_TABLE TABLE
WREAD TABLE

SQL> desc meeting;
이름 널? 유형
----------------------------------------- -------- ----------------------------
CODE NOT NULL VARCHAR2(20)
SEX VARCHAR2(5)
AGE VARCHAR2(5)
AREA VARCHAR2(5)
COUNTER VARCHAR2(9)
SUBJECT VARCHAR2(50)
COMMENTS VARCHAR2(200)
FAVORITE VARCHAR2(100)
H_PHONE VARCHAR2(20)
NAME VARCHAR2(20)
PSWORD VARCHAR2(20)
SIGN_DATE VARCHAR2(30)
MAIL VARCHAR2(30)

SQL> explain plan
2 set statement_id='kang4'    kang4는 이 질의에 대한 일종의 식별자입니다.(마음대로 적으세요)
3 into plan_table for
4 select sex, area, h_phone from meeting;

해석되었습니다.

SQL> select lpad(' ', 2*level) ||operation||' '||options||' '||object_name as query_plan
2 from plan_table
3 where statement_id='kang4'
4 connect by prior id = parent_id and statement_id = 'kang4';

QUERY_PLAN
--------------------------------------------------------------------------------
SELECT STATEMENT
TABLE ACCESS FULL MEETING
TABLE ACCESS FULL MEETING


SQL> delete from plan_table;

4 행이 삭제되었습니다.

SQL> commit;

커밋이 완료되었습니다.


autotrace를 이용하면 위와 같이 불편하게 입력할 필요는 없을 겁니다.
//==========================================================================
윈도NT에서 커맨드라인에서 오라클서비스 시작/종료(net명령)
 
NT상에서 오라클의 시작은 보통 제어판-서비스에서 시작할 수 있다.
하지만 도스 프롬프트 상에서도 가능하다.

시작 배치파일은 다음과 같이 될 수 있다.
net start "OracleAgent80"
net start "OracleStartSID"
rem net start "OracleServiceSID" /y
net start "OracleTNSListener80"

서비스의 종료는 start대신 stop을 사용할 수 있다.

다음은 OracleAgent80이라는 서비스를 도스프롬프트에서 시작하는 예이다.

C:\>net start "OracleAgent80"
OracleAgent80 서비스를 시작합니다....................
OracleAgent80 서비스가 잘 시작되었습니다.


C:\>net stop "OracleAgent80"
OracleAgent80 서비스를 멈춥니다....
OracleAgent80 서비스를 잘 멈추었습니다.
Copyleft(C) 명규의 오라클OCP All rights free
//========================================================================
NT에서 Instance Manager를 이용한 서비스 제어


test라는 인스턴스에 대한 서비스를 생성(제어판-서비스에 등록된다.)
oradim80 -new -sid test -initpwd manager -startmode auto -pfile c:\orant\database\inittest.ora

서비스시작
oradim80 -startup -sid test -starttype srvc,inst -usrpwd manager -pfile c:\orant\database\inittest.ora

사용할 instance선택
유닉스와 비슷하게 set Oracle_Sid=test와 같이 한다.

기존의 서비스(제어판-서비스)를 제거할때
oradim80 -delete -sid test

ODBC설정과 사용

더보기

ODBC설정과 사용

-- 설정 화면 캡쳐가 다 날라 갔네요. 참고 바랍니다.

NT에서 ODBC의 설정은 다른 DBMS의 설정과 약간 틀리다. 
MS-SQL이나 Access의 경우 바로 제어판-ODBC에서 설정이 가능하지만 오라클은 
이와는 달리 일단 서비스이름을 지정해야 한다. MS-SQL, Access에서 ODBC설정은 
따로 설명하지 않을 것이다. 
그럼 서비스이름을 지정하는 방법을 알아보자 
Oracle Net8 Easy Config를 실행한다. 
디폴트 설치시 시작-프로그램-Oracle for Windows NT폴더에서 찾을 수 있다. 
 
새로운 서비스를 등록하는 것이므로 Choose Action란에는 Add New Service를 선택. 
Choose Service Name의 New Service Name은 후에 ODBC를 설정할 때 사용할 이름이다. 
test라는 DB를 이용하는 것이어서 나는 testdb라고 지정했다. 보통 test_service라고 지정하기도 한다. 
NEXT버튼을 누른다. 
 
연결에 사용할 프로토콜을 지정하는 부분이다. 
단순히 TCP/IP프로토콜을 지정한다. 
 
Host Name, Port를 지정하는 부분이다. 
Port는 디폴트로 사용하고(만일 포트번호를 바꾸고 싶다면 1024이상의 숫자를 사용하라) 
Host Name을 자신의 컴퓨터이름으로 지정한다. 나의 경우 maddog-nt라는 컴퓨터이름을 가지고 있다. 
 
제일 중요한 부분이다. 
SID를 선택하는 부분으로, 쉽게 사용할 DB를 선택하는 것이다. 
앞에서 설명했듯이 test DB를 사용하므로 test라고 입력했다. 
 
이제까지 설정한 Service를 테스트하는 부분이다. 
처음 서비스를 추가하는 것이므로 테스트를 한 번 해본다. 
서비스 이전에 DB Instance가 시작상태에 있는 것을 확인한다. 
 
테스트가 성공했음을 확인한다. 
NEXT버튼을 누르면 마지막 부분으로 넘어간다.  끝으로 FINISH버튼을 누른다. 
이제 서비스가 등록되었으므로 ODBC설정만 남았다. 
제어판-ODBC데이터원본을 선택, 시스템 DSN탭에서 추가버튼을 누른다. 
데이터원본의 드라이버를 선택하는 화면이 나타나는데 여기서 
Oracle ODBC Driver 8.00.05.00을 선택하고 나타나는 다이얼로그에서 그림과 같이 설정한다. 
 
Data Source Name은 ODBC를 사용하여 DB연결을 하는 응용프로그램에서 사용할 
이름이다. Service Name은 Net8 Easy Config에서 설정했던 서비스이름을 지정한다. 
UserID는 사용할 DB에 존재하는 사용자의 ID를 지정한다.

DB삭제하기

더보기

DB삭제하기

-- 설정 화면 캡쳐가 다 날라 갔네요. 참고 바랍니다.

사실 제어판-서비스에 생성되는 오라클서비스만 제외한다면 유닉스에서와 다를 것이 없다.
Oracle Database Assistant를 이용하는 방법도 있는데 아래의 방법으로 더 빨리 제거할 수 있다.
Oracle Database Assistant는 자바로 실행되기에 좀 느리다.
우선, 아래와 같이 제어판-서비스에서 해당 DB의 서비스들을 제거한다.
디폴트로 설치되는 DB인 orc1과 필요에 의해 생성했던 test, mad라는 총 3개의 DB를 제거한다.
오라클 서비스제거(제어판-서비스 항목중 OracleServiceSID를 제거한다.)
C:\>oradim80 -delete -sid test
C:\>oradim80 -delete -sid mad
C:\>oradim80 -delete -sid orc1
스타트서비스제거(제어판-서비스 항목중 OracleStartSID를 제거한다.)
C:\>oradim80 -delete -srvc OracleStartMAD
C:\>oradim80 -delete -srvc Oraclestarttest
C:\>oradim80 -delete -srvc oraclestartorc1
일단 제어판-서비스에서 해당 DB의 서비스들을 제거하면 이후로는 DB의 데이터파일들만 제거해
주면 된다. 패러미터파일은 취향에 따라 제거해 주든지 하고(C:\ORANT\DATABASE\INITSID.ORA)..



앞서 DB생성시 만들었던 데이터파일들이다. 
이 놈들을 OS의 삭제 명령으로 간단히 지워주면 되는데 삭제 전에 DB의 인스턴스를 종료했음을
확인하자. 해당 DB의 데이터파일들이 무엇이고 위치가 어디에 있는지 모른다면 미리 
V$DATAFILE, V$CONTROLFILE, V$LOGFILE에 질의하여 알아둔다.
만일 archive log나 trace파일을 생성한다면 이도 고려하면 좋을 것이다.
이것은 서버관리자에서 show parameters로 질의하면 알 수 있을 것이다.
아래는 mad(Oracle Database Assistant로 생성한 DB)라는 DB를 SQL WorkSheet상에서 질의한 결과이다.
SQLWKS> select name from v$datafile
     2> 
NAME                                                                            
--------------------------------------------------------------------------------
E:\ORADATA\DATABASE\SYS1MAD.ORA                                                 
E:\ORADATA\DATABASE\RBS1MAD.ORA                                                 
E:\ORADATA\DATABASE\USR1MAD.ORA                                                 
E:\ORADATA\DATABASE\TMP1MAD.ORA                                                 
E:\ORADATA\DATABASE\INDX1MAD.ORA                                                
5 행이 선택되었습니다
SQLWKS> select * from v$logfile
     2> 
GROUP#     STATUS  MEMBER                                                                          
---------- ------- --------------------------------------------------------------------------------
         1         E:\ORADATA\DATABASE\LOGMAD1.ORA                                                 
         2         E:\ORADATA\DATABASE\LOGMAD2.ORA                                                 
2 행이 선택되었습니다
 
SQLWKS> select * from v$controlfile
     2> 
STATUS  NAME                                                                            
------- --------------------------------------------------------------------------------
        E:\ORADATA\DATABASE\CTL1MAD.ORA                                                 
        E:\ORADATA\DATABASE\CTL2MAD.ORA                                                 
2 행이 선택되었습니다
//============================================================================
Oracle Database Assistant를 이용한 DB생성
Oracle Database Assistant를 이용하면 유닉스에서와 같이 관리자가 일일이 수동으로
sql문을 작성할 필요가 없이 DB생성을 MS가 자랑하는 마법사와 같이 interactive하게 진행
할 수 있다. 그럼, 실제 그림을 보면서 알아보자. (어쩔 수 없이 그림으로 도배하는군요)

위에서 보듯이 DB의 생성, 삭제, 수정을 할 수 있다.
DB를 생성할 것이므로 첫벗째 라디오 버튼을 선택했다.

위에서 Custom을 선택한다.
그렇지 않고 Typocal을 선택하면 모든 과정을 Oracle Database Assistant가 자동으로 진행한다.

카트리지는 본인이 설치하지 않은 관계로 선택할 수 없게 되어 있다.
Advanced Replication은 선택하지 않았다. 

디폴트로 Medium으로 되어 있지만 그럴 필요 없으므로 Small로 선택했다.
Change Character Set은 DB생성후 수정할 수 없다. 하지만 디폴트로 한국어로 되어 있으므로
그냥 놔두면 이상없다.

DB의 이름을 지정하는 중요한 부분이다.
DB이름은 mad로 지정했고, 초기화 패러미터 파일은 e:드라이브에 두었다. password는
internal, sys가 사용하는 비밀번호(manager라고 지정했다)를 지정한다. 수동설치에서 sys의 
디폴트 password가 change_on_install이었지만 여기서 지정하므로 manager가 된다.



컨트롤 파일을 설정하는 부분이다. 디폴트로 사용했다.

데이터파일들을 설정하는 부분이다. 디폴트로 사용했다

로그파일을 설정하는 부분이다. 디폴트로 사용했다.

checkpoint와 archive log의 사용을 설정한다. Archive log기능은 디폴트로 사용하지 않게 설정된다.
checkpoint interval은 운영체제의 block크기로 설정한다는 것에 유의하자.

디폴트로 Shared Pool Size는 너무 크므로(필자의 환경에서는) 작게 잡았다.
나머지 부분은 동일하다. Process는 백그라운드프로세스를 포함한 숫자임을 유의하자.

user, background프로세스의 로그를 저장할 것인가를 설정한다. 디폴트로 두었다.

마지막으로 DB를 생성한다. Finish버튼을 누른다.

DB를 생성하는 과정을 보여준다.

Oracle Database Assistant가 DB생성과정을 종료하면 OracleServiceMAD와 OracleStartMAD가 
제어판-서비스에 추가된 것을 확인할 수 있다. OracleServiceMAD는 시작상태에 있다.
이제까지 Oracle Database Assistant로 DB를 생성하는 과정을 설명했다.
필자의 경우 이 과정에서 몇개의 에러 메시지가 표시되었으나 무슨 뜻인지도 모르겠고 해서
그냥 무시해버렸다. 나중에 SQL WorkSheet로 로그인하니 오라클의 버전도 표시하지 않았다.
그래서 그냥 catproc.sql을 다시 실행해 버리니 문제가 없었다.
 
Oracle Database Assistant로 DB생성후 할 작업
오라클 설치시 디폴트로 SID는 orc1로 되어 있다. 이것을 mad라고 바꾸어 보자.
regedit를 연다. (윈도에서 시작-실행을 선택해 regedit라고 입력한후 엔터)
그림과 같이 오라클의 SID가 ORC1로 되어 있는 것을 알 수 있다.

ORACLE_SID를 mad로 변경한다. (ORACLE_SID항목을 더블클릭한 후 수정하면 된다.)
만일 한 시스템에 여러개의 DB인스턴스를 가진다면 매번 레지스트리를 수정해야 하나?
그럴 경우엔 DB의 서비스이름을 지정해 준다. 

위의 그림은 Instance Manager를 실행할 때 뜨는 대화상자이다.
앞에서 ORACLE_SID를 MAD로 변경했기 때문에 Service항목을 따로 지정하지 않아도 로그인할 수 있다.
하지만 여러 DB를 사용한다면 각 DB마다 서비스이름을 지정하고 그 이름을 Service항목에 지정함으로써
해당 DB에 로그인할 수 있다. 서비스이름설정은 OCBC설정과 사용을 참고하라.
제어판-서비스에서 OracleStartMAD서비스는 시작되지 않았으므로 위와 같이 SYSDBA로서 Instance Manager에
로그인한다. SYSDBA가 아니라면 로그인이 불가능하다. system사용자는 인스턴스를 시작할 수 없다는 것에 유의하라.

Database Open을 선택하여 Apply버튼을 클릭하면 MAD인스턴스가 시작한다.
일반사용자를 등록하는 것으로 설명을 마치기로 한다.
다음과 같이 kang이라는 사용자를 등록하자.
사용자를 생성하기에 앞서 사용자에게 할당할 테이블스페이스를 확인한다.
SQLWKS> select * from v$tablespace
     2> 
TS#        NAME                          
---------- ------------------------------
         0 SYSTEM                        
         1 RBS                           
         2 USR                           
         3 TEMPORARY                     
         4 INDX                          
5 행이 선택되었습니다
kang이라는 사용자를 생성한다.
SQLWKS> create user kang identified by kang
     2> default tablespace usr
     3> temporary tablespace temporary
     4> profile default
     5> 
명령문이 처리되었습니다
connect, resource권한을 부여한다.
SQLWKS> grant connect, resource to kang
     2> 
명령문이 처리되었습니다
제대로 되었는지 kang으로 로그인해 본다.
SQLWKS> connect kang/kang
연결되었습니다

윈도NT에서 DB생성

더보기

윈도NT에서 DB생성

윈도NT에서 DB생성은 간단히 oracle database assistant를 실행하여
만들 수 있다. 아래는 유닉스방식으로 생성하는 방식을 설명한다.

참고:
오라클의 database assistant는 db생성, 서비스등록과 설정파일,
DB생성스크립트를 만들어준다. 
간단한 DB를 database assistant로 생성한 후, 추가적인
tablespace, data file을 생성하기 위해 서버매니저를 실행하거나
initSID.ora를 수정한다.

오라클이 설치된 디렉토리는 c:\orant, 오라클 인스톨시 설치되는 
디폴트 DB이름이 ORC1이라고 가정한다.
새로 생성할 DB이름은 test라고 지정할 것이다.

윈도NT에서는 유닉스와는 DB생성과 인스턴스의 시작이 차이가 있다.
일단 C:\orant\database\initorc1.ora의 파일을 같은 디렉토리에
C:\orant\database\inittest.ora로 복사하고 파일안의 db_name과
control_files패러미터를 편집한다. 아래와 같다.

참고:
oracle_sid는 db_name과 같다.
즉, 동일하게 생각하면 된다. sid는 instance identifier 혹은 system identifier로 불리운다. 

inittest.ora 편집
db_name=test
control_files = e:\ora_data\DATABASE\test\control01.ctl
rollback_segments=(r01, r02)
db_block_buffers=100
remote_login_passwordfile = exclusive

참고:
디폴트DB의 shared_pool_size, db_block_buffers값이 너무 높게 
설정되어 있었다. remote_login_passwordfile은 exclusive로 했다.

NT에서는 유닉스와는 달리 서버매니저를 실행하려면 일단 3개의 
서비스를 시작해야 한다. 디폴트DB는 설치시 자동으로 제어판-서비스
항목에 자신을 등록해 놓았다.
오라클8을 사용한다면 다음의 서비스가 시작되어야 한다.

OracleServiceORC1, OracleStartORC1, OracleTNSListener80

이 서비스는 인스턴스 매니저(Instance Manager)의 커맨드라인모드에서
등록될 수 있다. 아래와 같이 입력한다. 참고로 위의 숫자80은 오라클버전을
의미한다. 참고로 오라클7.3은 oradim73.exe와 같은 실행화일을 가진다.

C:\>oradim80 -new -sid test -intpwd manager -startmode auto -pfile c:\orant\database\inittest.ora

제어판-서비스를 확인한다.
OracleServiceTEST와 OracleStartTEST가 서비스에 추가된 것을 확인할 수 있을 것이다.
확인해 보면 OracleServiceTEST만 시작상태에 있는 것을 유의하라.
OracleStartTEST는 인스턴스가 시작되었을 경우에 시작상태로 표시된다.
후에 서비스를 중지하기 위해 제어판-서비스에서 멈춤을 선택하지는 말라.
이는 shutdown abort와 같은 종료를 한다. 
이는 나중에 인스턴스 시작시 매번 SMON이 자동복구를 하게 한다.
(이를 막는 방법은 레지스트리키의 ora_shutdown이나 ora_sid_shutdown을 true를 설정
하면 된다. 이는 shutdown immediate와 같다. 레지스트리키의 위치는 
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE에서 발견할 수 있다.이는 오라클8이상에서만 가능하다.)




위에서 패스워드는 manager로 지정한 것을 유의하라.
이는 서버매니저로 로긴시 사용될 것이다. 
(OracleStarttest만 정의되어 있지 않을 경우, 'oradim80 -delete -sid test'를 먼저 실행한다.)
이제 oracle_sid를 test로 지정하고 서버매니저를 실행한다.

C:\>set Oracle_Sid=test

C:\>svrmgr30

Oracle Server Manager Release 3.0.5.0.0 - Production

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

Oracle8 Enterprise Edition Release 8.0.5.0.0 - Production
With the Partitioning and Objects options
PL/SQL Release 8.0.5.0.0 - Production

SVRMGR> connect internal/manager
연결되었습니다
SVRMGR> startup nomount
ORACLE 인스턴스가 시작되었습니다
시스템 글로벌 영역 4542464 바이트 합계
Fixed Size 49152 바이트
Variable Size 4214784 바이트
Database Buffers 204800 바이트
Redo Buffers 73728 바이트
SVRMGR> show sga
시스템 글로벌 영역 4542464 바이트 합계
Fixed Size 49152 바이트
Variable Size 4214784 바이트
Database Buffers 204800 바이트
Redo Buffers 73728 바이트
SVRMGR> show parameters db_name
NAME TYPE VALUE
----------------------------------- ------- ------------------------------
db_name string test

DB이름이 test인 것을 확인한다.

참고:
show sga명령은 SGA영역의 크기를 확인할 수 있다. 이는 인스턴스시작시
출력되는 내용과 동일하다.
show parameters는 initSID.ora파일에 지정된 패러미터를 출력한다.
패러미터파일에 지정되지 않은 값은 디폴트 값을 가진다. 
뒤에 패러미터이름을 지정하면 해당 패러미터만 검색가능하다. 
확실한 패러미터이름을 모른다면 이름의 일부분만을 입력하라.
부분검색이 가능하다. 즉, show parameters db라고 입력하면 db라는 단어를
포함한 패러미터들의 값이 모두 출력된다.


이제 DB생성만 하면 된다.
이는 유닉스에서와 별다를 것이 없다.
(DB생성은 c:\orant\RDBMS80\ADMIN\CREATEDB.SQL파일을 참고하라.)
나는 위의 파일과 다르게 진행했다.
일단 데이터가 저장될 폴더(e:\ora_data\database\test)를 만들어 준다.

SVRMGR> create database test
2> maxinstances 8
3> maxlogfiles 32
4> character set "KO16KSC5601"
5> national character set "KO16KSC5601"
6> datafile
7> 'e:\ora_data\database\test\system01.dbf' size 50m
8> logfile
9> 'e:\ora_data\database\test\redotest01.log' size 500k,
10> 'e:\ora_data\database\test\redotest02.log' size 500k,
11> 'e:\ora_data\database\test\redotest03.log' size 500k;
명령문이 처리되었습니다

데이터베이스 생성 SQL문이다.
여기서는 데이터파일과 redo log파일을 생성한다. 컨트롤파일도 이때 생성된다.
컨트롤파일은 따로 지정하지 않으면 패러미터파일(initSID.ora)에서 지정한 
파일이름을 가지고 생성된다. 위의 예에서는 리두로그를 그룹으로 만들지 않았다.
여러분이 생성할때는 리두로그그룹을 생성하기를 바란다. 별로 어렵지 않을 것이다.

위의 결과, 다음과 같은 파일이 생겼음을 확인할 수 있다.




시스템(system01.dbf)에 데이터사전뷰을 만든다

SVRMGR> @c:\orant\rdbms80/admin/catalog.sql
결과화면 생략...

이후로는 설명은 생략한다. 
자세한 설명은 리눅스에서의 DB생성(createdb.html)을 참고하라.
NT에서 서비스의 시작/종료는 net명령(nt_netcommand.html)을 참고한다.

SVRMGR> show parameters rollback_segments
NAME TYPE VALUE
----------------------------------- ------- ------------------------------
max_rollback_segments integer 30
rollback_segments string e:\ora_data\database\test\r01,
SVRMGR> create rollback segment r0 tablespace system
2> storage(initial 16k next 16k minextents 2 maxextents 20);
명령문이 처리되었습니다
SVRMGR> alter rollback segment r0 online;
명령문이 처리되었습니다
SVRMGR> create tablespace rbs datafile
2> 'e:\ora_data\database\test\rbs01.dbf' size 15m
3> default storage(
4> initial 128k
5> next 128k
6> pctincrease 0
7> minextents 2);
명령문이 처리되었습니다
SVRMGR> create tablespace temp datafile
2> 'e:\ora_data\database\test\temp01.dbf' size 1m
3> default storage(
4> initial 256k
5> next 256k
6> pctincrease 0);
명령문이 처리되었습니다
SVRMGR> create tablespace tools datafile
2> 'e:\ora_data\database\test\tools01.dbf' size 25m;
명령문이 처리되었습니다
SVRMGR> create tablespace users datafile
2> 'e:\ora_data\database\test\users01.dbf' size 1m;
명령문이 처리되었습니다
SVRMGR> create rollback segment r01 tablespace rbs;
명령문이 처리되었습니다
SVRMGR> create rollback segment r02 tablespace rbs;
명령문이 처리되었습니다
SVRMGR> alter rollback segment r01 online;
명령문이 처리되었습니다
SVRMGR> alter rollback segment r0 offline;
명령문이 처리되었습니다
SVRMGR> drop rollback segment r0;
명령문이 처리되었습니다
SVRMGR> alter user sys temporary tablespace temp;
명령문이 처리되었습니다
SVRMGR> alter user system default tablespace tools temporary tablespace temp;
명령문이 처리되었습니다
SVRMGR> @c:/orant/rdbms80/admin/catproc.sql
결과화명생략..
아래는 이제까지 생성된 데이터파일을 보여준다.

DBMS_REPAIR패키지 사용하기

더보기

DBMS_REPAIR패키지 사용하기

작성자: 강명규
OS: Linux 2.4.18
Oralce: Oracle EE 8.1.7

DBMS_REPAIR패키지에는 테이블과 인덱스내의 망가진 블럭(corrupt block --;)을 찾아서 수정해주는
data corruption repair 프로시저를 가지고 있다. 약간 low level적인 작업이므로 DBA만을 위한
패키지이므로 일반사용자라면 이 글을 볼 필요없겠다. 따라서 sys계정으로 작업하게 된다.
그리고 이 패키지는 8i이상에서만 사용할 수 있으므로 하위버전이라면 역시 이 글을 볼 필요없겠다.


db_block_checksum과 db_block_checking

db_block_checksum
체크섬(checksum)이라는 것은 블럭내에 저장된 총 바이트(bytes)를 계산한 값이다.
db_block_checksum패러미터는 DBWn, direct loader가 체크섬을 계산할 것인지 결정한다.
true로 설정하면, 디스크에 write시 모든 데이터블럭의 cache헤더에 체크섬을 저장한다.
checksum은 블럭을 read할때 검증되어진다.
false로 설정하면, system테이블스페이브에 대해서만 DBWn가 체크섬을 계산한다.

db_block_checking
true로 설정시, 모든 데이터블럭에 대한 블럭체킹을 실시한다.
false로 설정시, system테이블스페이스를 제외한 모든 데이터블럭의 블럭체킹을 하지 않는다.
오라클은 블럭내의 데이터를 읽을때(walking through), consistent한지 파악함으로써 블럭을 체크하게된다.

위 둘의 차이점은 체크섬을 저장하느냐 여부로 따라 판단하는 것이 편할 것이다.

db_block_checking을 패러미터파일에 true로 설정한다.
[oracle@ns bdump]$ cat $ORACLE_HOME/dbs/initdb.ora|grep db_block_checking
db_block_checking=true

[oracle@ns bdump]$ svrmgrl

Oracle Server Manager Release 3.1.7.0.0 - Production

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

Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SVRMGR> connect internal
Connected.
SVRMGR> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SVRMGR> startup
ORACLE instance started.
Total System Global Area                         13947040 bytes
Fixed Size                                          73888 bytes
Variable Size                                     5312512 bytes
Database Buffers                                  8388608 bytes
Redo Buffers                                       172032 bytes
Database mounted.
Database opened.
SVRMGR> @?/rdbms/admin/dbmsrpr.sql -- dbms_repair 패키지 spec생성
Statement processed.
SVRMGR> @?/rdbms/admin/prvtrpr.plb -- dbms_repair 패키지 body생성
Statement processed.
Statement processed.
SVRMGR> quit
Server Manager complete.


손상된 data block을 만들기 위한 사전작업

dbms_repair패키지를 사용하기 위한 테스트로 corrupt block을 만들어야 한다.

SQL> conn system/xxxxxx
Connected.
SQL> create tablespace ts_corrupt_test
  2  datafile '/u01/app/oracle/oradata/db/ts_corrupt_test01.dbf' size 500k;

Tablespace created.

SQL> conn kang/xxxxxx
Connected.
SQL> create table test tablespace ts_corrupt_test
  2  as
  3  select table_name, owner, table_type from all_catalog;

Table created.

primary key생성을 위한 중복행 제거
SQL> delete from test a where a.rowid < (select max(rowid) from test b where b.table_name= a.table_name);

302 rows deleted.

SQL> alter table test
  2  add constraint test_pk primary key(table_name)
  3  using index tablespace ts_corrupt_test;

Table altered.

SQL> commit;

Commit complete.

SQL> select count(1) from test;

  COUNT(1)
----------
      1232

test라는 테이블이 존재하는 데이터파일에 block corruption이 발생하게 만든다.
db shutdown후 데이터파일을 hexa editor로 자~알 건들여서 startup하면
오라클이 에러를 뱉는다. 이땐 그냥 recover database하면 대개 open할 수 있다.
그럼 corruption block이발생한다. 다시 말하지만, 자~알 건드려야 corruption block이 발생한다.
나름대로 노하우를 가지고 있어야 할 것이다.

SVRMGR> startup
ORACLE instance started.
Total System Global Area                         13947040 bytes
Fixed Size                                          73888 bytes
Variable Size                                     5312512 bytes
Database Buffers                                  8388608 bytes
Redo Buffers                                       172032 bytes
Database mounted.
ORA-01113: file 7 needs media recovery
ORA-01110: data file 7: '/u01/app/oracle/oradata/db/ts_corrupt_test01.dbf'
SVRMGR> recover database;
Media recovery complete.
SVRMGR> alter database open;
Statement processed.
SVRMGR> quit


이제 test테이블을 조회해보면 table scan시 다음과 같은 에러가 남을 볼 수 있다.

SQL> conn kang/xxxxxx
Connected.
SQL> analyze table test validate structure;
analyze table test validate structure
*
ERROR at line 1:
ORA-01498: block check failure - see trace file


SQL>
제대로 block corruption이 발생하게끔 만들었음을 알 수 있다.
이제 dbms_repair패키지를 사용하여 이를 어떻게 처리할지 보겠다.


손상된 data block에 대한 정보를 보관할 테이블,뷰 생성
block corruption이 발생한 곳의 레코드는 조회할 수 없다.
블럭손상에 대한 결과를 저장하기 위한 테이블,뷰을 생성한다.
admin_tables라는 프로시저는 4개의 인수를 갖고 각각의 인수는 다음과 같다.
테이블명(table_name)
테이블타입(table_type)  : ORPHAN_TABLE, REPAIR_TABLE
하고자하는 작업(action) : CREATE_ACTION, PURGE_ACTION, DROP_ACTION
테이블이 생성될 테이블스페이스명(tablespace)

SQL> conn sys/xxxxxx
Connected.
SQL> exec dbms_repair.admin_tables('REPAIR_TABLE',DBMS_REPAIR.REPAIR_TABLE,DBMS_REPAIR.CREATE_ACTION,'USERS');

PL/SQL procedure successfully completed.

위와 같이 해주면 다음과 같이 repair_table 테이블과 dba_repair_table 이라는 뷰가 생성된다.

SQL> select * from tab where tname like '%REPAIR%';

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
DBA_REPAIR_TABLE               VIEW
REPAIR_TABLE                   TABLE

이 놈은 corrupt된 블럭을 가진 테이블의 인덱스를 위한 테이블을 생성한다.
SQL> exec dbms_repair.admin_tables('ORPHAN_KEY_TABLE', DBMS_REPAIR.ORPHAN_TABLE,DBMS_REPAIR.CREATE_ACTION,'USERS');

PL/SQL procedure successfully completed.

SQL> select * from tab where tname like '%ORPHAN%';

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
DBA_ORPHAN_KEY_TABLE           VIEW
ORPHAN_KEY_TABLE               TABLE

SQL>

위에서 보듯이 지정된 테이블이 생성되고, DBA_[지정된 테이블명]으로 된 뷰가 생성된다.
이제 손상된 정보를 저장하기 위한 테이블을 생성했으니 CHECK_OBJECT프로시저를 사용하여
REPAIR테이블에 손상정보를 파악하여 입력되도록 하겠다. 이 프로시저에 대한 인수는 다음과 같다.

schema_name        : 객체를 소유한 스키마
object_name        : 체크할 테이블이나 인덱스
partition_name     : 파티셔닝된 경우에만 해당 파티션을 지정하고 아니면 생략할 것.
object_type        : TABLE_OBJECT, INDEX_OBJECT
repair_table_name  : admin_tables프로시저에서 지정했던 테이블명(repair_table)
flags              : 사용되지 않음
relative_fno       : 블럭범위(block range)지정시 relative file number. 몰라도 되겠다.
block_start        : 블럭범위지정했을 경우, 첫번째 블럭
block_end          : 블럭범위지정했을 경우, 마지막 블럭
corrupt_count      : 설명없어도 알 수 있겠지.. 이것은 out변수이므로 입력이 아니라 출력받는 값이다.

SQL> set serveroutput on
SQL> var num number
SQL> exec dbms_repair.check_object('KANG','TEST',repair_table_name=>'REPAIR_TABLE',corrupt_count=>:corrupt_count);

PL/SQL procedure successfully completed.

SQL> print corrupt_count

CORRUPT_COUNT
-------------
            1

SQL> col corrupt_description format a40
SQL> col repair_description format a40 
SQL> set linesize 1000
SQL> select RELATIVE_FILE_ID, BLOCK_ID, CORRUPT_DESCRIPTION, REPAIR_DESCRIPTION, MARKED_CORRUPT from repair_table;

RELATIVE_FILE_ID   BLOCK_ID CORRUPT_DESCRIPTION                      REPAIR_DESCRIPTION                       MARKED_COR
---------------- ---------- ---------------------------------------- ---------------------------------------- ----------
               7          5 Block Checking: DBA = 29360133, Block Ty mark block software corrupt              FALSE
                            pe = KTB-managed data block
                            kdbchk: there are free slots not on the
                            free list
                                    nfree=35


SQL>

위에서 보듯이, 파일7, 블럭5에 corruption이 발생했음을 알 수 있다.
위에서 marked_corrupt컬럼이 FALSE값을 가지고 있으므로, TRUE로 변경하여 corruption을 mark하도록 변경한다.

fix_corrupt_blocks프로시저는 check_object프로시저에 의해 생성된 repair테이블의 데이터를 참조하여,
지정된 objects가 가진 corrupt block을 표시한다.(fix).
이 프로시저는 다음과 같은 인수를 갖는다.

schema_name       :
object_name       : fix할 블럭을 가진 object
partition_name    :
object_type       : TABLE_OBJECT or INDEX_OBJECT
repair_table_name : REPAIR_TABLE
flags             : 사용되지 않음
fix_count         : fix된 블럭수

SQL> var fix_count number
SQL> exec dbms_repair.fix_corrupt_blocks('KANG','TEST',object_type=>dbms_repair.table_object,repair_table_name=>'REPAIR_TABLE', fix_count=> :fix_count);

PL/SQL procedure successfully completed.

SQL> print fix_count

 FIX_COUNT
----------
         1

SQL> select * from kang.test;

TABLE_NAME                     OWNER                          TABLE_TYPE
------------------------------ ------------------------------ -----------
DUAL                           PUBLIC                         SYNONYM
..
DBA_SNAPSHOT_REFRESH_TIMES     PUBLIC                         SYNONYM
ALL_SNAPSHOT_REFRESH_TIMES     PUBLIC                         SYNONYM
ERROR:
ORA-01578: ORACLE data block corrupted (file # 7, block # 5)
ORA-01110: data file 7: '/u01/app/oracle/oradata/db/ts_corrupt_test01.dbf'



150 rows selected.

SQL>


table scan시 에러가 발생하고 있다.
fix_corrupt_blocks프로시저가 표시해 놓은 corrupt_blocks을 skip_corrupt_blocks프로시저에 의해 skip처리해야 한다.
이 프로시저는 지정한 객체에 대한 table scan이나 index scan시 corrupt block의 skip할 것인가 안할 것인가를 지정한다.


SQL> exec dbms_repair.skip_corrupt_blocks('KANG','TEST',dbms_repair.table_object,dbms_repair.skip_flag);

PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> select * from kang.test;

TABLE_NAME                     OWNER                          TABLE_TYPE
------------------------------ ------------------------------ -----------
DUAL                           PUBLIC                         SYNONYM
..
CHAINED_ROWS                   KANG                           TABLE
EXCEPTIONS                     KANG                           TABLE

1141 rows selected.


아래에서 보듯이 marked_corrupt컬럼이 true로 변경되었음을 알 수 있다.
SQL> select RELATIVE_FILE_ID, BLOCK_ID, MARKED_CORRUPT from repair_table;

RELATIVE_FILE_ID   BLOCK_ID MARKED_COR
---------------- ---------- ----------
               7          5 TRUE

SQL>

dump_orphan_keys프로시저는 인덱스와 관련된 프로시저이다.
dump_orphan_keys프로시저로 corrupt data block내의 row를 가리키고 있는 인덱스엔트리를 알수있다.

SQL> var key_count number 
SQL> begin
  2  dbms_repair.dump_orphan_keys(
  3  schema_name=>'KANG',
  4  object_name=>'TEST_PK',
  5  object_type=>DBMS_REPAIR.INDEX_OBJECT,
  6  repair_table_name=>'REPAIR_TABLE',
  7  orphan_table_name=>'ORPHAN_KEY_TABLE',
  8  key_count=>:key_count);
  9  end;
 10  /


SQL> print key_count

 KEY_COUNT
----------
        91

SQL> select SCHEMA_NAME, INDEX_NAME, INDEX_ID, TABLE_NAME, KEYROWID from orphan_key_table;

SCHEMA_NAME                    INDEX_NAME                       INDEX_ID TABLE_NAME                     KEYROWID
------------------------------ ------------------------------ ---------- ------------------------------ ----------------------------------------
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABBAA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABBcA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABC4A
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABDIA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABAEA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABAYA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABAsA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABCcA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABA4A
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABC8A
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABDMA
...
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABGgA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABGYA
KANG                           TEST_PK                              3927 TEST                           AAAA9WAAUAAAMABFwA

91 rows selected.

91개의 orphan key가 발견되었으므로 인덱스를 rebuild해준다.
SQL> alter index kang.test_pk rebuild online;

Index altered.


rebuild_freelists는 지정된 object에 대한 freelists를 재생성한다.
인수는 다음과 같다.

schema_name
object_name
partition_name
object_type

SQL> exec dbms_repair.rebuild_freelists('KANG','TEST',object_type=>dbms_repair.table_object);

PL/SQL 처리가 정상적으로 완료되었습니다.

참고문서:Oracle Technical Bulletin No. 11941

롤백세그먼트와 트랜잭션

더보기

롤백세그먼트와 트랜잭션

작성일: 2002-07-31 
작성자: 강명규
OS: Linux 2.4.18
Oralce: Oracle EE 8.1.7

[system]
SQL> connect system/xxxxxx@dbakorea
SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;

SEGMENT_NAME                   OWNER  TABLESPACE_NAME                STATUS
------------------------------ ------ ------------------------------ ----------------
SYSTEM                         SYS    SYSTEM                         ONLINE
RBS0                           PUBLIC RBS                            ONLINE
RBS1                           PUBLIC RBS                            ONLINE
RBS2                           PUBLIC RBS                            ONLINE
RBS3                           PUBLIC RBS                            ONLINE
RBS4                           PUBLIC RBS                            ONLINE
RBS5                           PUBLIC RBS                            ONLINE
RBS6                           PUBLIC RBS                            ONLINE

8 개의 행이 선택되었습니다.

SQL> create rollback segment rbs7
  2  tablespace rbs storage( optimal 5000k);

롤백 세그멘트가 생성되었습니다.

SQL> alter rollback segment rbs7 online;

롤백 세그멘트가 변경되었습니다.

SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;

SEGMENT_NAME                   OWNER  TABLESPACE_NAME                STATUS
------------------------------ ------ ------------------------------ ----------------
SYSTEM                         SYS    SYSTEM                         ONLINE
RBS0                           PUBLIC RBS                            ONLINE
RBS1                           PUBLIC RBS                            ONLINE
RBS2                           PUBLIC RBS                            ONLINE
RBS3                           PUBLIC RBS                            ONLINE
RBS4                           PUBLIC RBS                            ONLINE
RBS5                           PUBLIC RBS                            ONLINE
RBS6                           PUBLIC RBS                            ONLINE
RBS7                           SYS    RBS                            ONLINE

9 개의 행이 선택되었습니다.

SQL> select n.name, s.status, xacts 
  2  from v$rollname n, v$rollstat s
  3  where n.usn = s.usn;

NAME                           STATUS               XACTS
------------------------------ --------------- ----------
SYSTEM                         ONLINE                   0
RBS0                           ONLINE                   0
RBS1                           ONLINE                   0
RBS2                           ONLINE                   0
RBS3                           ONLINE                   0
RBS4                           ONLINE                   0
RBS5                           ONLINE                   0
RBS6                           ONLINE                   0
RBS7                           ONLINE                   0

9 개의 행이 선택되었습니다.






[kang]
테스트를 위해 kang유저로 또 하나의 SQL*PLUS창을 연다.
SQL> conn kang/xxxxxx@dbakorea
연결되었습니다.
SQL> set transaction use rollback segment rbs7;

트랜잭션이 설정되었습니다.

SQL> select * from test;

ID         PASSWD
---------- ----------
maddog     yyyy

SQL> update test set passwd='mmmm';

1 행이 갱신되었습니다.




[system]
여기까지 하면 rbs7 롤백세그먼트가 active 트랜잭션을 가지고 있다.

SQL> select n.name, s.status, xacts 
  2  from v$rollname n, v$rollstat s
  3  where n.usn = s.usn;

NAME                           STATUS               XACTS
------------------------------ --------------- ----------
SYSTEM                         ONLINE                   0
RBS0                           ONLINE                   0
RBS1                           ONLINE                   0
RBS2                           ONLINE                   0
RBS3                           ONLINE                   0
RBS4                           ONLINE                   0
RBS5                           ONLINE                   0
RBS6                           ONLINE                   0
RBS7                           ONLINE                   1

9 개의 행이 선택되었습니다.


롤백세그먼트 rbs7에 1개의 트랜잭션이 활성화되어 있음을 알 수 있다.
물론, 이것은 kang이라는 사용자의 update문에 걸려있는 것이다. 
아직 kang은 commit이나 rollback을 한 상황이 아니다. rbs7을 offline으로 변경하자.

SQL> alter rollback segment rbs7 offline;

롤백 세그멘트가 변경되었습니다.

SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;

SEGMENT_NAME                   OWNER  TABLESPACE_NAME                STATUS
------------------------------ ------ ------------------------------ ----------------
SYSTEM                         SYS    SYSTEM                         ONLINE
RBS0                           PUBLIC RBS                            ONLINE
RBS1                           PUBLIC RBS                            ONLINE
RBS2                           PUBLIC RBS                            ONLINE
RBS3                           PUBLIC RBS                            ONLINE
RBS4                           PUBLIC RBS                            ONLINE
RBS5                           PUBLIC RBS                            ONLINE
RBS6                           PUBLIC RBS                            ONLINE
RBS7                           SYS    RBS                            ONLINE

9 개의 행이 선택되었습니다.

트랜잭션을 가진 rbs7에 대한 offline이 막힘없이 된다. 어떻게 .. active transaction이 있는
롤백세그먼트가 offline이 성공하는가? 아.. 놀라워라. 그런데 dba_rollback_segs에 질의하니
online 상태라고 표시된다. 음.. 속았다. 그렇다. offline은 실제 pending중이다. 이것은
다음과 같이 v$rollstat에 질의해보면 알 수 있다.

SQL> select n.name, s.status, xacts 
  2  from v$rollname n, v$rollstat s
  3  where n.usn = s.usn;

NAME                           STATUS               XACTS
------------------------------ --------------- ----------
SYSTEM                         ONLINE                   0
RBS0                           ONLINE                   0
RBS1                           ONLINE                   0
RBS2                           ONLINE                   0
RBS3                           ONLINE                   0
RBS4                           ONLINE                   0
RBS5                           ONLINE                   0
RBS6                           ONLINE                   0
RBS7                           PENDING OFFLINE          1

9 개의 행이 선택되었습니다.


이와 같이 peding offline상태에서는 더 이상의 추가적인 트랜잭션을 받아들이지 않는다.
즉, kang의 update문이 commit or rollback되기만을 기다리고 있다.
어느 시점에 kang이 트랜잭션을 종료하다면(commit or rollback), rbs7은 이 때 실질적인 offline상태로 변한다.







[kang]
SQL> commit;

커밋이 완료되었습니다.

SQL> select * from test;

ID         PASSWD
---------- ----------
maddog     mmmm


이제 트랜잭션을 종료했다. 어떻게 되나 보자.

[system]

SQL> select segment_name,owner,tablespace_name,status from dba_rollback_segs;

SEGMENT_NAME                   OWNER  TABLESPACE_NAME                STATUS
------------------------------ ------ ------------------------------ ----------------
SYSTEM                         SYS    SYSTEM                         ONLINE
RBS0                           PUBLIC RBS                            ONLINE
RBS1                           PUBLIC RBS                            ONLINE
RBS2                           PUBLIC RBS                            ONLINE
RBS3                           PUBLIC RBS                            ONLINE
RBS4                           PUBLIC RBS                            ONLINE
RBS5                           PUBLIC RBS                            ONLINE
RBS6                           PUBLIC RBS                            ONLINE
RBS7                           SYS    RBS                            OFFLINE

9 개의 행이 선택되었습니다.

SQL> select n.name, s.status, xacts 
  2  from v$rollname n, v$rollstat s
  3  where n.usn = s.usn;           

NAME                           STATUS               XACTS
------------------------------ --------------- ----------
SYSTEM                         ONLINE                   0
RBS0                           ONLINE                   0
RBS1                           ONLINE                   0
RBS2                           ONLINE                   0
RBS3                           ONLINE                   0
RBS4                           ONLINE                   0
RBS5                           ONLINE                   0
RBS6                           ONLINE                   0

8 개의 행이 선택되었습니다.






dba_rollback_segs에는 offline으로 변경되었고, v$rollstat에는 rbs7항목이 사라졌음을 알 수 있다.
실제, 위의 내용은 시간이 좀 지나서 변경된다. 
빠른 결과를 보고 싶다면, alter rollback segment rbs7 offline을 한 번 더 수행주면 되겠다.
kang이 rbs7을 사용하라고 지정해두었는데 이제 rbs7가 offline이 되었으니 더이상 kang의 트랜잭션은
rbs7을 사용하지 못한다. 그럼 트랜잭션을 사용하면 어떻게 될까? 아래에서 보듯이 임의로 지정된(?) 
rbs0가 트랜잭션에 사용됨을 알 수 있다.

[kang]

SQL> update test set passwd='nnnn';

1 행이 갱신되었습니다.


[system]

SQL> select n.name, s.status, xacts  
  2  from v$rollname n, v$rollstat s 
  3  where n.usn = s.usn;            

NAME                           STATUS               XACTS
------------------------------ --------------- ----------
SYSTEM                         ONLINE                   0
RBS0                           ONLINE                   1
RBS1                           ONLINE                   0
RBS2                           ONLINE                   0
RBS3                           ONLINE                   0
RBS4                           ONLINE                   0
RBS5                           ONLINE                   0
RBS6                           ONLINE                   0

8 개의 행이 선택되었습니다.


자신이 사용하고 있는 ROLLBACK SEGMENT파악
SQL> SELECT r.name "RBS", s.sid, s.serial#, s.username "USER", t.status,
  2         t.cr_get, t.phy_io, t.used_ublk, t.noundo,
  3         substr(s.program, 1, 78) "COMMAND"
  4  FROM   sys.v_$session s, sys.v_$transaction t, sys.v_$rollname r
  5  WHERE  t.addr = s.taddr
  6    and  t.xidusn = r.usn
  7  ORDER  BY t.cr_get, t.phy_io;

RBS     SID    SERIAL# USER       STATUS     CR_GET     PHY_IO  USED_UBLK NOU COMMAND
----- ----- ---------- ---------- ------ ---------- ---------- ---------- --- ----------------------
RBS0      9         59 KANG       ACTIVE          1          0          1 NO  SQLPLUSW.EXE

SQL> select c.segment_name, e.sid, e.username,
  2         b.object_name, b.object_type,
  3         d.used_urec, a.os_user_name,
  4         d.xidusn, d.start_time,
  5         e.process, e.program, e.status
  6   from v$locked_object a,
  7        dba_objects b,
  8        dba_rollback_segs c,
  9        v$transaction d,
 10        v$session e
 11  where a.object_id = b.object_id
 12    and a.xidusn = c.segment_id
 13    and a.xidusn = d.xidusn
 14    and a.xidslot = d.xidslot
 15    and d.addr = e.taddr;

SEGMENT_NAME   SID USERNAME OBJECT_NAME OBJEC  USED_UREC OS_USER_NAME        XIDUSN START_TIME           PROCE
------------ ----- -------- ----------- ----- ---------- --------------- ---------- ----------------
RBS0             9 KANG     TEST        TABLE          1 Administrator            1 08/04/02 21:58:03    1132:356  SQLPLUSW.EXE 

SQL>

List Partitioning

더보기

List Partitioning

range파티셔닝은 지정한 범위에 있는 값만 해당 파티션에 할당할 수 있고,
hash파티셔닝은 어느 파티션에 row를 할당할지 사용자가 컨트롤할 수 없다

list파티셔닝은 row를 지정된 파티션에 명시적으로 할당하는 것이 가능하고,
관련이 없는 데이터집합에 대해서 자연스럽게 그룹화와 조직화가 가능하다.

list파티셔닝은 multi컬럼 파티셔닝을 지원하지 않는다.
즉, 파티셔닝키는 단지 하나의 컬럼으로만 구성될 수 있다.
(range, hash에서는 가능하다.)

* 필자의 생각
아직도 파티셔닝키에 어떠한 조작을 못하는게 아쉽다.
예를 들어, substring한 컬럼값 선두 몇자리만 비교하여 
해당 파티션에 할당할 수 없다.
list파티셔닝은 다른 파티션에 비해 제약이 많은것 같다.

CREATE TABLE sales_by_region
(
    deptno number,
    deptname varchar2(20),
    quarterly_sales number(10, 2),
    state varchar2(2)
)
PARTITION BY LIST (state)
(
    PARTITION q1_northwest VALUES ('OR', 'WA'),
    PARTITION q1_southwest VALUES ('AZ', 'UT', 'NM'),
    PARTITION q1_northeast VALUES ('NY', 'VM', 'NJ'),
    PARTITION q1_southeast VALUES ('FL', 'GA'),
    PARTITION q1_northcentral VALUES ('SD', 'WI'),
    PARTITION q1_southcentral VALUES ('OK', 'TX')
);

(10, 'accounting', 100, 'WA')         q1_northwest파티션에 매핑
(20, 'R&D', 150, 'OR')                q1_northwest파티션에 매핑
(30, 'sales', 100, 'FL')              q1_southeast파티션에 매핑
(40, 'HR', 10, 'TX')                  q1_southwest파티션에 매핑
(50, 'systems engineering', 10, 'CA') 어느 파티션에도 매핑되지 않음




CREATE TABLE sales_by_region 
(
    item# INTEGER, 
    qty INTEGER,
    store_name VARCHAR(30), 
    state_code VARCHAR(2),
    sale_date DATE
)
STORAGE(INITIAL 10K NEXT 20K) TABLESPACE tbs5
PARTITION BY LIST (state_code)
(
    PARTITION region_east VALUES ('MA','NY','CT','NH','ME','MD','VA','PA','NJ') STORAGE (INITIAL 20K NEXT 40K PCTINCREASE 50) TABLESPACE tbs8,
    PARTITION region_west VALUES ('CA','AZ','NM','OR','WA','UT','NV','CO')      PCTFREE 25 NOLOGGING,
    PARTITION region_south VALUES ('TX','KY','TN','LA','MS','AR','AL','GA'),
    PARTITION region_central VALUES ('OH','ND','SD','MO','IL','MI', null, 'IA')
);



실제 테이블생성해보자.

작성일: 2001-11-16
Oracle 9i EE(9.0.1.0.1)
Windows 2000 Advanced Server
Petium III 1Gz, 512MB


SQL> connect system/xxxxx
연결되었습니다.

-- 4개의 테이블스페이스를 생성
SQL> create tablespace ts_kyungsang
  2  datafile 'd:\ts_kyungsang01.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> create tablespace ts_junna
  2  datafile 'd:\ts_junna01.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> create tablespace ts_choongchung
  2  datafile 'e:\ts_choongchung01.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> create tablespace ts_kyungki
  2  datafile 'e:\ts_kyungki01.dbf' size 10m;

테이블 영역이 생성되었습니다.

SQL> connect kang/xxxxxx
연결되었습니다.

SQL> CREATE TABLE member
  2  (
  3      id          varchar(15),
  4      name        varchar(20),
  5      birth       date,
  6      cellular    varchar(13),
  7      mail        varchar(50),
  8      city        varchar(10)
  9  ) storage( initial 5m next 1m pctincrease 0 ) tablespace users
 10  partition by list(city)
 11  (
 12      partition kyung_sang_do     values ('ULSAN', 'BUSAN', 'DAEGU') tablespace ts_kyungsang,
 13      partition kyung_ki_do       values ('SEOUL', 'INCHUN', 'KOYANG', 'SUNGNAM') tablespace ts_kyungki,
 14      partition choong_chung_do   values ('DAEJUN') tablespace ts_choongchung,
 15      partition jun_na_do         values ('GWANGJU') tablespace ts_junna
 16  );

테이블이 생성되었습니다.

SQL> insert into member values
  2  ('maddog', '강명규', to_date('19740509', 'YYYYMMDD'), '011830xxxx', 'kang@dbakorea.pe.kr', 'ULSAN');

1 개의 행이 만들어졌습니다.

SQL> insert into member values                                                                           
  2  ('maddog1', '아무개1', to_date('19740510', 'YYYYMMDD'), '011830xxx1', 'kang1@dbakorea.pe.kr', 'SEOUL');

1 개의 행이 만들어졌습니다.

SQL> insert into member values                                                                           
  2  ('maddog2', '아무개2', to_date('19740511', 'YYYYMMDD'), '011830xxx2', 'kang2@dbakorea.pe.kr', 'DAEJUN');

1 개의 행이 만들어졌습니다.

SQL> insert into member values                                                                           
  2  ('maddog3', '아무개3', to_date('19740512', 'YYYYMMDD'), '011830xxx3', 'kang3@dbakorea.pe.kr', 'GWANGJU');

1 개의 행이 만들어졌습니다.

-- 파티션키에 매칭되는 데이터가 아니면 에러 발생함
SQL> insert into member values                                                                              
  2  ('maddog4', '아무개4', to_date('19740513', 'YYYYMMDD'), '011830xxx4', 'kang4@dbakorea.pe.kr', 'NEWYORK');
insert into member values
            *
1행에 오류:
ORA-14400: 삽입된 분할 영역 키와 매핑되는 분할 영역이 없음


SQL> connect system/xxxxxx
연결되었습니다.

SQL> col id format a10
SQL> col name format a10
SQL> col mail format a20
SQL> select * from kang.member;

ID         NAME       BIRTH    CELLULAR      MAIL                 CITY
---------- ---------- -------- ------------- -------------------- ----------
maddog     강명규     74/05/09 011830xxxx    kang@dbakorea.pe.kr  ULSAN
maddog1    아무개1    74/05/10 011830xxx1    kang1@dbakorea.pe.kr SEOUL
maddog2    아무개2    74/05/11 011830xxx2    kang2@dbakorea.pe.kr DAEJUN
maddog3    아무개3    74/05/12 011830xxx3    kang3@dbakorea.pe.kr GWANGJU

SQL> alter tablespace ts_kyungki offline;

테이블 영역이 변경되었습니다.

SQL> select * from kang.member;
ERROR:
ORA-00376: 현재 파일 12를 읽을 수 없습니다
ORA-01110: 12 데이터 파일: 'E:\TS_KYUNGKI01.DBF'

-- 해당파티션에 존재하지 않는 데이터들은 select 가능하다.
SQL> select * from kang.member where city in('ULSAN','DAEJUN','GWANGJU');

ID         NAME       BIRTH    CELLULAR      MAIL                 CITY
---------- ---------- -------- ------------- -------------------- ----------
maddog     강명규     74/05/09 011830xxxx    kang@dbakorea.pe.kr  ULSAN
maddog2    아무개2    74/05/11 011830xxx2    kang2@dbakorea.pe.kr DAEJUN
maddog3    아무개3    74/05/12 011830xxx3    kang3@dbakorea.pe.kr GWANGJU

SQL> select * from kang.member where city ='ULSAN';

ID         NAME       BIRTH    CELLULAR      MAIL                 CITY
---------- ---------- -------- ------------- -------------------- ----------
maddog     강명규     74/05/09 011830xxxx    kang@dbakorea.pe.kr  ULSAN


SQL> alter tablespace ts_kyungki online;

테이블 영역이 변경되었습니다.


-- 연습을 위해 생성된 것들을 삭제
SQL> connect kang/xxxxxx
연결되었습니다.
SQL> drop table member;

테이블이 삭제되었습니다.

SQL> connect system/xxxxxx
연결되었습니다.
SQL> drop tablespace ts_kyungki;

테이블 영역이 삭제되었습니다.

SQL> drop tablespace ts_kyungsang;

테이블 영역이 삭제되었습니다.

SQL> drop tablespace ts_junna;

테이블 영역이 삭제되었습니다.

SQL> drop tablespace ts_choongchung;

테이블 영역이 삭제되었습니다.


오라클이 테이블스페이스에 할당된 데이터 파일들을 지워주지 않으므로
OS상에서 해당 데이터파일들을 삭제한다.

tablespace coalesce

더보기

tablespace coalesce

작성자: 강명규
OS: Linux 2.4.10
Oralce: Oracle EE 8.1.7

db_block_size: 8kbytes



extent가 할당/해제되다 보면 테이블스페이스내 free한 extent가 연속적이지 못하게 된다.
이런 것들을 coalesce(합병)해주면 I/O를 줄일 수 있고, 시간또한 절약될 것이다.
보통 coalsce는 백그라운드 프로세스인 SMON(System Monitor)가 자동으로 실행한다.
DBA는 수동으로 'alter tablespace AAA coalesce'로 수동합병을 할 수 있다.

추가분(2002-12-15)
dictionary-managed tablespace의 coalesce
별다른 일이 없다면, 자신의 테이블스페이스는 dictionary-managed tablespace이다.
이와 달리, locally-managed tablespace라는 것이 있는데 이에 대한 내용은 이 사이트내 오라클 메뉴 
'Locally Managed Tablespace사용하기'를 참고하기 바란다. 참고로 locally-managed tablespace는 coalesce가 필요치 않다.
coalesce(코우얼레스: 마지막 음절에 강세가 있다. -.-)라는 말은 병합/합체라는 뜻이다. 
테이블스페이스내에 free extent는 연속된 free block들의 집합으로 구성된다. 
테이블스페이스의 세그먼트에 extent를 할당할 경우, 요청된 extent의 크기와 가장 근접한 free extent가 사용되어진다. 
세그먼트가 drop되면 세그먼트에 할당되었던 extent는 deallocated되어져 free한 상태로 된다. 
하지만, 인접한 free extent들이 즉시 하나의 큰 free extent들로 재결합되지는 않는다. 
이로 인해 단편화가 발생하며 이는 커다란 extent를 할당하는 것을 어렵게 한다.

단편화는 몇가지 방법으로 처리될 수 있다.

1. 세그먼트에 새로운 extent를 할당하려고 하면, 오라클은 우선 이 새로운 extent에 맞는 크기의 free extent를 검색한다. 
   만일 충분히 큰 free extent를 발견하지 못한다면, 오라클은 테이블스페이스내의 인접한 free extent들을 병합(coalesce)하고 난뒤, 
   다시 검색하게 된다. 이 병합과정은 적당한 크기의 free extent를 찾지 못한다면, 오라클에 의해 수행된다.

2. SMON 백그라운드 프로세스는 해당 테이블스페이스가 dictionary-managed tablespace이고, pctincrease가 0이 아니라면, 
   주기적으로 이웃한 free extent들을 병합한다. SMON의 병합작업은 오버헤드를 야기할 수 있으므로, 몇몇 DBA들은 
   PCTINCREASE값을 0로 설정하고, DBA 스스로 필요한 시기에 병합처리(coalesce)를 하기도 한다.

3. PCTINCREASE값이 0이 아닌 세그먼트가 drop/truncate되어지면, 제한된 형태의 병합과정이 수행된다. 

4. 사용자가 ALTER TABLESPACE .. COALESCE문장을 수행하여 수동으로 인접한 free extent들을 병합할 수 있다.

팁)
만일 테이블스페이스의 모든 extent가 동일한 크기를 가진다면 coalesce를 해줄 필요는 없다.
colaesce는 data extent에는 적용되지 않는다. 즉, data extent가 단편화되어 있는 경우 coalesce로
이 단편화된 것을 제거하지는 못한다. 이때는 exp/imp로 해결하면 된다.
추가분(2002-12-15)

테스트를 위해 ts_test라는 테이블스페이스를 생성
SQL> create tablespace ts_test
  2  datafile '/u01/app/oracle/oradata/dev2/ts_test01.dbf' size 1m
  3  autoextend on
  4  next 256k maxsize 2m;

생성된 테이블스페이스를 dba_free_space에서 조회해 보자
SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26          2    1040384        127           26


dba_free_space에서 주의깊게 볼 컬럼은 다음과 같다.
FILE_ID:  extent가 속한 파일식별번호
BLOCK_ID: free한 extent의 시작블럭번호
BLOCKS:   free한 블럭수
BYTES:    사용가능한 크기(BLOCKS x db_block_size)


테스트를 위한 notice테이블 생성
SQL> create table notice(
  2  regdate date,
  3  title   varchar(100),
  4  content varchar(2000))
  5  storage( initial 10k next 10k minextents 2 pctincrease 50)
  6  tablespace ts_test;

notice테이블에 1000개의 데이터를 INSERT
SQL> @d:\temp\temp_data.sql	

notice테이블을 ts_test에 생성하고 나서 이 테이블스페이스의 공간(extent)사용상황을 보기위해 dba_extents에 질의해 본다.
SQL> select extent_id, block_id, blocks, bytes
  2  from dba_extents
  3  where segment_name='NOTICE' and owner='SYSTEM';

 EXTENT_ID   BLOCK_ID     BLOCKS      BYTES
---------- ---------- ---------- ----------
         0          2          2      16384
         1          4          2      16384
         2          6          3      24576
         3          9          5      40960
         4         14         10      81920

dba_extents에서 주의깊게 볼 컬럼은 다음과 같다.
BLOCK_ID: 할당된 extent의 시작위치
BLOCKS:   extent내에 할당된 block수
BYTES:    extent의 크기


위에서 보듯이 우리가 insert한 데이터가 continuous하게 insert되었음을 알 수 있다.
extent는 0,1,2,3,4로 총 5개가 존재한다.
이 5개의 extent는 위의 block_id, blocks컬럼값을 보면 알 수 있듯, 순서대로 인접하게 존재한다.


ts_test를 dba_free_space에 조회해 보면 block_id, bytes, blocks가 감소되어 free한 공간이 줄어들었음을 알 수 있다.
SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26         24     860160        105           26

테이블을 drop하고 다시 조회해보면 처음에 조회했을때와 같이 free한 공간이 다시 돌아왔음을 알 수 있다.
SQL> drop table notice;
SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26          2    1040384        127           26


위에서는 단편화가 발생하지 않는 경우를 보인 것이고, 이제부터 단편화되었을때의 예를 보이겠다.
우선 notice, notice1, notice2 3개의 테이블을 다시 생성하겠다.

SQL> create table notice(
  2  regdate date,
  3  title   varchar(100),
  4  content varchar(2000))
  5  storage( initial 10k next 10k minextents 2 pctincrease 50)
  6  tablespace ts_test;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26          6    1007616        123           26

잠 와서 설명을 달기 힘들다. 다음에 달아야지.. 

SQL> create table notice1
  2  storage( initial 4k)
  3  tablespace ts_test
  4  as select * from notice;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26          8     991232        121           26

SQL> create table notice2
  2  storage( initial 10k next 10k pctincrease 0)
  3  tablespace ts_test
  4  as select * from notice;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26         10     974848        119           26

SQL> drop table notice1;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26         10     974848        119           26
TS_TEST                 26          6      16384          2           26

SQL> @d:\temp\temp_data.sql

SQL> insert into notice2 select * from notice;
SQL> /
SQL> /
SQL> /
SQL> /
SQL> COMMIT;
SQL> select extent_id, block_id, blocks, bytes
  2  from dba_extents
  3  where segment_name='NOTICE2' and owner='SYSTEM';

 EXTENT_ID   BLOCK_ID     BLOCKS      BYTES
---------- ---------- ---------- ----------
         0          8          2      16384
         1          6          2      16384
         2         28          2      16384
         3         30          2      16384
         4         32          2      16384
         5         34          2      16384
         6         36          2      16384
         7         38          2      16384
         8         40          2      16384
         9         42          2      16384
        10         44          2      16384
        11         46          2      16384
        12         48          2      16384
        13         50          2      16384
        14         52          2      16384
        15         54          2      16384
        16         56          2      16384
        17         58          2      16384
        18         60          2      16384
        19         62          2      16384
        20         64          2      16384
        21         66          2      16384
        22         68          2      16384
        23         70          2      16384
        24         72          2      16384
        25         74          2      16384
        26         76          2      16384
        27         78          2      16384
        28         80          2      16384
        29         82          2      16384

30 개의 행이 선택되었습니다.

SQL> select * from dba_free_space
  2  where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26         84     368640         45           26

SQL> drop table notice;
SQL> drop table notice2;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26         74      16384          2           26
TS_TEST                 26          2      32768          4           26
TS_TEST                 26         84     368640         45           26
TS_TEST                 26         10     147456         18           26
TS_TEST                 26         72      16384          2           26
TS_TEST                 26         76      16384          2           26
TS_TEST                 26         78      16384          2           26
TS_TEST                 26         80      16384          2           26
TS_TEST                 26         82      16384          2           26
TS_TEST                 26         56      16384          2           26
TS_TEST                 26         58      16384          2           26
TS_TEST                 26         60      16384          2           26
TS_TEST                 26         62      16384          2           26
TS_TEST                 26         64      16384          2           26
TS_TEST                 26         66      16384          2           26
TS_TEST                 26         68      16384          2           26
TS_TEST                 26         70      16384          2           26
TS_TEST                 26         40      16384          2           26
TS_TEST                 26         42      16384          2           26
TS_TEST                 26         44      16384          2           26
TS_TEST                 26         46      16384          2           26
TS_TEST                 26         48      16384          2           26
TS_TEST                 26         50      16384          2           26
TS_TEST                 26         52      16384          2           26
TS_TEST                 26         54      16384          2           26
TS_TEST                 26          8      16384          2           26
TS_TEST                 26          6      16384          2           26
TS_TEST                 26         28      16384          2           26
TS_TEST                 26         30      16384          2           26
TS_TEST                 26         32      16384          2           26
TS_TEST                 26         34      16384          2           26
TS_TEST                 26         36      16384          2           26
TS_TEST                 26         38      16384          2           26

33 개의 행이 선택되었습니다.

SQL> select extent_id, block_id, blocks, bytes
  2  from dba_extents
  3  where segment_name='NOTICE2' and owner='SYSTEM';

선택된 레코드가 없습니다.

SQL> alter tablespace ts_test coalesce;

SQL> select * from dba_free_space where tablespace_name='TS_TEST';

TABLESPACE_NAME    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO
--------------- ---------- ---------- ---------- ---------- ------------
TS_TEST                 26          2    1040384        127           26

변수대입에 대해

더보기

변수대입에 대해

자주 사용하는 부분에 대해선 일일이 코딩하는 노가다를 줄여야 한다.
그럼 누구나 알고 있는 &에 대해 이야기하자.
이 놈은 다음과 같이 insert 작업을 편하게 만들어 준다.

SQL> create table test( id varchar2(10), name varchar2(10));

테이블이 생성되었습니다.

SQL> insert into test values('&id', '&name');
id의 값을 입력하십시오: maddog
name의 값을 입력하십시오: 강명규
구   1: insert into test values('&id', '&name')
신   1: insert into test values('maddog', '강명규')

1 개의 행이 만들어졌습니다.

SQL> /
id의 값을 입력하십시오: superman
name의 값을 입력하십시오: 슈퍼맨
구   1: insert into test values('&id', '&name')
신   1: insert into test values('superman', '슈퍼맨')

1 개의 행이 만들어졌습니다.

처음 &를 사용하여 insert문을 만들면 다음부터는 /만 치면,
필요한 부분에 대해서만 입력하면 되므로 좋은 방법이 될수 있다.
&&와 같이 2개를 사용하면 무슨 효과가 있을까? 이 놈은 한번만 입력하면 
그 값을 유지한다. 역시 예제를 보자.

SQL> insert into test values('&id', '&&name');
id의 값을 입력하십시오: kang
name의 값을 입력하십시오: 강명규
구   1: insert into test values('&id', '&&name')
신   1: insert into test values('kang', '강명규')

1 개의 행이 만들어졌습니다.

SQL> /
id의 값을 입력하십시오: ocp
구   1: insert into test values('&id', '&&name')
신   1: insert into test values('ocp', '강명규')

1 개의 행이 만들어졌습니다.

SQL> /
id의 값을 입력하십시오: oracle
구   1: insert into test values('&id', '&&name')
신   1: insert into test values('oracle', '강명규')

1 개의 행이 만들어졌습니다.

처음 insert문에서 name에 2개의 &를 사용했다.
다음부터의 /입력이후론 name에 대해서는 다시 입력하지 않아도 된다.


그럼 일정부분의 입력만 받고 싶을경우는?
&와 .을 사용하여야 한다. 예제를 보면 싶게 알 수 있을 것이다.

SQL> select * from test where birth='&X.0509';
Enter value for x: 1974
old   1: select * from test where birth='&X.0509'
new   1: select * from test where birth='19740509'

NAME              AGE BIRTH
---------- ---------- --------
강명규             27 19740509

SQL> select * from test where birth='&X0509';
Enter value for x0509: 1974
old   1: select * from test where birth='&X0509'
new   1: select * from test where birth='1974'

no rows selected

ORDBMS기능 맛배기

더보기

ORDBMS기능 맛배기

ORDBMS라고 들어봤을 것이다.
좀 모순이 있는 용어라고 생각된다. 하지만.. 어디까지나 내 생각이다.

본인이 프로그래머라 일단은 C++의 클래스의 개념과 비슷한 type이란 놈을 설명하겠다.
type은 create type이라는 질의로 만들수 있다.
일단 예제를 보자.

create type paycheck_type as object
(
check_number			number(20),  	
payer					varchar2(40),						
payee					varchar2(40),						
date_issued				date,        						
payment_authorization	varchar2(10),
payer_account_number	varchar2(20),
routing_number			varchar2(20),
payment_amount			number(10),
member function adjust_amount( check_number number, deduct_amount number) return number
-- pragma restrict_references(adjust_amount, WNDS)
);

푸.. 이거 완전히 C++의 class구조이다.
무지하게 흥미가 당기게 만든다.
일반 테이블 선언하듯이 하면 되는데 일단은 as object라는 것이 붙어서 자신이 객체라는
것을 알린다. member function도 존재해서 object화를 하는데 구색은 다 갖췄다.
member function은 PL/SQL로 개발할 수 있다.

여기서 adjust_amount라는 놈을 정의해보자.
type body로써 정의한다.
create or replace type body paycheck_type is
	member function adjust_amount( check_number number, deduct_amount number) return number is
	begin
		return check_number - deduct_amount;
	end;
end;

실제 위의 예제를 SQL*PLUS상에서 보자.
SQL> create type paycheck_type as object
  2  (
  3  check_number   number(20),   
  4  payer     varchar2(40),      
  5  payee     varchar2(40),      
  6  date_issued    date,              
  7  payment_authorization varchar2(10),
  8  payer_account_number varchar2(20),
  9  routing_number   varchar2(20),
 10  payment_amount   number(10),
 11  member function adjust_amount( check_number number, deduct_amount number) return number
 12  -- pragma restrict_references(adjust_amount, WNDS)
 13  );
 14  /

유형이 작성되었습니다.

SQL> create or replace type body paycheck_type is
  2   member function adjust_amount( check_number number, deduct_amount number) return number is
  3   begin
  4    return check_number - deduct_amount;
  5   end;
  6  end;
  7  /

유형 본체가 작성되었습니다.

실제 위의 것은 어떻게 사용될 수 있는가?
테이블을 만들어 보자.
위에서 만든 type을 of라는 놈을 사용해서 테이블 만들때 참조한다.

SQL> create table paycheck of paycheck_type;

테이블이 생성되었습니다.
SQL> desc paycheck;
 이름                                                  널?      유형
 ----------------------------------------------------- -------- --------------
 CHECK_NUMBER                                                   NUMBER(20)
 PAYER                                                          VARCHAR2(40)
 PAYEE                                                          VARCHAR2(40)
 DATE_ISSUED                                                    DATE
 PAYMENT_AUTHORIZATION                                          VARCHAR2(10)
 PAYER_ACCOUNT_NUMBER                                           VARCHAR2(20)
 ROUTING_NUMBER                                                 VARCHAR2(20)
 PAYMENT_AMOUNT                                                 NUMBER(10)

SQL> 

재미있는 것은 type이 또 다른 type을 포함할 수 있다는 것이다.
즉, 다음과 같은 표현이 가능하다.

SQL> create type debit_payroll_type as object
  2  (
  3  acc_wd_num number(10),
  4  debit ref paycheck_type
  5  );
  6  /

유형이 작성되었습니다.

debit_payroll도 type이지만, paycheck_type이라는 또 다른 type을 포함하고 있다.
이건 C++에서의 상속과 유사한 개념이다.

그럼 실제 데이터를 넣어보자.
SQL> insert into paycheck values (
  2  paycheck_type(123456, '사장', '명규', sysdate, 'Neximo', 123, 123, 2400));

1 개의 행이 만들어졌습니다.

SQL> select * from paycheck;

CHECK_NUMBER PAYER      PAYEE      DATE_ISS PAYMENT_AU PAYER_ACCOUNT_NUMBER ROUTING_NUMBER       PAYMENT_AMOUNT
------------ ---------- ---------- -------- ---------- -------------------- -------------------- ---
      123456 사장       명규       01/04/03 Neximo     123                  123                            2400
      
흠.. 재미있군..

8이후 추가된 disable novalidate

더보기

8이후 추가된 disable novalidate

환경: Windows 2000 Advanced Server, Oracle EE 8.1.6

오라클8 이후 부터 변경된 제약조건 enable/disable을 테스트해본 예이다.
8이전에는 제약조건(constraint)은 enable/disable 2가지로 상태변경을 했었다.
8이후부터는 3개로 변경되었다.

disable
enable validate
enable novalidate

disable은 이전의 disable과 동일하고, enable validate의 경우 이전의 enable과 동일하다
enable novalidate의 경우, 새로이 추가된 기능이다.
기존의 enable(enable validate로 변경됨)의 경우 constarint를 enable할 시점에 있어 기존의
데이터에 constraint를 위반하는 data가 있으면 enable이 실패하게 된다.
하지만 enable novalidate를 사용하면 기존의 있던 데이터에 대해서는 constraint위반을 체크하지
않고, 새로 입력되는 데이터에 대해서만 체크하게 된다.

아래는 테스트시 사용하게 될 테이블과 DML문이다.

create table employee
(
empid number(10) not null,
name varchar2(40) not null,
salary number(10) not null,
constraint pk_employees_01 primary key(empid) deferrable
);

insert into employee values(1, 'maddog', 2500);
insert into employee values(1, 'superman', 2500);0
insert into employee values(1, 'batman', 2500);
insert into employee values(2, 'kang', 2500);


실제 테스트예

employee테이블을 생성한다.
constraint가 나중에 체크되도록 primary key에 deferrable옵션을 사용했다.
이 옵션을 사용하면 commit시점에서 constraint가 체크된다.
SQL> create table employee
  2  (
  3  empid number(10) not null,
  4  name varchar2(40) not null,
  5  salary number(10) not null,
  6  constraint pk_employees_01 primary key(empid) deferrable
  7  );

테이블이 생성되었습니다.

중복되는 키(empid가 1)를 갖는 2개의 row를 insert한다.
commit시 당연히 오류가 날 것이다.
SQL> insert into employee values(1, 'maddog', 2500);

1 개의 행이 만들어졌습니다.

SQL> insert into employee values(1, 'superman', 2500);

1 개의 행이 만들어졌습니다.

SQL> commit;
commit
*
1행에 오류:
ORA-02091: 트랜잭션이 롤백되었습니다
ORA-00001: 무결성 제약 조건(KANG.PK_EMPLOYEES_01)에 위배됩니다

그냥 데이터가 들어갔는지 확인해보자. 당연히 없다.
SQL> select * from employee;

선택된 레코드가 없습니다.

중복된 키를 갖지 않았으면 당연히 commit된다.
SQL> insert into employee values(1, 'maddog', 2500);

1 개의 행이 만들어졌습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL> delete from employee;

1 행이 삭제되었습니다.

SQL> commit;

커밋이 완료되었습니다.

이제 실제 enable novalidate를 테스트해보자
primary key를 disable하고 난후, 위와 똑같은 상황에서 enable novalidate를 해보자.
SQL> alter table employee
  2  disable constraint pk_employees_01;

테이블이 변경되었습니다.

SQL> insert into employee values(1, 'maddog', 2500);

1 개의 행이 만들어졌습니다.

SQL> insert into employee values(1, 'superman', 2500);

1 개의 행이 만들어졌습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL> alter table employee
  2  enable constraint pk_employees_01;
alter table employee
*
1행에 오류:
ORA-02437: (KANG.PK_EMPLOYEES_01)을 검증할 수 없습니다 - 잘못된 기본 키입니다


SQL> alter table employee
  2  enable validate constraint pk_employees_01;
alter table employee
*
1행에 오류:
ORA-02437: (KANG.PK_EMPLOYEES_01)을 검증할 수 없습니다 - 잘못된 기본 키입니다


SQL> alter table employee
  2  enable novalidate constraint pk_employees_01;

테이블이 변경되었습니다.

SQL> insert into employee values(1, 'batman', 2500);

1 개의 행이 만들어졌습니다.

SQL> commit;
commit
*
1행에 오류:
ORA-02091: 트랜잭션이 롤백되었습니다
ORA-00001: 무결성 제약 조건(KANG.PK_EMPLOYEES_01)에 위배됩니다


SQL> insert into employee values(2, 'kang', 2500);

1 개의 행이 만들어졌습니다.

SQL> commit;

커밋이 완료되었습니다.

SQL> select * from employee;

     EMPID NAME                                         SALARY
---------- ---------------------------------------- ----------
         1 superman                                       2500
         1 maddog                                         2500
         2 kang                                           2500

SQL>

테이블 저장관계 테스트

더보기

테이블 저장관계 테스트

2m인 tablespace를 생성하고 난 뒤, 테이블을 생성한다.

실습1
저장절에서 initial을 2m로 지정하여 생성하려고 하면 에러가 발생한다.

실습2
저장절에서 initial를 1m, next를 1m로 지정하여 생성하면, 에러없이 테이블생성이 되나,
next extent할당이 되지 않는다.


테이블 스페이스 생성

SQL> connect system/xxxxxx
연결되었습니다.
SQL> create tablespace ts_test
  2  datafile 'c:\oracle\oradata\maddog\ts_test1.dbf' size 2m;

테이블 영역이 생성되었습니다.

SQL> create user test identified by test
  2  default tablespace ts_test
  3  temporary tablespace temp;

사용자가 생성되었습니다.

SQL> grant connect, resource to test;

권한이 부여되었습니다.


실습1

SQL> connect test/test
연결되었습니다.
SQL> create table test(
  2  id varchar2(9),
  3  name varchar2(10))
  4  storage ( initial 1m next 1m);

테이블이 생성되었습니다.

SQL> select * from user_segments;

SEGMENT_NAME
--------------------------------------------------------------------------------
PARTITION_NAME                 SEGMENT_TYPE       TABLESPACE_NAME
------------------------------ ------------------ ------------------------------
     BYTES     BLOCKS    EXTENTS INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS
---------- ---------- ---------- -------------- ----------- -----------
MAX_EXTENTS PCT_INCREASE  FREELISTS FREELIST_GROUPS BUFFER_
----------- ------------ ---------- --------------- -------
TEST
                               TABLE              TS_TEST
   1064960        130          1        1048576     1048576           1
        505           50          1               1 DEFAULT

SQL> alter table test allocate extent ( size 1m);
alter table test allocate extent ( size 1m)
*
1행에 오류:
ORA-01653: TEST.TEST 테이블을 128(으)로 TS_TEST 테이블스페이스에서 확장할 수
없습니다


SQL> alter table test allocate extent(size 200k);

테이블이 변경되었습니다.

SQL> select * from user_segments;

SEGMENT_NAME
--------------------------------------------------------------------------------
PARTITION_NAME                 SEGMENT_TYPE       TABLESPACE_NAME
------------------------------ ------------------ ------------------------------
     BYTES     BLOCKS    EXTENTS INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS
---------- ---------- ---------- -------------- ----------- -----------
MAX_EXTENTS PCT_INCREASE  FREELISTS FREELIST_GROUPS BUFFER_
----------- ------------ ---------- --------------- -------
TEST
                               TABLE              TS_TEST
   1269760        155          2        1048576     1048576           1
        505           50          1               1 DEFAULT


SQL> alter table test deallocate unused keep 1m;

테이블이 변경되었습니다.

SQL> select * from user_segments;

SEGMENT_NAME
--------------------------------------------------------------------------------
PARTITION_NAME                 SEGMENT_TYPE       TABLESPACE_NAME
------------------------------ ------------------ ------------------------------
     BYTES     BLOCKS    EXTENTS INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS
---------- ---------- ---------- -------------- ----------- -----------
MAX_EXTENTS PCT_INCREASE  FREELISTS FREELIST_GROUPS BUFFER_
----------- ------------ ---------- --------------- -------
TEST
                               TABLE              TS_TEST
   1056768        129          1        1048576      204800           1
        505           50          1               1 DEFAULT


SQL> drop table test;

테이블이 삭제되었습니다.


실습2

SQL> create table test(id number)
  2  storage(initial 2m);
create table test(id number)
*
1행에 오류:
ORA-01658: TS_TEST 테이블스페이스에 세그먼트에 대한 INITIAL 확장 영역을 작성할
수 없습니다

시스템 권한 & 객체 권한의 grant/revoke

더보기

시스템 권한 & 객체 권한의 grant/revoke

실습 1
system 사용자가 어떤 하나의 system privilege를 A 에게 with admin option으로 주었다.
A는 grant받은 해당 system privilege를 with admin option없이 B에게도 주었다.
system 사용자가 이 상황에서 A에게 주었던 해당 system privilege를 철회했다.
이상황에서 B는 A에게서 받은 해당 system privilege를 그대로 유지하게 된다.


실습 2
실습 1과 유사하나, 이번엔 A가 B에게 권한을 줄때 with admin option으로 준다.
system사용자가 A에게서 권한을 revoke한다. B가 A에게서 받은 with admin option은
유호하다. 다시 B가 A에게 자신이 받은 권한을 부여할 수 있다.


실습 3
이것은 실습 object privilege를 테스트하는 것을 제외하면 실습 1과 동일한 과정이다.
하지만 system privilege와 object privilege는 결과가 다르다.
A라는 사용자가 자신의 테이블에 대한 SELECT권한을 B에게 with grant option으로 주었다
(system privilege는 with admin option, object privilege는 with grant option을 사용한다)
B는 이 권한을 다시 C에게 with grant option없이 부여한다.
A는 B에게 보여한 권한을 revoke한다.
이제 B, C는 모두 권한을 상실하게 된다.
시스템 권한에서 C에게 권한이 유지된 것과는 달리, 객체권한은 cascade하게 모두 철회된다


실습 4
실습3에서 C에게 with grant option으로 권한을 부여한다.
하지만 결과는 동일하다. A가 B에게 권한을 revoke하면 B, C 모두 권한을 상실하게 된다.


실습 5
A가 B에게 자신의 테이블에 대해 references, update, select권한을 주었다.
B는 A테이블에 대해 참조하는 테이블을 생성한다.
A는 B에게서 권한을 revoke하려고 하나, 이전처럼 바로 revoke할 수 없다.
cascade constraints옵션과 함께 revoke한다.


system privilege는 select any table, A는 maddog, B는 scott으로 정하고,
테스트한 예이다.


실습 1

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from v$pwfile_users;
select * from v$pwfile_users
              *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다


SQL> connect scott/tiger
연결되었습니다.
SQL> select * from v$pwfile_users;
select * from v$pwfile_users
              *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다


SQL> connect system/xxxxxx
연결되었습니다.
SQL> grant select any table to maddog with admin option;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
MADDOG                         SELECT ANY TABLE                         YES
MADDOG                         UNLIMITED TABLESPACE                     NO

SQL> grant select any table to scott;

권한이 부여되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
SCOTT                          SELECT ANY TABLE                         NO
SCOTT                          UNLIMITED TABLESPACE                     NO

SQL> connect system/xxxxxx
연결되었습니다.
SQL> revoke select any table from maddog;

권한이 취소되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from v$pwfile_users;
select * from v$pwfile_users
              *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다


SQL> connect scott/tiger
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE                                ADM
------------------------------ ---------------------------------------- ---
SCOTT                          SELECT ANY TABLE                         NO
SCOTT                          UNLIMITED TABLESPACE                     NO

SQL> connect system/xxxxxx
연결되었습니다.

SQL> revoke select any table from scott;

권한이 취소되었습니다.


실습 2

SQL> grant select any table to maddog with admin option;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> grant select any table to scott with admin option;

권한이 부여되었습니다.

SQL> connect system/xxxxxx
연결되었습니다.
SQL> revoke from select any table from maddog;
revoke from select any table from maddog
       *
1행에 오류:
ORA-00990: 권한이 부적합합니다


SQL> revoke select any table from maddog;

권한이 취소되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> grant select any table to maddog;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from v$pwfile_users;

USERNAME                       SYSDB SYSOP
------------------------------ ----- -----
INTERNAL                       TRUE  TRUE
SYS                            TRUE  TRUE

SQL> connect system/xxxxxx
연결되었습니다.
SQL> revoke select any table from maddog, scott;

권한이 취소되었습니다.


실습 3

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
MEMBER                         TABLE
MEMBER_DETAIL                  TABLE

SQL> grant select on member to maddog with grant option;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from kang.member;

ID         PASSWORD   NAME        PERSONNUM        SEX
---------- ---------- ---------- ---------- ----------
maddog     rkskekfk   강명규     xxxxxx          1

SQL> grant select on kang.member to scott;

권한이 부여되었습니다.

SQL> connect scott/tiger;
연결되었습니다.
SQL> select * from kang.member;

ID         PASSWORD   NAME        PERSONNUM        SEX
---------- ---------- ---------- ---------- ----------
maddog     rkskekfk   강명규     xxxxxx          1

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> revoke select on member from maddog;

권한이 취소되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from kang.member;
select * from kang.member
                   *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다


실습 4

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> grant select on member to maddog with grant option;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> grant select on kang.member to scott with grant option;

권한이 부여되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from kang.member;

ID         PASSWORD   NAME        PERSONNUM        SEX
---------- ---------- ---------- ---------- ----------
maddog     rkskekfk   강명규     xxxxxx          1

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> revoke select on member from maddog;

권한이 취소되었습니다.

SQL> connect scott/tiger
연결되었습니다.
SQL> select * from kang.member;
select * from kang.member
                   *
1행에 오류:
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다


실습 5

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> grant references, update, select on member to maddog;

권한이 부여되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> create table member_detail
  2  (
  3  id varchar2(10),
  4  address varchar2(50),
  5  vocation varchar2(10),
  6  constraint member_detail_fk foreign key(id) references kang.member(id)
  7  );

테이블이 생성되었습니다.

SQL> select owner, constraint_name, constraint_type, table_name, r_owner, r_constraint_name
  2  from user_constraints;

OWNER   CONSTRAINT_NAME   C TABLE_NAME       R_OWNER                        R_CONSTRAINT_NAME
------- ----------------- - ---------------- ------------------------------ ------------------
MADDOG  MEMBER_DETAIL_FK  R MEMBER_DETAIL    KANG                           MEMBER_PK

SQL> select * from kang.member;

ID         PASSWORD   NAME        PERSONNUM        SEX
---------- ---------- ---------- ---------- ----------
maddog     rkskekfk   강명규     xxxxxx          1

SQL> insert into member_detail values('maddog', '노상', 'programmer');

1 개의 행이 만들어졌습니다.

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> revoke references, update, select on member from maddog;
revoke references, update, select on member from maddog
*
1행에 오류:
ORA-01981: 현 권한취소를 수행하려면 CASCADE CONSTRAINTS가 지정되어야 합니다


SQL> revoke references, update, select on member from maddog cascade constraints;

권한이 취소되었습니다.

SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> select * from member_detail;

ID         ADDRESS                                            VOCATION
---------- -------------------------------------------------- ----------
maddog     노상                                               programmer

SQL> select * from user_constraints;

선택된 레코드가 없습니다.

SQL>

롤과 권한에 대한 실습

더보기

롤과 권한에 대한 실습

작성자: 강명규
OS: Linux 7.0(Kernel 2.4.10)
Oracle: Enterprise Edition 8.1.7


강명규,임꺽정,홍길동 3명의 사용자를 생성한다.
강명규가 테이블의 소유자로 지정할 것이고, 나머지 임꺽정,홍길동은
강명규가 소유한 테이블을 access하는 사용자로 지정할 것이다.

의적이라는 롤을 생성한다.
의적이라는 롤에게 강명규가 소유한 테이블들에 대한 select권한을 부여할 것이다.
의적이라는 롤은 임꺽정,홍길동에게 부여한다.

결론적으로 임꺽정,홍길동은 강명규가 가진 테이블에 대한 select권한을 가질 것이다.


SQL> connect system/xxxxxx@dev2
연결되었습니다.
SQL> create user 강명규 identified by aa
  2  default tablespace users
  3  temporary tablespace temp
  4  quota 10m on users;

사용자가 생성되었습니다.

SQL> create user 임꺽정 identified by bb
  2  default tablespace users
  3  temporary tablespace temp
  4  quota 0m on users;

사용자가 생성되었습니다.

SQL> create user 홍길동 identified by cc
  2  default tablespace users
  3  temporary tablespace temp
  4  quota 0m on users;

사용자가 생성되었습니다.


여기서 잠깐)
패스워드는 사용자이름과 달리 한글로 지정할 수 없다.


생성된 사용자에게 권한부여
강명규는 기본적으로 사용되는 connect, resource롤을 부여한다.
connect, resource롤은 아래와 같은 시스템권한을 가지고 있다.

SQL> select grantee, privilege from dba_sys_privs
  2  where grantee in('CONNECT', 'RESOURCE');

GRANTEE         PRIVILEGE
--------------- --------------------
CONNECT         ALTER SESSION
CONNECT         CREATE CLUSTER
CONNECT         CREATE DATABASE LINK
CONNECT         CREATE SEQUENCE
CONNECT         CREATE SESSION
CONNECT         CREATE SYNONYM
CONNECT         CREATE TABLE
CONNECT         CREATE VIEW
RESOURCE        CREATE CLUSTER
RESOURCE        CREATE INDEXTYPE
RESOURCE        CREATE OPERATOR
RESOURCE        CREATE PROCEDURE
RESOURCE        CREATE SEQUENCE
RESOURCE        CREATE TABLE
RESOURCE        CREATE TRIGGER
RESOURCE        CREATE TYPE

16 개의 행이 선택되었습니다.


SQL> grant connect, resource to 강명규;

권한이 부여되었습니다.


임꺽정,홍길동은 연결만 가능하도록 하는 create session 시스템권한만 준다.

SQL> grant create session to 임꺽정,홍길동;

권한이 부여되었습니다.

SQL> create role 의적;

롤이 생성되었습니다.

SQL> grant 의적 to 임꺽정,홍길동;

권한이 부여되었습니다.



강명규로 로그인하여 '회원' '주소' 2개의 테이블을 생성하여
이 테이블들에 대한 select권한을 의적이라는 롤에 부여한다.

SQL> connect 강명규/aa@dev2
연결되었습니다.
SQL> create table 회원
  2  (
  3  아이디 varchar(10),
  4  이름 varchar(10),
  5  나이 number(3)
  6  );

테이블이 생성되었습니다.

SQL> create table 주소
  2  (
  3  아이디 varchar(10),
  4  주소 varchar(50)
  5  );

테이블이 생성되었습니다.

SQL> alter table 회원
  2  add constraint 회원_pk primary key(아이디)
  3  using index tablespace users;

테이블이 변경되었습니다.

SQL> alter table 주소
  2  add constraint 주소_fk foreign key(아이디)
  3  references 회원(아이디);

테이블이 변경되었습니다.

SQL> grant select on 회원 to 의적;

권한이 부여되었습니다.

SQL> grant select on 주소 to 의적;

권한이 부여되었습니다.

강명규가 사용가능한 테이블스페이스 할당량
SQL> select * from user_ts_quotas;

TABLESPACE_NAME                     BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS
------------------------------ ---------- ---------- ---------- ----------
USERS                                   0   10485760          0       1280

강명규가 가진 시스템권한
SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE            ADM
------------------------------ -------------------- ---
강명규                         UNLIMITED TABLESPACE NO

강명규가 가진 객체권한
SQL> select * from user_tab_privs;

GRANTEE         OWNER      TABLE_NAME           GRANTOR    PRIVILEGE            GRA
--------------- ---------- -------------------- ---------- -------------------- ---
의적            강명규     회원                 강명규     SELECT               NO
의적            강명규     주소                 강명규     SELECT               NO

강명규가 다른 사용자에게 부여한 객체권한
SQL> select * from user_tab_privs_made;

GRANTEE         TABLE_NAME           GRANTOR    PRIVILEGE            GRA
--------------- -------------------- ---------- -------------------- ---
의적            주소                 강명규     SELECT               NO
의적            회원                 강명규     SELECT               NO

강명규가 다른 사용자로부터 받은 객체권한
SQL> select * from user_tab_privs_recd;

선택된 레코드가 없습니다.


이제 임꺽정으로 로그인하여 사용자 정보를 보자
홍길동은 임꺽정과 동일하므로 생략하겠다.

SQL> connect 임꺽정/bb@dev2
연결되었습니다.
SQL> select * from user_ts_quotas;

TABLESPACE_NAME                     BYTES  MAX_BYTES     BLOCKS MAX_BLOCKS
------------------------------ ---------- ---------- ---------- ----------
USERS                                   0          0          0          0

SQL> select * from user_sys_privs;

USERNAME                       PRIVILEGE            ADM
------------------------------ -------------------- ---
임꺽정                         CREATE SESSION       NO

임꺽정은 의적이라는 롤을 부여받았으므로 강명규가 소유한 회원테이블을 select할 수 있다.
SQL> select * from 강명규.회원;

선택된 레코드가 없습니다.

아래의 예에서 
임꺽정이 강명규에 대한 테이블을 select할 수 있음에도 불구하고 0개의 row가 리턴되는 이유는 
select 권한이 의적이라는 롤에게 부여되었고, 의적 롤은 임꺽정에게 부여되었으므로 
해당사용자에 대한 직접적으로 select 객체권한을 부여받은 것이 아니기 때문이다.

SQL> select * from user_tab_privs;

선택된 레코드가 없습니다.

SQL> select * from user_tab_privs_made;

선택된 레코드가 없습니다.

SQL> select * from user_tab_privs_recd;

선택된 레코드가 없습니다.

SQL> select * from user_role_privs;

USERNAME                       GRANTED_ROLE                   ADM DEF OS_
------------------------------ ------------------------------ --- --- ---
임꺽정                         의적                           NO  YES NO

SQL> connect system/xxxxxx@dev2
연결되었습니다.

SQL> select * from dba_tab_privs
  2  where grantee in('의적');

GRANTEE         OWNER      TABLE_NAME           GRANTOR    PRIVILEGE            GRA
--------------- ---------- -------------------- ---------- -------------------- ---
의적            강명규     회원                 강명규     SELECT               NO
의적            강명규     주소                 강명규     SELECT               NO



강명규가 가진 테이블에 대한 select권한을 임꺽정, 의적 둘 다에 부여한다.
롤에게서 권한을 revoke했을때, 사용자는 계속 강명규가 가진 테이블에 대한 select권한을 가진다.
따라서 롤/사용자에게 부여되는 권한이 중복되지 않게 부여하는 것이 관리적인 면에서 중요하다.


SQL> connect 강명규/aa@dev2
연결되었습니다.
SQL> grant select on 회원 to 임꺽정;

권한이 부여되었습니다.

SQL> grant select on 주소 to 임꺽정;

권한이 부여되었습니다.

SQL> revoke select on 회원 from 의적;

권한이 취소되었습니다.

SQL> revoke select on 주소 from 의적;

권한이 취소되었습니다.

SQL> connect 임꺽정/bb@dev2
연결되었습니다.
SQL> select * from 강명규.주소;

선택된 레코드가 없습니다.


cf)
grant옵션(객체권한과 관련)과 admin옵션(시스템권한과 관련)에 따른 grant,revoke는 링크를 참조한다

TABLESPACE CREATION DROP

더보기

TABLESPACE CREATION DROP

현재상황
kang이라는 유저의 디폴트 테이블스페이스는 ts_kang이다.
현재 kang이라는 유저가 접속되어 있고 ts_kang의 status는 online상태이다.
system계정에서 테이블스페이스 ts_kang을 drop(삭제)하려고 한다.

SQL> select * from dba_tablespaces;

TABLESPACE_NAME                INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE MIN_EXTLEN STATUS    CONTENTS  LOGGING   EXTENT_MAN ALLOCATIO PLU
------------------------------ -------------- ----------- ----------- ----------- ------------ ---------- --------- --------- --------- ---------- --------- ---
SYSTEM                                  65536       65536           1  2147483645           50      65536 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
RBS                                    524288      524288           8        4096           50     524288 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
USERS                                  131072      131072           1        4096            0     131072 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
TEMP                                    65536       65536           1                        0      65536 ONLINE    TEMPORARY LOGGING   DICTIONARY USER      NO
TOOLS                                   32768       32768           1        4096            0      32768 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
INDX                                   131072      131072           1        4096            0     131072 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
DRSYS                                   65536       65536           1  2147483645           50      65536 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
TS_KANG                                 16384       16384           1         505            0          0 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
OEM_REPOSITORY                          65536                       1  2147483645                   65536 ONLINE    PERMANENT LOGGING   LOCAL      SYSTEM    NO

9 개의 행이 선택되었습니다.


테이블스페이스가 empty상태가 아니라면 즉, 테이블스페이스내 데이터를 가진 segment들이 존재할 경우,
including contents를 사용하여 drop 시켜야 한다.

SQL> drop tablespace ts_kang;
drop tablespace ts_kang
*
1행에 오류:
ORA-01549: 테이블스페이스가 비어있지 않으므로 INCLUDING CONTENTS 옵션을 사용해 주십시오


SQL> drop tablespace ts_kang including contents;

테이블 영역이 삭제되었습니다.

SQL> select * from dba_tablespaces;

TABLESPACE_NAME                INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE MIN_EXTLEN STATUS    CONTENTS  LOGGING   EXTENT_MAN ALLOCATIO PLU
------------------------------ -------------- ----------- ----------- ----------- ------------ ---------- --------- --------- --------- ---------- --------- ---
SYSTEM                                  65536       65536           1  2147483645           50      65536 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
RBS                                    524288      524288           8        4096           50     524288 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
USERS                                  131072      131072           1        4096            0     131072 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
TEMP                                    65536       65536           1                        0      65536 ONLINE    TEMPORARY LOGGING   DICTIONARY USER      NO
TOOLS                                   32768       32768           1        4096            0      32768 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
INDX                                   131072      131072           1        4096            0     131072 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
DRSYS                                   65536       65536           1  2147483645           50      65536 ONLINE    PERMANENT LOGGING   DICTIONARY USER      NO
OEM_REPOSITORY                          65536                       1  2147483645                   65536 ONLINE    PERMANENT LOGGING   LOCAL      SYSTEM    NO

8 개의 행이 선택되었습니다.


위에서는 테이블스페이스가 online인 상태에서 바로 drop시켰다.
하지만 현재 활성화된 작업이 있다면 실패하게 된다. 
이럴때는 테이블스페이스를 offline으로 변경하여 삭제한다.

SQL> alter tablespace ts_kang offline;
SQL> drop tablespace ts_kang including contents;


drop tablespace을 하고나면, DB의 control file에서 해당 데이터파일의 file pointer만 drop시킨다.
실제 데이터파일은 해당 디렉토리에 그대로 존재한다.
따라서 완전삭제를 위해서는 OS명령으로 해당 데이터 파일을 삭제해줘야한다.

drop할 테이블스페이스내에 primary key or unique제한조건을 가진 테이블을 가지고 있고,
다른 테이블스페이스에 있는 테이블이 이를 reference하는 foreign키를 가진다면

drop tablespace ts_kang including contents cascade constraints

로 child table의 foreign key constraints를 제거할 수 있다.


다음은 실제 테이블스페이스생성, 사용자추가, 테이블생성, 사용자변경, 사용자삭제, 테이블스페이스삭제의 과정이다.


SQL> select t.name, d.status, d.name from v$tablespace t, v$datafile d where t.ts# = d.ts#;

NAME                           STATUS  NAME
------------------------------ ------- ------------------------------------------------------
SYSTEM                         SYSTEM  C:\ORACLE\ORADATA\MADDOG\SYSTEM01.DBF
RBS                            ONLINE  C:\ORACLE\ORADATA\MADDOG\RBS01.DBF
USERS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\USERS01.DBF
TEMP                           ONLINE  C:\ORACLE\ORADATA\MADDOG\TEMP01.DBF
TOOLS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\TOOLS01.DBF
INDX                           ONLINE  C:\ORACLE\ORADATA\MADDOG\INDX01.DBF
DRSYS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\DR01.DBF
OEM_REPOSITORY                 ONLINE  C:\ORACLE\ORADATA\MADDOG\OEM_REPOSITORY.ORA

8 개의 행이 선택되었습니다.

SQL> create tablespace ts_kang
  2  datafile 'c:\oracle\oradata\maddog\ts_kang.dbf' size 5m
  3  default storage( minextents 1 maxextents 50 initial 100k next 100k pctincrease 0 );

테이블 영역이 생성되었습니다.

SQL> select t.name, d.status, d.name from v$tablespace t, v$datafile d where t.ts# = d.ts#;

NAME                           STATUS  NAME
------------------------------ ------- -------------------------------------------------------
SYSTEM                         SYSTEM  C:\ORACLE\ORADATA\MADDOG\SYSTEM01.DBF
RBS                            ONLINE  C:\ORACLE\ORADATA\MADDOG\RBS01.DBF
USERS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\USERS01.DBF
TEMP                           ONLINE  C:\ORACLE\ORADATA\MADDOG\TEMP01.DBF
TOOLS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\TOOLS01.DBF
INDX                           ONLINE  C:\ORACLE\ORADATA\MADDOG\INDX01.DBF
DRSYS                          ONLINE  C:\ORACLE\ORADATA\MADDOG\DR01.DBF
TS_KANG                        ONLINE  C:\ORACLE\ORADATA\MADDOG\TS_KANG.DBF
OEM_REPOSITORY                 ONLINE  C:\ORACLE\ORADATA\MADDOG\OEM_REPOSITORY.ORA

9 개의 행이 선택되었습니다.


2명의 사용자를 생성한다.
테이블스페이스 drop시, maddog은 drop할 것이고 kang은 남겨둘 것이다.
SQL> create user kang identified by xxxxxx
  2  default tablespace ts_kang
  3  temporary tablespace temp
  4  quota 1m on ts_kang;

사용자가 생성되었습니다.

SQL> create user maddog identified by xxxxxx
  2  default tablespace ts_kang
  3  temporary tablespace temp
  4  quota 2m on ts_kang;

사용자가 생성되었습니다.
 
SQL> grant connect, resource to kang;

권한이 부여되었습니다.

SQL> grant connect, resource to maddog;

권한이 부여되었습니다.

사용자 kang으로 로그인한후 테이블을 만들고 데이터를 하나 넣는다.
SQL> connect kang/xxxxxx
연결되었습니다.
SQL> create table member
  2  (
  3  id varchar2(10),
  4  password varchar2(10) not null,
  5  name varchar2(10),
  6  personnum number(13),
  7  sex number(1) default 1 not null,
  8  constraint member_pk primary key(id),
  9  constraint member_ch_pn check( length(personnum) = 13 )
 10  )
 11  storage( initial 32k next 32k minextents 1 maxextents 30 pctincrease 0 ) 
 12  pctused 75 pctfree 5
 13  tablespace ts_kang;

테이블이 생성되었습니다.

SQL> insert into member values('maddog', 'hahaha', '강명규', 1234567890123, 1 );

1 개의 행이 만들어졌습니다.


사용자 maddog에도 동일하게 작업한다.
SQL> connect maddog/xxxxxx
연결되었습니다.
SQL> create table member
  2  (
  3  id varchar2(10),
  4  password varchar2(10) not null,
  5  name varchar2(10),
  6  personnum number(13),
  7  sex number(1) default 1 not null,
  8  constraint member_pk primary key(id),
  9  constraint member_ch_pn check( length(personnum) = 13 )
 10  )
 11  storage( initial 32k next 32k minextents 1 maxextents 60 pctincrease 0 ) 
 12  pctused 75 pctfree 5
 13  tablespace ts_kang;

테이블이 생성되었습니다.

SQL> insert into member values('maddog', 'hahaha', '강명규', 1234567890123, 1 );

1 개의 행이 만들어졌습니다.


여기서 잠깐 tablespace와 segment(segment type: table)의 저장절을 위시한 내용을 짚고 넘어가자


TABLE
create table member
(
id varchar2(10),
password varchar2(10) not null,
name varchar2(10),
personnum number(13),
sex number(1) default 1 not null,
constraint member_pk primary key(id) using index tablespace ts_index,
constraint member_ch_pn check( length(personnum) = 13 )
)
storage( initial 32k next 32k minextents 1 maxextents 60 pctincrease 0 ) 
pctused 75 pctfree 5
tablespace ts_kang;

insert into member values('maddog', 'hahaha', '강명규', 1234567890123, 1 );

create table member_detail
(
id varchar2(10),
address varchar2(50),
vocation varchar2(10),
constraint member_detail_fk foreign key(id) references member(id)
)

SQL> drop table member cascade constraints;

테이블이 삭제되었습니다.


storage줄의 괄호안 부분은 extent의 할당과 관련을 가진다.

initial: segment의 처음 extent의 크기를 지정한다. 여기서는 23k bytes이다. 
         현재 db block의 크기가 8k bytes로 설정되어 있다.
         extent는 db block들의 합이므로 크기는 db block크기의 배수로 지정하는 것이 좋겠다.

next: 데이블내에 데이터가 많아져서 다음번째 extent를 할당해야 한다.
      다음번째 증가하는 extent의 크기를 지정한다.
      pctincrease가 0이므로 여기서는 다음 extent의 크기는 32k bytes이다.
      원래, 다음 할당되는 extent의 크기는 다음과 같다.
      
      ( 마지막 할당된 extent의 크기 + 마지막 할당된 extent의 크기 x pctincrease(백분율임을 유의))
      
      여기서는 pctincrease가 0이므로 항상 다음 extent의 크기는 32k bytes가 된다.
      만일 여기서 pctincrease를 10으로 잡았다면 처음 extent는 32k, 2번째는 32k, 3번째는 32.1k(32k x 0.1),
      4번째는 32.1k x 0.1, ... 이 될것이다. 
      extent는 db block의 집합이므로 만일 DB블럭크기에 맞지 않다면, extent의 크기는 DB블럭크기에 맞게 조정될 것이다.
      
minextents: 최소 extent의 개수, 참고로 롤백세그먼트는 항상 minextents의 개수가 2이상이어야 한다.

maxextents: 최대 extent의 개수. 이 값을 넘어서면 더이상 extent가 할당될 수 없다.

pctincrease: 다음 extent증가치(백분율)

그외: rollback segment의 경우 optimal이 사용가능하다.
      freelists, freelist groups


그 밑줄의 pctused, pctfree는 DB Block의 공간할당과 연관된다.

pctused: db block크기의 몇 퍼센트까지 데이터를 저장하기 위해 사용할 것인가?
         여기서는 75%를 지정했다. 따라서 블럭에 들어가는 row들이 블럭내 사용율 75%를
         초과하면 다음 db block에 row를 저장할 것이다.
         
pctfree: update연산을 위해 db block에서 여분으로 둘 공간퍼센트

마지막 줄은 사용할 테이블을 지정한다.
지정하지 않으면 사용자의 default tablespace에 테이블을 생성한다.


TABLESPACE
create tablespace ts_test
datafile 'ts_test.dbf' size 1m
default storage
(initial 100k next 100k minextents 1 maxextents 10 pctincrease 0)
online;

tablespace는 테이블과 달리 storage앞에 꼭 default가 붙어야 한다.
storage절의 내용은 테이블과 동일.
pctused, pctfree사용못함


세그먼트(segment name: member, segment type: table)에 할당된 
extent의 개수는 dba_segments에서 확인할 수 있다.

SQL> select segment_name, segment_type, tablespace_name,bytes, blocks, extents
  2  from user_segments;

SEGMENT_NAME         SEGMENT_TYPE       TABLESPACE_NAME                     BYTES     BLOCKS    EXTENTS
-------------------- ------------------ ------------------------------ ---------- ---------- ----------
MEMBER               TABLE              TS_KANG                             32768          4          1
PLAN_TABLE           TABLE              TS_KANG                            122880         15          1
MEMBER_PK            INDEX              TS_INDEX                           122880         15          1




이제 테이블스페이스 ts_kang을 삭제할 것이다.
우선, 사용자 maddog을 삭제하겠다.
SQL> connect system/xxxxxx
연결되었습니다.

drop할 계정이 자신의 shema에 이미 데이터를 가졌다면 cascade옵션을 줘야 한다.
SQL> drop user maddog;
drop user maddog
*
1행에 오류:
ORA-01922: 'MADDOG'(을)를 삭제하려면 CASCADE를 지정하여야 합니다


SQL> drop user maddog cascade;

사용자가 삭제되었습니다.


이제 테이블 스페이스를 drop하자.
drop하기 전에 테이블스페이스를 offline으로 만들어 활성화된 작업이 없도록 하자.
처음에 설명한대로 테이블스페이스내 데이터가 있다면 including contents옵션을 사용해야 한다.


참고
테이블스페이스의 옵션에서 offline외에 read only, read write옵션도 있다.
보통의 테이블스페이스는 read write상태로 읽기와 쓰기가 가능하다.
만일 테이블스페이스에 데이터를 읽기만 가능하고(select only), 
쓰지 못하게 하려면(insert, update, delete not permitted)
read only옵션을 사용한다.


SQL> alter tablespace ts_kang offline;

테이블 영역이 변경되었습니다.

SQL> drop tablespace ts_kang;
drop tablespace ts_kang
*
1행에 오류:
ORA-01549: 테이블스페이스가 비어있지 않으므로 INCLUDING CONTENTS 옵션을 사용해 주십시오


SQL> drop tablespace ts_kang including contents;

테이블 영역이 삭제되었습니다.


tablespace ts_kang을 drop했을때 kang이 만든 member테이블과 그 안의
데이터들은 날아가버렸다.
사용자의 kang의 default tablespace(ts_kang)가 존재하지 않는다.
따라서 새로운 object를 생성할 수도 없다.


SQL> connect kang/xxxxxx
연결되었습니다.
SQL> select * from tab;

선택된 레코드가 없습니다.

SQL> create table test(id number);
create table test(id number)
*
1행에 오류:
ORA-00959: 테이블 영역 'TS_KANG' 가 존재하지 않습니다


사용자 kang의 default tablespace를 users로 변경한다.
SQL> alter user kang
  2  default tablespace users;

사용자가 변경되었습니다.

SQL> connect kang/xxxxxx
연결되었습니다.
SQL> create table test(id number);

테이블이 생성되었습니다.

SQL> drop table test;

테이블이 삭제되었습니다.

아카이브모드 사용

더보기

아카이브모드 사용

패러미터파일(init[SID].ora)에 다음과 같이 지정한다.

log_archive_start = true			(자동 아카이브를 사용하겠음,  ARCH백그라운드프로세스가 실행됨)
log_archive_dest = "C:\Oracle\oradata\maddog\archive"	(아카이브로그가 저장될 곳)
log_archive_format = %%ORACLE_SID%%T%TS%S.ARC	(파일이름을 어떤 식으로 할 것인가 지정)

이렇게 한 후, 데이터베이스를 시동하면 자동아카이빙으로 들어가게 된다.
오라클 8iEE(Enterprise Edition 8.1.xx버전이후로는 다음과 같이 사용할 것을 권고하고 있다.)
log_archive_start가 true이면 온라인redolog파일이 full되었을 경우 자동으로 아카이빙을 처리할 수 있게 한다.

log_archive_dest_1 = "location=C:\Oracle\oradata\maddog\archive"

log_archive_dest_n에서 n은 5개까지 잡혀져 있다.

자동 아카이빙이란
online redo log파일이 full이되면 로그스위치가 발생한다.
LGWR는 redo를 online redo log의 또 다른 set에 쓰기 시작한다.
(즉, 다른 로그그룹에 쓴다.)
로그 스위치후, 체크포인트가 발생한다.
LGWR는 DBWR에게 DB의 변경사항들을 포함하는 모든 버퍼에 있는 버퍼캐쉬의 내용을
디스크에 쓰도록한다. 또한 LOGWR는 로그스위치정보를 datafile의 헤더와 control파일에
쓴다. 자동 아카이빙을 설정했다면 마지막으로 ARCH백그라운드 프로세스가 online redo log를
LOG_ARCHIVE_DEST에 지정되어 있는 디렉토리로 복사한다.
만약 수동으로 아카이브하려면 다음과 같이 해줘야 한다.
이것은 full된 online redo log파일을 아카이브한다.

alter system archive log all to '/u01/oracle/arch'


alter system archive log start(자동아카이빙사용)는 ARCHIVE_LOG_DEST에 지정된 디렉토리로
archive log파일을 기록한다. 만일 수동으로 위치를 지정하고 싶다면 다음과 같이
한다.

alter system archive log start to '/u02/oracle/archive'

SVRMGR> startup
ORACLE 인스턴스가 시작되었습니다.
시스템 글로벌 영역                         45487372 바이트 합계
Fixed Size                                          70924 바이트
Variable Size                                    28364800 바이트
Database Buffers                                 16973824 바이트
Redo Buffers                                        77824 바이트
데이터베이스가 마운트되었습니다.
데이터베이스가 열려졌습니다.

SVRMGR> archive log list
데이터베이스 로그 모드         아카이브 모드가 아님
자동 아카이벌                  사용 가능
아카이브 수신지                C:\Oracle\oradata\maddog\archive (ARCHIVE_LOG_DEST)
가장 오래된 온라인 로그 순차   1165
현재 로그 순차                 1167


현재 위의 예에서 보듯이 DB가 아카이브 모드가 아니다.
데이터베이스 로그 모드'는 데이터베이스 생성시 지정해줘야 된다.
default는 noarchivelog이다.

create database .. [archivelog or noarchivelog]


noarchivelog인 데이터베이스를 archivelog모드로 변경하기 위해선 다음과 같이 해야 한다.

1. 데이터베이스 인스턴스를 shutdown한다.
2. 데이터베이스를 백업한다.(DB변경사항이 있으면 하는 형식적인 절차이다.)
3. 데이터베이스 인스턴스를 start, mount한다.(open하지 않음)
   만일 OPS(Oracle Parallel Server)를 사용한다면 exclusive하게 mount해야 한다.
4. 데이터베이스를 archivelog모드로 변경한다.

SVRMGR> shutdown
데이터베이스가 닫혔습니다.
데이터베이스가 마운트 해제되었습니다.
ORACLE 인스턴스가 종료되었습니다.

SVRMGR> startup mount exclusive;
ORACLE 인스턴스가 시작되었습니다.
시스템 글로벌 영역                         45487372 바이트 합계
Fixed Size                                          70924 바이트
Variable Size                                    28364800 바이트
Database Buffers                                 16973824 바이트
Redo Buffers                                        77824 바이트
데이터베이스가 마운트되었습니다.

SVRMGR> alter database maddog archivelog;
명령문이 처리되었습니다.

SVRMGR> archive log list
데이터베이스 로그 모드         아카이브 모드
자동 아카이벌                  사용 가능
아카이브 수신지                C:\Oracle\oradata\maddog\archive
가장 오래된 온라인 로그 순차   1165
다음 아카이브 로그 순차        1167
현재 로그 순차                 1167

SVRMGR> alter database maddog open;
명령문이 처리되었습니다.

참조)
패러미터파일에서 log_archive_start = true을 설정하여 자동 아카이브를 사용할 수도 있으나,
서버관리자에서 archive log start로도 자동 아카이브를 사용할 수도 있다.

SVRMGR> archive log list
데이터베이스 로그 모드         아카이브 모드가 아님
자동 아카이벌                  사용 불가능
아카이브 수신지                C:\Oracle\Ora81\RDBMS
가장 오래된 온라인 로그 순차   1165
현재 로그 순차                 1167

SVRMGR> alter system archive log start	(alter system은 생략 가능하다)
명령문이 처리되었습니다.

SVRMGR> archive log list
데이터베이스 로그 모드         아카이브 모드가 아님
자동 아카이벌                  사용 가능
아카이브 수신지                C:\Oracle\Ora81\RDBMS
가장 오래된 온라인 로그 순차   1165
현재 로그 순차                 1167

SVRMGR> alter system archive log stop	(alter system은 생략 가능하다)
명령문이 처리되었습니다.

참조)
log_archive_format에 대해 살펴보자.

log_archive_format = %%ORACLE_SID%%T%TS%S.ARC

%%ORACLE_SID은 자신의 SID가 될 것이다. 여기서는 maddog이 되겠다.

%T: OPS(Oracle Parallel Server)안에 있는 instance의 redo log들에 대한 쓰레드번호. 좌측이 0으로 채워짐
%t: 상동. 좌측이 0으로 채워지지 않음
%S: 로그시퀀스번호. 좌측이 0으로 채워짐
%s: 상동. 좌측이 0으로 채워지지 않음

실제 위의 예에서 log_archive_format로 지정한 파일이름이 어떻게 생성되는지를 보자.
SVRMGR> alter system switch logfile;	이 명령으로 archive log파일이 디스크에 기록되게 된다
명령문이 처리되었습니다.

SVRMGR> archive log list;
데이터베이스 로그 모드         아카이브 모드
자동 아카이벌                  사용 가능
아카이브 수신지                C:\Oracle\oradata\maddog\archive
가장 오래된 온라인 로그 순차   1166
다음 아카이브 로그 순차        1168
현재 로그 순차                 1168

DB의 아카이브상태는 v$database뷰에서도 알수 있다.
v$database는 또한 change-based복구에서 필요로 하는 SCN을 제공한다.
로그순차(log sequence)의 경우 v$log_history뷰에서도 알 수 있다.
v$database의 정보는 control file에서 수집된 것이다.

SQL> select * from v$database;

      DBID NAME      CREATED  RESETLOGS_CHANGE# RESETLOG PRIOR_RESETLOGS_CHANGE#
---------- --------- -------- ----------------- -------- -----------------------
PRIOR_RE LOG_MODE     CHECKPOINT_CHANGE# ARCHIVE_CHANGE# CONTROL CONTROLF
-------- ------------ ------------------ --------------- ------- --------
CONTROLFILE_SEQUENCE# CONTROLFILE_CHANGE# CONTROLF OPEN_RESETL VERSION_
--------------------- ------------------- -------- ----------- --------
OPEN_MODE
----------
3524231243 MADDOG    00/09/03                 1 00/09/03                       0
         ARCHIVELOG             83385621          161317 CURRENT 00/09/03
                 3554            83385621 00/11/07 NOT ALLOWED 00/09/03
READ WRITE



SQL> SELECT * FROM V$LOG_HISTORY;


     RECID      STAMP    THREAD#  SEQUENCE# FIRST_CHANGE# FIRST_TI NEXT_CHANGE#
---------- ---------- ---------- ---------- ------------- -------- ------------
         1  407369109          1          1             1 00/09/03          281
         2  407369111          1          2           281 00/09/03          673
         3  407369114          1          3           673 00/09/03         1248
         4  407369119          1          4          1248 00/09/03         1740
         5  407369121          1          5          1740 00/09/03         2339
         6  407369124          1          6          2339 00/09/03         2929
         7  407369127          1          7          2929 00/09/03         3442
.
.
      1165  407373591          1       1165        161240 00/09/03       161317
      1166  407374000          1       1166        161317 00/09/03       181479
      1167  412272843          1       1167        181479 00/09/03       182038


위의 명령실행후, C:\Oracle\oradata\maddog\archive에 가보면 다음과 같은 파일이 생긴것을 알 수 있다.

MADDOGT001S01167.ARC

현재 활성화된 리두로그는 다음의 질의를 통해 알수 있다.
여기서 ARCHIVED(예제에서는 ARC로 이름이 짤렸다.)는 어떤 리두로그그룹이 archive되었는지 알 수 있다.
SQL> select * from v$log;

    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TI
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------
         1          1       1168    1048576          1 NO  CURRENT                 182038 00/10/29
         2          1       1166    1048576          1 YES INACTIVE                161317 00/09/03
         3          1       1167    1048576          1 YES INACTIVE                181479 00/09/03

SQL> select * from v$logfile;

    GROUP# STATUS  MEMBER
---------- ------- ----------------------------------------
         1         C:\ORACLE\ORADATA\MADDOG\REDO01.LOG
         2 STALE   C:\ORACLE\ORADATA\MADDOG\REDO02.LOG
         3         C:\ORACLE\ORADATA\MADDOG\REDO03.LOG

음.. v$log와 v$logfile을 group#으로 join key를 삼아서 join하면 좋겠군..

패러미터파일(init.ora)의 LOG_ARCHIVE_DEST에 저장되는 아카이브된 redo로그들은
보통 오프라인상태인 테이프등에 백업받아 두는 것이 좋다.
만약 아카이브된 리두로그가 손상되었다면 손상된 리두로그 바로 전의 시점까지만
복구된다. 이런 상황에서는 단지 완벽하지 않은(incomplete) 복구를 할 수 밖에 없다.
incomplete복구는 time-based, change-based, cancel-based가 있다.

2001-11-11 추가
아카이브된 리두로그(offline 리두로그라고도 함)파일들은 log_archive_dest에 쌓이게 되고
여기에 쌓인 파일들의 목록들은 v$archived_log에 기록된다.

2001-12-22 추가
패러미터파일(Init.ora)에서 아카이브관련된 이름은 log_archive_로 시작한다.
SVRMGRL프롬프트상에서 아카이브에 관련된 이름은 archive log로 지정된다.

관련뷰: v$archived_log, v$logfile, v$log, v$log_history


2004-01-31 추가
9i부터는 다음과 같이 하면 된다.

DB를 아카이빙이 사용할 디렉토리 지정
SQL> alter system set log_archive_dest='/u01/app/oracle/admin/dev/arch'; (오라클 재시작시 반영안됨)
or
SQL> alter system set log_archive_dest='/u01/app/oracle/admin/dev/arch' scope=both; (오라클 재시작시 반영됨)

DB를 아카이브모드로 변경
SQL> alter database maddog archivelog;

자동 아카이빙 활성화
SQL> alter system archive log start;	
SQL> alter system set log_archive_start=true scope=spfile; (오라클 재시작시 반영되도록 함)

online backup(archive log mode)

더보기

online backup(archive log mode)

작성자: 강명규
OS: Linux 2.4.10
Oracle: Oracle 8.1.7 EE

complete recovery를 보장하는 online backup(hot backup)을 하는 방법을 설명한다.
이 백업은 DB의 downtime을 허용하지 못하는 환경에서 사용된다.
처음의 백업엔 offline backup과 병용하여 사용하기를 권하고 있다.

1.
svrmgrl에서 'archive log list' 하여 'Oldest online log sequence' 의 값을 파악

SVRMGR> archive log list
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /u01/app/oracle/admin/dev2/arch
Oldest online log sequence     1044
Next log sequence to archive   1046
Current log sequence           1046
SVRMGR>



2.
백업할 tablespace목록, 각 tablespace에 할당된 datafile을 파악하기 위해 다음 질의를 실행

SVRMGR> select t.name, d.name from v$tablespace t, v$datafile d where t.ts# = d.ts#;
NAME                           NAME
------------------------------ --------------------------------------------------------------------------------
SYSTEM                         /u01/app/oracle/oradata/dev2/system01.dbf
TOOLS                          /u01/app/oracle/oradata/dev2/tools01.dbf
RBS                            /u01/app/oracle/oradata/dev2/rbs01.dbf
TEMP                           /u01/app/oracle/oradata/dev2/temp01.dbf
USERS                          /u01/app/oracle/oradata/dev2/users01.dbf
INDX                           /u01/app/oracle/oradata/dev2/indx01.dbf
TS_TEST                        /u01/app/oracle/oradata/dev2/ts_test01.dbf
TS_TEST                        /u01/app/oracle/oradata/dev2/ts_test02.dbf



3.
각각의 테이블스페이스를 백업모드로 변경하면서, tablespace별로 속한 데이터파일을 백업(복사)한다.
svrmgrl에서 'alter tablespace 테이블스페이스명 begin backup' 실행
이는 데이터파일 헤더를 동결(checkpoint기록을 중지)하여 테이블스페이스를 백업 준비상태로 둔다.
해당 테이블스페이스 백업이 완료되었다면, 'alter tablespace 테이블스페이스명 end backup' 실행하여
테이블스페이스가 사용될 수 있도록 변경한다.

SVRMGR> alter tablespace ts_test begin backup;
Statement processed.
SVRMGR> !cp /u01/app/oracle/oradata/dev2/ts_test01.dbf /backup/oracle/
SVRMGR> !cp /u01/app/oracle/oradata/dev2/ts_test02.dbf /backup/oracle/
SVRMGR> alter tablespace ts_test end backup;

나머지 테이블스페이스들도 위의 과정대로 실행한다.

SVRMGR> @tablespace_backup

[tablespace_backup.sql]
alter tablespace SYSTEM begin backup;
!cp /u01/app/oracle/oradata/dev2/system01.dbf /backup/oracle/
alter tablespace SYSTEM end backup;

alter tablespace TOOLS begin backup;
!cp /u01/app/oracle/oradata/dev2/tools01.dbf /backup/oracle/
alter tablespace TOOLS end backup;

alter tablespace RBS begin backup;
!cp /u01/app/oracle/oradata/dev2/rbs01.dbf /backup/oracle/
alter tablespace RBS end backup;

alter tablespace TEMP begin backup;
!cp /u01/app/oracle/oradata/dev2/temp01.dbf /backup/oracle/
alter tablespace TEMP end backup;

alter tablespace USERS begin backup;
!cp /u01/app/oracle/oradata/dev2/users01.dbf /backup/oracle/
alter tablespace USERS end backup;

alter tablespace INDX begin backup;
!cp /u01/app/oracle/oradata/dev2/indx01.dbf /backup/oracle/
alter tablespace INDX end backup;


* 테이블스페이스의 backup모드를 보려면 v$backup을 조회하면 된다.
status가 active로 되어 있으면 해당 테이블스페이스가 begin backup모드상태임을 의미한다.
SVRMGR> select t.name, d.name, d.file# 
     2> from  v$tablespace t, v$datafile d 
     3> where 
     4> t.ts# = d.ts#
     5> and
     6> t.name = 'TS_TEST';
NAME                           NAME                                          FILE#     
------------------------------ --------------------------------------------- ----------
TS_TEST                        /u01/app/oracle/oradata/dev2/ts_test01.dbf            29
TS_TEST                        /u01/app/oracle/oradata/dev2/ts_test02.dbf            30
2 rows selected.
SVRMGR> select * from v$backup where file# in (29,30);
FILE#      STATUS             CHANGE#    TIME     
---------- ------------------ ---------- ---------
        29 NOT ACTIVE             230427 19-DEC-01
        30 NOT ACTIVE             230427 19-DEC-01
2 rows selected.
SVRMGR> alter tablespace ts_test begin backup;
Statement processed.
SVRMGR> select * from v$backup where file# in (29,30);
FILE#      STATUS             CHANGE#    TIME     
---------- ------------------ ---------- ---------
        29 ACTIVE                 230498 19-DEC-01
        30 ACTIVE                 230498 19-DEC-01
2 rows selected.
SVRMGR> alter tablespace ts_test end backup;
Statement processed.
SVRMGR> select * from v$backup where file# in (29,30);
FILE#      STATUS             CHANGE#    TIME     
---------- ------------------ ---------- ---------
        29 NOT ACTIVE             230498 19-DEC-01
        30 NOT ACTIVE             230498 19-DEC-01
2 rows selected.




4.
svrmgrl에서 archive log list를 수행하여 'Current log sequence' 값을 파악

SVRMGR> archive log list
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /u01/app/oracle/admin/dev2/arch
Oldest online log sequence     1044
Next log sequence to archive   1046
Current log sequence           1046


5.
오라클이 현재 redo로그에 대한 archive를 생성하도록 하고,
위에서 구한 Oldest online log sequence인 1044에서 바로 위에서 구한 Current log sequence까지의
아카이브로그를 백업한다.

컨트롤파일 헤더를 갱신하기 위해 log switch를 실시한다.
SVRMGR> alter system switch logfile;
Statement processed.

SVRMGR> archive log list
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /u01/app/oracle/admin/dev2/arch
Oldest online log sequence     1045
Next log sequence to archive   1047
Current log sequence           1047

[oracle@dev2 arch]$ pwd
/u01/app/oracle/admin/dev2/arch
[oracle@dev2 arch]$ ls
arch_1_1000.arc  arch_1_1007.arc  arch_1_1014.arc  arch_1_1021.arc  arch_1_1028.arc  arch_1_1035.arc  arch_1_1042.arc
arch_1_1001.arc  arch_1_1008.arc  arch_1_1015.arc  arch_1_1022.arc  arch_1_1029.arc  arch_1_1036.arc  arch_1_1043.arc
arch_1_1002.arc  arch_1_1009.arc  arch_1_1016.arc  arch_1_1023.arc  arch_1_1030.arc  arch_1_1037.arc  arch_1_1044.arc
arch_1_1003.arc  arch_1_1010.arc  arch_1_1017.arc  arch_1_1024.arc  arch_1_1031.arc  arch_1_1038.arc  arch_1_1045.arc
arch_1_1004.arc  arch_1_1011.arc  arch_1_1018.arc  arch_1_1025.arc  arch_1_1032.arc  arch_1_1039.arc  arch_1_1046.arc
arch_1_1005.arc  arch_1_1012.arc  arch_1_1019.arc  arch_1_1026.arc  arch_1_1033.arc  arch_1_1040.arc
arch_1_1006.arc  arch_1_1013.arc  arch_1_1020.arc  arch_1_1027.arc  arch_1_1034.arc  arch_1_1041.arc

[oracle@dev2 arch]$ cp arch_1_1044.arc /backup/oracle
[oracle@dev2 arch]$ cp arch_1_1045.arc /backup/oracle 
[oracle@dev2 arch]$ cp arch_1_1046.arc /backup/oracle 


백업받은 아카이브로그 이외의 로그는 삭제한다.
SCN이 순서대로 부여되므로 1044이전의 SCN을 가지는 로그들을 삭제해준다.
모든 archive log를 삭제해도 상관없다.

SVRMGR> select sequence#, archived, status from v$log;
SEQUENCE#  ARC STATUS          
---------- --- ----------------
      1045 YES INACTIVE        
      1046 YES INACTIVE        
      1047 NO  CURRENT         
3 rows selected.

[oracle@dev2 arch]$ rm arch_1_10[0,1,2,3]* 
[oracle@dev2 arch]$ ls -l
total 2791
-rw-r-----    1 oracle   oinstall   512512 Dec 18 17:10 arch_1_1040.arc
-rw-r-----    1 oracle   oinstall   512512 Dec 18 17:10 arch_1_1041.arc
-rw-r-----    1 oracle   oinstall   512512 Dec 18 17:10 arch_1_1042.arc
-rw-r-----    1 oracle   oinstall   512512 Dec 18 17:10 arch_1_1043.arc
-rw-r-----    1 oracle   oinstall   512512 Dec 18 20:33 arch_1_1044.arc
-rw-r-----    1 oracle   oinstall   230912 Dec 19 12:26 arch_1_1045.arc
-rw-r-----    1 oracle   oinstall    44032 Dec 19 13:55 arch_1_1046.arc
[oracle@dev2 arch]$ rm arch_1_1040.arc arch_1_1041.arc arch_1_1042.arc arch_1_1043.arc 
[oracle@dev2 arch]$ ls -l
total 775
-rw-r-----    1 oracle   oinstall   512512 Dec 18 20:33 arch_1_1044.arc
-rw-r-----    1 oracle   oinstall   230912 Dec 19 12:26 arch_1_1045.arc
-rw-r-----    1 oracle   oinstall    44032 Dec 19 13:55 arch_1_1046.arc


6. 컨트롤 파일을 백업

SVRMGR> select * from v$controlfile;                         
STATUS  NAME                                                                            
------- --------------------------------------------------------------------------------
        /u01/app/oracle/oradata/dev2/control01.ctl                                      
        /u02/app/oracle/oradata/dev2/control02.ctl                                      
2 rows selected.
SVRMGR> alter database backup controlfile to '/backup/oracle/control_20011219.ctl';
Statement processed.

% 컨트롤파일을 스크립트로 형식으로 백업하려면 위 문장대신 아래와 같이 한다.
init.ora의 background_dump_dest에 지정한 위치에 저장된다.

alter database backup conrolfile to trace

백업디렉토리인 /bakup/oracle에는 다음과 같이 백업된 파일들이 있다.
이 디렉토리에 있는 파일들을 테이프등으로 이동시켜 보관한다.
//=========================================================
offline 백업/복구 
 
논리적 백업 - export/import유틸리티 사용
       오라클데이터베이스에서의 관점 : 오라클 자체적으로 백업을 처리
       읽기일관성을 보장하기 위해 보통 alter system enable restricted session을 수행후 실행
       장점: 다른 백업전략보다 손쉽게 할 수 있음. 
             DB online상태에서 수행가능
             변경사항이 거의 없거나, read only database에 적당하다
             (dataware house, DSS: Decision Support System)
       단점: 읽기일관성을 보장하지 못함. 
             대개 사용자실수(테이블drop..)에서 복구옵션으로 사용됨
             백업이 수행된 시점까지만 복구가능.
      

      
물리적 백업 - offline(cold)백업 
      OS에서의 관점 : 오라클 자체에서 백업이 다 처리되지 못하고, OS상의 복사 명령등이 수행됨
      오라클 shutdown후 datafile, redo log file, control file, parameter
      file등을 OS의 복사명령으로 수행하여 백업
      백업받을 파일들의 목록은 v$datafile, v$logfile, v$controlfile에서 구할 수 있다.
      장점: 읽기 일관성이 보장됨
      단점: 오라클 shutdown필요
            백업이 수행된 시점까지만 복구가능
      

      
물리적 + 논리적 - online백업
      말그대로 데이터베이스가 online상태에서 백업함.
      이 기능을 사용하기 위해선 archive모드를 사용해야 함
      보통 tablespace단위로 백업. 따라서 백업중인 tablespace를 제외한
      다른 tablespace는 사용자들에게 가용한 상태로 있음.
      tablespace단위로 백업할 경우 v$tablespace에서 백업할 tablespace의 목록을 구할 수 있다.
      control file, archived log파일도 같이 백업해야 한다.

      alter tablespace 테이블스페이스명 begin backup;
        OS상에서 테이블스페이스를 백업
      alter tablespace 테이블스페이스명 end backup;
      모든 테이블스페이스에 대해 위의 명령을 차례로 수행하여 백업 
      
      장점: DB 온라인상태에서 수행
            읽기일관성 보장
            백업중에도 db사용가능.
      단점: 다른 백업에 비해 복잡
            아카이브로그(디스크에 있는 online redo log의 복사본을 뜨는 것) 모드로 운영해야 함
  
      복구는 2단계로 이루어진다.
       백업이 실시된 시점까지 백업본을 적용
       장애가 발생한 시점까지 archive redo log 적용
  
  * 권장되는 백업: cold백업 + archivelog log 병용
  

  
  
RMAN백업
  DB의 online or offline일때, rman을 사용하여 백업
  장점: 사용되는 공간만 백업수행
        tablespace를 백업모드로 할 필요가 없으므로 redo의 오버헤드를 감소시킨다.
        24시간 가용성을 제공하고 완벽한(complete) 복구을 보장한다.
        사용자가 지정한 시간(point-in-time recovery : time, scn, cancel)까지 복구를 지원
    
offline백업(cold백업) 
1. DB를 shutdown normal 혹은 shutdown immediate로 닫는다.
   만일, shutdown immediate로 DB가 셧다운이 안될때는 다음과 같이 한다.
   
   alter system checkpoint;
   shutdown abort;
   startup restrict;
   shutdown immediate;
   
2. OS의 복사명령으로 datafile, redo log파일, control파일, parameter파일(init.ora), 패스워드파일(orapwSID)
   을 백업한다.

3. 백업이 끝났으면(위의 2번과정을 다 수행했다면), DB를 startup해서 사용한다.


복구(오프라인복구) 
(Offline백업에 대한 복구는 장애가 발생한 시점까지가 아니라, 가장 최근의 백업시점까지만 복구가능하다 - 당연)

동일한 디스크에 위치한 데이터파일 복구

1. DB를 shutdown abort로 닫는다.
2. 백업해두었던 datafile, redo log파일, control파일, parameter파일(init.ora), 패스워드파일(orapwSID)
   들을 현재의 DB데이터파일들이 위치한 곳으로 이동
3. startup mount수행
4. alter database open resetlos수행


상이한 디스크에 위치한 데이터파일 복구
만일 디스크가 교체될 수 없는 경우, 파일들을 다른 디스크로 이동시켜 복구한다.

1. DB를 shutdown abort로 닫는다.
2. 백업해두었던 datafile, redo log파일, control파일, parameter파일(init.ora), 패스워드파일(orapwSID)
   들을 다른 디스크로 이동
3. 패러미터파일에서 control_files패러미터를 수정
4. startup mount exclusive수행
5. 새로운 디스크에 위치한 데이터파일들의 위치를 control파일에 갱신
	alter database maddog
	rename file '/u01/oracle/data/data01.dbf' to '/u02/oracle/data/data01.dbf'
6. DB백업(형식적인 절차)
7. alter database open resetlogs수행

full export and import실습

더보기

full export and import실습

작성자  : 강명규
OS      : LINUX kernel 2.4.18(x86)
ORACLE  : 8i(8.1.7) EE

메모리: 160MB
CPU   : Celeron (Mendocino) 400

ORACLE_BASE: /u01/app/oracle
ORACLE_HOME: /u01/app/oracle/product/8.17
ORACLE_SID : db


tablespace내 free space의 fragmentation을 제거하기 위한 방법으로
full export -> DB recreate -> full import의 방법이 많이 사용된다.

1. Do a full database export (FULL=Y) to back up the entire database.
2. Shut down Oracle after all users are logged off.
3. Delete the database. See your Oracle operating system-specific documentation for information on how to delete a database.
4. Re-create the database using the CREATE DATABASE command.
5. Do a full database import (FULL=Y) to restore the entire database.



[실습]

1. Do a full database export (FULL=Y) to back up the entire database.

[root@ns /backup]# exp userid=system/xxxxxx \
> file=/backup/full_20020523.dmp \
> log=/backup/full_20020523.log \
> full=y inctype=complete

Export: Release 8.1.7.0.1 - Production on Thu May 23 14:07:37 2002

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


Connected to: Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production
Export done in KO16KSC5601 character set and US7ASCII NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. . exporting table                    DEF$_AQCALL          0 rows exported
. . exporting table                   DEF$_AQERROR          0 rows exported
. . exporting table                  DEF$_CALLDEST          0 rows exported
. . exporting table               DEF$_DEFAULTDEST          0 rows exported
. . exporting table               DEF$_DESTINATION          0 rows exported
. . exporting table                     DEF$_ERROR          0 rows exported
. . exporting table                       DEF$_LOB          0 rows exported
. . exporting table                    DEF$_ORIGIN          0 rows exported
. . exporting table                DEF$_PROPAGATOR          0 rows exported
. . exporting table       DEF$_PUSHED_TRANSACTIONS          0 rows exported
. . exporting table                  DEF$_TEMP$LOB          0 rows exported
. . exporting table             QUEST_COM_PRODUCTS          2 rows exported
. . exporting table     QUEST_COM_PRODUCTS_USED_BY          0 rows exported
. . exporting table        QUEST_COM_PRODUCT_PRIVS          0 rows exported
. . exporting table                QUEST_COM_USERS          0 rows exported
. . exporting table      QUEST_COM_USER_PRIVILEGES          0 rows exported
. . exporting table QUEST_SL_COLLECTION_DEFINITION          0 rows exported
. . exporting table  QUEST_SL_COLLECTION_DEF_REPOS          0 rows exported
. . exporting table QUEST_SL_COLLECTION_REPOSITORY          0 rows exported
. . exporting table                QUEST_SL_ERRORS          0 rows exported
. . exporting table               QUEST_SL_EXPLAIN          0 rows exported
. . exporting table          QUEST_SL_EXPLAIN_PICK          0 rows exported
. . exporting table     QUEST_SL_QUERY_DEFINITIONS          0 rows exported
. . exporting table  QUEST_SL_QUERY_DEF_REPOSITORY          0 rows exported
. . exporting table    QUEST_SL_REPOSITORY_EXPLAIN          0 rows exported
. . exporting table    QUEST_SL_REPOSITORY_SQLAREA          0 rows exported
. . exporting table    QUEST_SL_REPOSITORY_SQLTEXT          0 rows exported
. . exporting table QUEST_SL_REPOSITORY_STATISTICS          0 rows exported
. . exporting table QUEST_SL_REPOSITORY_TRANS_INFO          0 rows exported
. . exporting table     QUEST_SL_REPOS_BIND_VALUES          0 rows exported
. . exporting table     QUEST_SL_REPOS_LAB_DETAILS          0 rows exported
. . exporting table    QUEST_SL_REPOS_PICK_DETAILS          0 rows exported
. . exporting table            QUEST_SL_REPOS_ROOT          0 rows exported
. . exporting table     QUEST_SL_REPOS_SGA_DETAILS          0 rows exported
. . exporting table  QUEST_SL_REPOS_SGA_STATISTICS          0 rows exported
. . exporting table               QUEST_SL_SQLAREA          0 rows exported
. . exporting table               QUEST_SL_SQLTEXT          0 rows exported
. . exporting table                  QUEST_SL_USER          1 rows exported
. . exporting table        SQLPLUS_PRODUCT_PROFILE          0 rows exported
. about to export OUTLN's tables via Conventional Path ...
. . exporting table                            OL$          0 rows exported
. . exporting table                       OL$HINTS          0 rows exported
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. . exporting table                           DEPT          0 rows exported
. . exporting table                        DM_TIME          0 rows exported
. . exporting table                          HITEL      15786 rows exported
. . exporting table                         거래처        166 rows exported
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting statistics
Export terminated successfully without warnings.
[root@ns /backup]# ls -lh /backup디렉토리에 exp백업파일을 두었다.
total 78M
-rw-r--r--    1 root     root          431 Mar 18 01:29 apache_mysql_oracle_zend.txt
-rw-r--r--    1 root     root         174k Oct 20  2001 busansms.tgz
-rw-r--r--    1 root     root          35M May 19 04:22 dbakorea-20020519.tgz
-rw-r--r--    1 root     root          34M May 16 18:21 dbakorea20020516.tgz
-rw-r--r--    1 root     root         3.8M May 11 00:49 full_20020511.dmp
-rw-r--r--    1 root     root         3.2k May 11 00:49 full_20020511.log
-rw-r--r--    1 root     root         3.9M May 23 14:08 full_20020523.dmp
-rw-r--r--    1 root     root         5.4k May 23 14:08 full_20020523.log
-rw-r--r--    1 root     root          35k Mar 17 22:22 httpd.conf
[root@ns /backup]# df -h 시스템에 남은 용량을 확인하자.(쩝..본인의 서버는 쬐금 열악하다.)
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda2             3.8G  2.9G  624M  83% /
[root@ns /backup]# 



2. Shut down Oracle after all users are logged off.(and 기존 DB의 백업)

testDB겸 devDB지만(중요한 데이터가 없다는 뜻이겠다), 정석을 따라 일단 기존의 DB를 백업해 둔다.
중요한 작업이므로 가장 쉬운 백업/복구를 지원하는 cold backup으로 하겠다.
사실 위에서 exp를 했으므로 해줄 필요가 없지만, 괜히 잘못되면 복구시간 장난 아니게 늘어나니
cold백업을 해주기를 권하겠다. archive log를 사용할 경우 LOG_ARCHIVE_DEST를 고려해야 겠지만,
cold백업하므로 상관없다.
테스트없이 prodDB로 하는 사람이 있는데, 절대 처음부터 prodDB를 가지고 장난하지 말기 바란다.

[root@ns /backup]# l /u01/app/oracle/oradata/db
total 302824
-rw-r-----    1 oracle   oinstall  4296704 May 23 14:17 control01.ctl
-rw-r-----    1 oracle   oinstall  4296704 May 23 14:17 control02.ctl
-rw-r-----    1 oracle   oinstall 10489856 May 23 14:08 indx01.dbf
-rw-r-----    1 oracle   oinstall 52432896 May 23 14:08 rbs01.dbf
-rw-r-----    1 oracle   oinstall   512512 May 23 14:08 redo01.log
-rw-r-----    1 oracle   oinstall   512512 May 23 14:08 redo02.log
-rw-r-----    1 oracle   oinstall   512512 May 23 14:08 redo03.log
-rw-r-----    1 oracle   oinstall 104861696 May 23 14:08 system01.dbf
-rw-r-----    1 oracle   oinstall 52432896 May 23 14:08 temp01.dbf
-rw-r-----    1 oracle   oinstall 26087424 May 23 14:08 tools01.dbf
-rw-r-----    1 oracle   oinstall 52432896 May 23 14:08 users01.dbf
[root@ns /backup]# l $ORACLE_HOME/dbs
total 22
-rw-r--r--    1 oracle   oinstall     8385 Oct 22  1999 init.ora
lrwxrwxrwx    1 oracle   oinstall       41 Apr 28 13:51 initdb.ora -> /u01/app/oracle/admin/db/pfile/initdb.ora
-rw-r--r--    1 oracle   oinstall     9219 Oct 22  1999 initdw.ora
-rw-rw----    1 oracle   oinstall       24 May 22 14:29 lkDB
-rwSr-----    1 oracle   oinstall     1536 May 11 01:28 orapwdb

[root@ns /backup]# su - oracle
[oracle@ns 8.1.7]$ svrmgrl

Oracle Server Manager Release 3.1.7.0.0 - Production

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

Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SVRMGR> connect internal
Connected.
SVRMGR> shutdown
Database closed.
Database dismounted.
ORACLE instance shut down.
SVRMGR> quit
Server Manager complete.
[oracle@ns 8.1.7]$ exit
logout
[root@ns /backup]# tar cvzf db_os_cold_20020523.tgz /u01/app/oracle/oradata/db $ORACLE_HOME/dbs
tar: Removing leading `/' from archive names
u01/app/oracle/oradata/db/
u01/app/oracle/oradata/db/control01.ctl
u01/app/oracle/oradata/db/control02.ctl
u01/app/oracle/oradata/db/indx01.dbf
u01/app/oracle/oradata/db/rbs01.dbf
u01/app/oracle/oradata/db/redo01.log
u01/app/oracle/oradata/db/redo02.log
u01/app/oracle/oradata/db/redo03.log
u01/app/oracle/oradata/db/system01.dbf
u01/app/oracle/oradata/db/temp01.dbf
u01/app/oracle/oradata/db/tools01.dbf
u01/app/oracle/oradata/db/users01.dbf
u01/app/oracle/product/8.1.7/dbs/
u01/app/oracle/product/8.1.7/dbs/init.ora
u01/app/oracle/product/8.1.7/dbs/initdw.ora
u01/app/oracle/product/8.1.7/dbs/orapwdb
u01/app/oracle/product/8.1.7/dbs/initdb.ora
u01/app/oracle/product/8.1.7/dbs/lkDB
[root@ns /backup]# l
total 102534
-rw-r--r--    1 root     root          431 Mar 18 01:29 apache_mysql_oracle_zend.txt
-rw-r--r--    1 root     root       177871 Oct 20  2001 busansms.tgz
-rw-r--r--    1 root     root     23474576 May 23 14:32 db_os_cold_20020523.tgz
-rw-r--r--    1 root     root     37055913 May 19 04:22 dbakorea-20020519.tgz
-rw-r--r--    1 root     root     35760091 May 16 18:21 dbakorea20020516.tgz
-rw-r--r--    1 root     root      3932160 May 11 00:49 full_20020511.dmp
-rw-r--r--    1 root     root         3261 May 11 00:49 full_20020511.log
-rw-r--r--    1 root     root      4128768 May 23 14:08 full_20020523.dmp
-rw-r--r--    1 root     root         5541 May 23 14:08 full_20020523.log
-rw-r--r--    1 root     root        35697 Mar 17 22:22 httpd.conf
[root@ns /backup]# tar tvzfw db_os_cold_20020523.tgz 
drwxr-xr-x oracle/oinstall   0 2002-05-11 01:25:05 u01/app/oracle/oradata/db/
-rw-r----- oracle/oinstall 4296704 2002-05-23 14:28:00 u01/app/oracle/oradata/db/control01.ctl
-rw-r----- oracle/oinstall 4296704 2002-05-23 14:28:00 u01/app/oracle/oradata/db/control02.ctl
-rw-r----- oracle/oinstall 10489856 2002-05-23 14:28:00 u01/app/oracle/oradata/db/indx01.dbf
-rw-r----- oracle/oinstall 52432896 2002-05-23 14:28:00 u01/app/oracle/oradata/db/rbs01.dbf
-rw-r----- oracle/oinstall   512512 2002-05-23 14:28:00 u01/app/oracle/oradata/db/redo01.log
-rw-r----- oracle/oinstall   512512 2002-05-23 14:08:13 u01/app/oracle/oradata/db/redo02.log
-rw-r----- oracle/oinstall   512512 2002-05-23 14:08:20 u01/app/oracle/oradata/db/redo03.log
-rw-r----- oracle/oinstall 104861696 2002-05-23 14:28:00 u01/app/oracle/oradata/db/system01.dbf
-rw-r----- oracle/oinstall  52432896 2002-05-23 14:28:00 u01/app/oracle/oradata/db/temp01.dbf
-rw-r----- oracle/oinstall  26087424 2002-05-23 14:28:00 u01/app/oracle/oradata/db/tools01.dbf
-rw-r----- oracle/oinstall  52432896 2002-05-23 14:28:00 u01/app/oracle/oradata/db/users01.dbf
drwxr-xr-x oracle/oinstall         0 2002-05-22 14:29:15 u01/app/oracle/product/8.1.7/dbs/
-rw-r--r-- oracle/oinstall      8385 1999-10-22 18:39:44 u01/app/oracle/product/8.1.7/dbs/init.ora
-rw-r--r-- oracle/oinstall      9219 1999-10-22 18:39:46 u01/app/oracle/product/8.1.7/dbs/initdw.ora
-rwSr----- oracle/oinstall      1536 2002-05-11 01:28:25 u01/app/oracle/product/8.1.7/dbs/orapwdb
lrwxrwxrwx oracle/oinstall         0 2002-04-28 13:51:59 u01/app/oracle/product/8.1.7/dbs/initdb.ora -> /u01/app/oracle/admin/db/pfile/initdb.ora
-rw-rw---- oracle/oinstall        24 2002-05-22 14:29:47 u01/app/oracle/product/8.1.7/dbs/lkDB
[root@ns /backup]#



3. Delete the database.

$ORACLE_HOME/dbs를 그대로 두고(init.ora가 있으므로), /u01/app/oracle/oradata/db의 모든 것들을 지워준다.
/u01/app/oracle/admin/db/중 pfile에는 init.ora파일이 있으므로  /u01/app/oracle/admin/db/를 지우고
싶다면  /u01/app/oracle/admin/db/pfile디렉토리는 놔두거나 init.ora을 $ORACLE_HOME/dbs에 옮긴뒤 지우도록한다.
나는 그냥 두기로 했다.

[root@ns /backup]# rm -fr /u01/app/oracle/oradata/db/*
[root@ns /backup]# l /u01/app/oracle/oradata
total 0



4. Re-create the database using the CREATE DATABASE command.
db생성은 oracle유저에서 합시다.

[root@ns /backup]# su - oracle

/u01/app/oracle/product/8.1.7/dbs/initdb.ora의 패러미터를 다음과 같이 설정
remote_login_passwordfile = none

[oracle@ns 8.1.7]$ svrmgrl

Oracle Server Manager Release 3.1.7.0.0 - Production

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

Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SVRMGR> spool /u01/app/oracle/admin/db/create/crdb_20020523.log
SVRMGR> connect internal
Connected.
SVRMGR> startup nomount pfile = "/u01/app/oracle/admin/db/pfile/initdb.ora"
ORACLE instance started.
Total System Global Area                         15868064 bytes
Fixed Size                                          73888 bytes
Variable Size                                     7233536 bytes
Database Buffers                                  8388608 bytes
Redo Buffers                                       172032 bytes
SVRMGR> create database "db"
     2> maxdatafiles 254   
     3> maxinstances 8
     4> maxlogfiles 32
     5> character set KO16KSC5601
     6> national character set US7ASCII
     7> datafile '/u01/app/oracle/oradata/db/system01.dbf' SIZE 150M AUTOEXTEND ON NEXT 10240K
     8> logfile 
     9> '/u01/app/oracle/oradata/db/redo01.log' SIZE 500K, 
    10> '/u01/app/oracle/oradata/db/redo02.log' SIZE 500K,
    11> '/u01/app/oracle/oradata/db/redo03.log' SIZE 500K;

Statement processed.
SVRMGR> @/u01/app/oracle/product/8.1.7/rdbms/admin/catalog.sql;

SVRMGR> ALTER TABLESPACE SYSTEM
     2> DEFAULT STORAGE ( INITIAL 64K NEXT 64K MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 50);
     3> ALTER TABLESPACE SYSTEM
     4> MINIMUM EXTENT 64K;
Statement processed.
SVRMGR> CREATE TABLESPACE RBS DATAFILE '/u01/app/oracle/oradata/db/rbs01.dbf' SIZE 50M REUSE
     2>  AUTOEXTEND ON NEXT 5120K
     3> MINIMUM EXTENT 512K
     4> DEFAULT STORAGE ( INITIAL 512K NEXT 512K MINEXTENTS 8 MAXEXTENTS 4096);
Statement processed.
SVRMGR> CREATE TABLESPACE TOOLS DATAFILE '/u01/app/oracle/oradata/db/tools01.dbf' SIZE 8M REUSE
     2>  AUTOEXTEND ON NEXT 320K
     3> MINIMUM EXTENT 32K
     4> DEFAULT STORAGE ( INITIAL 32K NEXT 32K MINEXTENTS 1 MAXEXTENTS 4096 PCTINCREASE 0);
Statement processed.
SVRMGR> CREATE TABLESPACE TEMP DATAFILE '/u01/app/oracle/oradata/db/temp01.dbf' SIZE 50M REUSE
     2>  AUTOEXTEND ON NEXT 640K
     3> MINIMUM EXTENT 64K
     4> DEFAULT STORAGE ( INITIAL 64K NEXT 64K MINEXTENTS 1 MAXEXTENTS UNLIMITED PCTINCREASE 0) TEMPORARY;
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS0 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS1 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS2 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS3 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS4 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS5 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> CREATE PUBLIC ROLLBACK SEGMENT RBS6 TABLESPACE RBS STORAGE ( OPTIMAL 4096K );
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS0" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS1" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS2" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS3" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS4" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS5" ONLINE;
Statement processed.
SVRMGR> ALTER ROLLBACK SEGMENT "RBS6" ONLINE;
Statement processed.
SVRMGR> alter user sys temporary tablespace TEMP;
Statement processed.
SVRMGR> alter user system temporary tablespace TEMP;
Statement processed.
SVRMGR> alter user system default tablespace tools;
Statement processed.
SVRMGR> @/u01/app/oracle/product/8.1.7/rdbms/admin/catproc.sql
SVRMGR> @/u01/app/oracle/product/8.1.7/rdbms/admin/caths.sql  
SVRMGR> @/u01/app/oracle/product/8.1.7/rdbms/admin/otrcsvr.sql
SVRMGR> connect system/manager
Connected.
SVRMGR> @/u01/app/oracle/product/8.1.7/sqlplus/admin/pupbld.sql
SVRMGR> quit
Server Manager complete.
[oracle@ns db]$ 



5. Do a full database import (FULL=Y) to restore the entire database.

[root@ns /backup]# imp userid=system/manager \
> file=/backup/full_20020523.dmp \
> log=/backup/full_imp_20020523.log \
> full=y \
> ignore=y

Import: Release 8.1.7.0.1 - Production on Thu May 23 17:21:59 2002

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


Connected to: Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

Export file created by EXPORT:V08.01.07 via conventional path
import done in KO16KSC5601 character set and US7ASCII NCHAR character set
. importing KANG's objects into KANG
. importing SYS's objects into SYS
. importing SYSTEM's objects into SYSTEM
. importing SYS's objects into SYS
. importing SYSTEM's objects into SYSTEM
. . importing table                  "DEF$_AQCALL"          0 rows imported
. . importing table                 "DEF$_AQERROR"          0 rows imported
. . importing table                "DEF$_CALLDEST"          0 rows imported
. . importing table             "DEF$_DEFAULTDEST"          0 rows imported
. . importing table             "DEF$_DESTINATION"          0 rows imported
. . importing table                   "DEF$_ERROR"          0 rows imported
. . importing table                     "DEF$_LOB"          0 rows imported
. . importing table                  "DEF$_ORIGIN"          0 rows imported
. . importing table              "DEF$_PROPAGATOR"          0 rows imported
. . importing table     "DEF$_PUSHED_TRANSACTIONS"          0 rows imported
. . importing table                "DEF$_TEMP$LOB"          0 rows imported
. . importing table           "QUEST_COM_PRODUCTS"          2 rows imported
. . importing table   "QUEST_COM_PRODUCTS_USED_BY"          0 rows imported
. . importing table      "QUEST_COM_PRODUCT_PRIVS"          0 rows imported
. . importing table              "QUEST_COM_USERS"          0 rows imported
. . importing table    "QUEST_COM_USER_PRIVILEGES"          0 rows imported
. . importing table "QUEST_SL_COLLECTION_DEFINITION"          0 rows imported
. . importing table "QUEST_SL_COLLECTION_DEF_REPOS"          0 rows imported
. . importing table "QUEST_SL_COLLECTION_REPOSITORY"          0 rows imported
. . importing table              "QUEST_SL_ERRORS"          0 rows imported
. . importing table             "QUEST_SL_EXPLAIN"          0 rows imported
. . importing table        "QUEST_SL_EXPLAIN_PICK"          0 rows imported
. . importing table   "QUEST_SL_QUERY_DEFINITIONS"          0 rows imported
. . importing table "QUEST_SL_QUERY_DEF_REPOSITORY"          0 rows imported
. . importing table  "QUEST_SL_REPOSITORY_EXPLAIN"          0 rows imported
. . importing table  "QUEST_SL_REPOSITORY_SQLAREA"          0 rows imported
. . importing table  "QUEST_SL_REPOSITORY_SQLTEXT"          0 rows imported
. . importing table "QUEST_SL_REPOSITORY_STATISTICS"          0 rows imported
. . importing table "QUEST_SL_REPOSITORY_TRANS_INFO"          0 rows imported
. . importing table   "QUEST_SL_REPOS_BIND_VALUES"          0 rows imported
. . importing table   "QUEST_SL_REPOS_LAB_DETAILS"          0 rows imported
. . importing table  "QUEST_SL_REPOS_PICK_DETAILS"          0 rows imported
. . importing table          "QUEST_SL_REPOS_ROOT"          0 rows imported
. . importing table   "QUEST_SL_REPOS_SGA_DETAILS"          0 rows imported
. . importing table "QUEST_SL_REPOS_SGA_STATISTICS"          0 rows imported
. . importing table             "QUEST_SL_SQLAREA"          0 rows imported
. . importing table             "QUEST_SL_SQLTEXT"          0 rows imported
. . importing table                "QUEST_SL_USER"          1 rows imported
. . importing table      "SQLPLUS_PRODUCT_PROFILE"          0 rows imported
. importing OUTLN's objects into OUTLN
. . importing table                          "OL$"          0 rows imported
. . importing table                     "OL$HINTS"          0 rows imported
. importing KANG's objects into KANG
. . importing table                         "DEPT"          0 rows imported
. . importing table                      "DM_TIME"          0 rows imported
. . importing table                        "HITEL"      15786 rows imported
. . importing table                       "거래처"        166 rows imported
. importing SYSTEM's objects into SYSTEM
. importing KANG's objects into KANG
. importing SYSTEM's objects into SYSTEM
. importing DBSNMP's objects into DBSNMP
. importing SYSTEM's objects into SYSTEM
. importing OUTLN's objects into OUTLN
. importing SYSTEM's objects into SYSTEM
. importing KANG's objects into KANG
. importing SYSTEM's objects into SYSTEM
About to enable constraints...
. importing KANG's objects into KANG
. importing SYSTEM's objects into SYSTEM
Import terminated successfully without warnings.
[root@ns /backup]#


import후엔 기존 백업받았던 DB의 환경이 되므로 system/manager와 같이 디폴트상태가 아님을
주의하기 바란다. 즉, 기존의 DB의 계정으로 연결하여 사용한다. 당연한 말이지만..

full DB export 사용

더보기

full DB export 사용

여기서는 full=y를 사용했을 경우만 생각해본다.
이는 DBA권한을 가진 사람이 모든 데이터베이스에 대해 백업을 실시할 때 사용한다.
full옵션을 사용할 수 있으려면 정확히 EXP_FULL_DATABASE 권한을 가져야한다.
export유틸리티를 사용하기 위해 catexp.sql이라는 유틸리티스크립트를 실행해야 하는데
이것은 catalog.sql이 실행되면서 부수적으로 실행되므로 그리 신경쓸 필요는 없다.
 
export는 논리적인 백업으로 완벽한 복구에 사용되기에는 무리이다.
많은(아주 많은 것 같다.) 사이트들이 백업수단으로 export를 사용하는 것 같다.
사용하기 쉬운 것과 짧은 시간에 할 수 있다는 것이 그 이유가 아닌가 생각된다.
개인적인 생각에는 export의 경우, 각 schema에 대한 백업수단(export시 owner옵션을 사용한 백업)으로서만 
사용하는 것이 좋을것 같다.

full=y를 사용할 경우 inctype으로 complete, cumulative, incremental 3가지가 사용될 수 있다. 
complete는 무조건 전체 데이터베이스를 백업.
cumulative는 complete이후 변경된 데이블에 대해서만 백업
incremental는 위 2가지 백업뒤 변경된 놈들에 대해 백업

cumulative는 incremental로 생성되는 파일수를 줄여주는 역활을 한다.
즉, 이전에 incremental백업을 2번한 상황에서 comulative백업을 하면 이전의 2개의 incremental백업은
cumulative백업으로 커버가 된다. 즉, 이전 2개의 incremental백업은 복구시 필요치 않고, cumulative백업
하나만 있으면 되는 것이다.

2주일간의 백업정책을 세운다면, 
처음 complete백업을 받는다.
일별로 incremental백업을 받는다.
하지만, 수요일, 일요일은 incremental백업대신 cumulative백업을 한다.
2주가 되는 일요일에 complete백업을 한다.

복구의 순서는, 
가장 최근의 complete백업한 것을 resotre한다.
가장 최근의 complete백업후에 발생한 cumulative백업들을 restore한다.
(cumulative백업이 없다면 incremental백업으로 대체)
위에서 행한 cumulative백업들중 가장 최근의 cumulative백업후의 incremental백업들을
가장 오래된 것부터 차례로 restore한다.

정리하면,
complete의 경우 주말에 한번 정도
incremental의 경우 날마다 
cumulative의 경우 주중에 한번(수요일정도)

오라클이 complete백업후의 변동된 사항을 어떻게 알수 있을까?
당연히 내부적인 테이블에 이런 정보를 저장하고 있다.
언제 complete, cumulative백업들이 발생했는가등등.. 문서하단에 자세히 설명하겠다.

[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=complete

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:35:28 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. . exporting table                    DEF$_AQCALL          0 rows exported
. . exporting table                   DEF$_AQERROR          0 rows exported
. . exporting table                  DEF$_CALLDEST          0 rows exported
. . exporting table               DEF$_DEFAULTDEST          0 rows exported
. . exporting table               DEF$_DESTINATION          0 rows exported
. . exporting table                     DEF$_ERROR          0 rows exported
. . exporting table                       DEF$_LOB          0 rows exported
. . exporting table                    DEF$_ORIGIN          0 rows exported
. . exporting table                DEF$_PROPAGATOR          0 rows exported
. . exporting table       DEF$_PUSHED_TRANSACTIONS          0 rows exported
. . exporting table                  DEF$_TEMP$LOB          0 rows exported
. . exporting table                           HELP        816 rows exported
. . exporting table        SQLPLUS_PRODUCT_PROFILE          0 rows exported
. about to export OUTLN's tables via Conventional Path ...
. . exporting table                            OL$          0 rows exported
. . exporting table                       OL$HINTS          0 rows exported
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. . exporting table                           TEST          1 rows exported
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting statistics
Export terminated successfully without warnings.

[kang@piruks kang]$ ls -l
total 155
-rw-rw-r--    1 kang     kang       155648 11월  2 15:37 expdat.dmp
drwxrwxr-x    4 kang     kang         1024 10월 27 13:02 public_html/
drwxrwxr-x    2 kang     kang         1024 10월 15 12:54 test/

complete로 백업후 바로 cumulative로 다시 실행해 봤다.
역시 변경사항이 없으니 .. 별 일은 하지 않는것 같다.
백업받을 파일을 지정하지 않으면 complete로 백업받은 파일을 덮어쓰니까 
다른 곳으로 미리 옮겨놓는 것이 좋을 것 같다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=cumulative

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:39:22 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.

파일의 크기가 줄었다.
[kang@piruks kang]$ ls -l                                               
total 27
-rw-rw-r--    1 kang     kang        24576 11월  2 15:42 expdat.dmp
drwxrwxr-x    4 kang     kang         1024 10월 27 13:02 public_html/
drwxrwxr-x    2 kang     kang         1024 10월 15 12:54 test/

역시 아무런 변경없이 incremental로 다시 실행해봤다. 
생각한대로 별 일은 하지 않는다. 파일크기도 cumulative와 같았다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=incremental

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:40:29 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.

[kang@piruks kang]$ ls -l                                                
total 27
-rw-rw-r--    1 kang     kang        24576 11월  2 15:43 expdat.dmp
drwxrwxr-x    4 kang     kang         1024 10월 27 13:02 public_html/
drwxrwxr-x    2 kang     kang         1024 10월 15 12:54 test/


음.. 데이터를 하나 넣어보고 다시 해보자
[kang@piruks kang]$ sqlplus kang/xxxxxx                              

SQL*Plus: Release 8.1.6.0.0 - Production on Thu Nov 2 15:46:34 2000

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SQL> insert into test values ('하하하', 29);

1 row created.

SQL> exit
Disconnected from Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

incremental로 다시 백업
물론 변경사항이 있으니 뭔가 할 거다.
test테이블에 대해 2개의 row를 백업받았다.
export는 row단위로 백업하는 것이 아니기때문에 이는 test라는 테이블전체를 백업받은 것이다.
다시 한번 말하는데 export는 변경된 테이블에 대해 백업을 실시한다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=incremental

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:48:11 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. . exporting table                           TEST          2 rows exported
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.
[kang@piruks kang]$ ls -l
total 27
-rw-rw-r--    1 kang     kang        24576 11월  2 15:48 expdat.dmp
drwxrwxr-x    4 kang     kang         1024 10월 27 13:02 public_html/
drwxrwxr-x    2 kang     kang         1024 10월 15 12:54 test/

이번에는 좀더 데이터를 많이 집어넣어 보자
[kang@piruks kang]$ sqlplus kang/xxxxxx

SQL*Plus: Release 8.1.6.0.0 - Production on Thu Nov 2 15:49:16 2000

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


Connected to:
Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production

SQL> insert into test values ('&a', 30);
Enter value for a: 슈퍼맨
old   1: insert into test values ('&a', 30)
new   1: insert into test values ('슈퍼?, 30)

1 row created.

SQL> /
Enter value for a: 배트맨
old   1: insert into test values ('&a', 30)
new   1: insert into test values ('배트?, 30)

1 row created.

SQL> /
Enter value for a: vicman
old   1: insert into test values ('&a', 30)
new   1: insert into test values ('vicman', 30)

1 row created.

SQL> quit
Disconnected from Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=incremental

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:50:24 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. . exporting table                           TEST          5 rows exported
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.

입력한 데이터가 별로 되지 않아 백업파일의 크기에 영향이 없다. 쩝..
[kang@piruks kang]$ ls -l
total 28
-rw-r--r--    1 kang     kang            5 11월  2 15:51 HantermLog.GDPo9B
-rw-rw-r--    1 kang     kang        24576 11월  2 15:50 expdat.dmp
drwxrwxr-x    4 kang     kang         1024 10월 27 13:02 public_html/
drwxrwxr-x    2 kang     kang         1024 10월 15 12:54 test/

incremental과 cumulative의 차이점이라고 발견할 수 있는 것은 한가지다.
cumulative가 incremental로 백업받은 것을 다시 백업할 수 있지만,
incremental백업은 cumulative로 백업받은 것을 다시 백업할 수 없다는 것이다.
음.. 중요한 사실인가? 밑에 cumulative와 incremental의 예를 보면 알 수 있을 것이다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=cumulative 

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:51:48 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. . exporting table                           TEST          5 rows exported
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.

cumulative백업후 데이터베이스에 아무런 변경없는 상태에서 incremental백업은 무의미하다.
즉 cumulative가 받은 백업데이터를 백업하지 못한다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=incremental

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:52:05 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
Export done in UTF8 character set and KO16KSC5601 NCHAR character set

About to export the entire database ...
. exporting tablespace definitions
. exporting profiles
. exporting user definitions
. exporting roles
. exporting resource costs
. exporting rollback segment definitions
. exporting database links
. exporting sequence numbers
. exporting directory aliases
. exporting context namespaces
. exporting foreign function library names
. exporting object type definitions
. exporting system procedural objects and actions
. exporting pre-schema procedural objects and actions
. exporting cluster definitions
. about to export SYSTEM's tables via Conventional Path ...
. about to export OUTLN's tables via Conventional Path ...
. about to export DBSNMP's tables via Conventional Path ...
. about to export TRACESVR's tables via Conventional Path ...
. about to export KANG's tables via Conventional Path ...
. exporting referential integrity constraints
. exporting synonyms
. exporting views
. exporting stored procedures
. exporting operators
. exporting indextypes
. exporting bitmap, functional and extensible indexes
. exporting posttables actions
. exporting triggers
. exporting snapshots
. exporting snapshot logs
. exporting job queues
. exporting refresh groups and children
. exporting dimensions
. exporting post-schema procedural objects and actions
. exporting user history table
. exporting default and system auditing options
. exporting information about dropped objects
. exporting statistics
Export terminated successfully without warnings.




일반사용자는 데이터베이스 full백업이 불가능하다.
[kang@piruks kang]$ exp userid=kang/xxxxxx full=y inctype=incremental

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:43:53 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
EXP-00023: must be a DBA to do Full Database export
(2)U(sers), or (3)T(ables): (2)U > 

EXP-00022: must be SYS or SYSTEM to do incremental export
EXP-00000: Export terminated unsuccessfully
[kang@piruks kang]$ 


full패러미터사용시 tables와 owner패러미터는 사용하지 못한다.
[kang@piruks kang]$ exp userid=system/xxxxxx full=y inctype=complete tables=kang.test

Export: Release 8.1.6.1.0 - Production on Thu Nov 2 15:45:55 2000

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


Connected to: Oracle8i Enterprise Edition Release 8.1.6.1.0 - Production
With the Partitioning option
JServer Release 8.1.6.0.0 - Production
EXP-00026: conflicting modes specified
EXP-00000: Export terminated unsuccessfully
[kang@piruks kang]$ 


incexp, incfil, incvid
sys계정에 보면, incexp, incfil, incvid테이블이 있다.
보통의 owner, table백업으로는 이 테이블들이 채워지지 않는다.
cumulative, incremental을 해야 이 놈들의  테이블이 채워진다.
백업을 하면 백업기록을 남겨야 incremental backup을 할 수 있는데 이 놈들이다.

incexp: export된 스키마들의 정보를 가짐(보통 무지하게 row가 많다)
incfil: incremental backup이 된 export파일들
incvid: 다음 export id를 가짐(즉, 지금 한게 id가 1이라면 다음은 2가 된다.)

exp userid=system/xxxx file=fullexp.dmp full=y inctype=complete
exp userid=system/xxxx file=cumexp.dmp full=y inctype=cumulative
exp userid=sys/xxxx file=incexp.dmp full=y inctype=incremental

이렇게 2번을 하고, DB 에서 조회

SQL> select * from incfil;

     EXPID EXPTYPE  EXPFILE                        EXPDATE   EXPUSER
---------- -------- ------------------------------ --------- ------------------------------
         1 X        fullexp.dmp                    12-JAN-01 SYSTEM
         2 C        cumexp.dmp                     12-JAN-01 SYSTEM
         3 I        incexp.dmp                     12-JAN-01 SYS

SQL> select * from incvid;

     EXPID
----------
         3


SQL> select * from incexp where rownum<5;

    OWNER# NAME                      TYPE# CTIME     ITIME          EXPID
---------- -------------------- ---------- --------- --------- ----------
         5 DEF$_AQCALL                   2 12-JAN-01 12-JAN-01          1
         5 DEF$_AQERROR                  2 12-JAN-01 12-JAN-01          1
         5 DEF$_CALLDEST                 2 12-JAN-01 12-JAN-01          1
         5 DEF$_DEFAULTDEST              2 12-JAN-01 12-JAN-01          1

//===========================================================
import, export사용(imp, exp) 
linux라는 사용자로 연결한다
SQL> connect linux/linux
연결되었습니다.
SQL> set pagesize 30

linux가 가진 테이블은 다음과 같다
SQL> select * from tab;
TNAME			       TABTYPE	CLUSTERID
------------------------------ ------- ----------
S_CUSTOMER		       TABLE
S_DEPT			       TABLE
S_EMP			       TABLE
S_IMAGE 		       TABLE
S_INVENTORY		       TABLE
S_ITEM			       TABLE
S_LONGTEXT		       TABLE
S_ORD			       TABLE
S_PRODUCT		       TABLE
S_REGION		       TABLE
S_TITLE 		       TABLE
S_WAREHOUSE		       TABLE
TEST			       TABLE
13 개의 행이 선택되었습니다.
SQL> quit
Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production에서 분리되었습니다.
[linux@localhost db]$ ls -l /usr/local/Oracle
total 2
drwxr-xr-x   3 oracle   dba          1024 Sep 22 13:23 app
drwxr-xr-x   3 oracle   dba          1024 Sep 22 13:26 oradata
[linux@localhost db]$ ls -l /usr/local/Oracle/oradata
total 1
drwxr-xr-x   2 oracle   dba          1024 Sep 22 13:34 kang
[linux@localhost db]$ ls -l /usr/local/Oracle/oradata/kang
total 131172
-rw-r-----   1 oracle   dba       1435648 Oct  5 23:46 control01.ctl
-rw-r-----   1 oracle   dba       1435648 Oct  5 23:46 control02.ctl
-rw-r-----   1 oracle   dba       1435648 Oct  5 23:46 control03.ctl
-rw-r-----   1 oracle   dba      15730688 Oct  5 23:44 rbs01.dbf
-rw-r-----   1 oracle   dba        512512 Oct  5 23:41 redokang01.log
-rw-r-----   1 oracle   dba        512512 Oct  5 23:42 redokang02.log
-rw-r-----   1 oracle   dba        512512 Oct  5 23:44 redokang03.log
-rw-r-----   1 oracle   dba      83888128 Oct  5 23:44 system01.dbf
-rw-r-----   1 oracle   dba       1050624 Oct  5 23:42 temp01.dbf
-rw-r-----   1 oracle   dba      26216448 Oct  5 23:42 tools01.dbf
-rw-r-----   1 oracle   dba       1050624 Oct  5 23:42 users01.dbf

linux의 테이블을 export한다. OCP에서는 이 툴을 이용하는 백업을 논리적(logical) 백업이라고 한다
그냥 명령인자없이 주면 interactive하게 진행할 수 있다.
이 경우 direct백업(특별한 경우가 아닌 이상, 이 방법으로 하면 속도가 빨라진다.)이 불가능하다(디폴트로 N)
[linux@localhost db]$ exp linux/linux
Export: Release 8.0.5.0.0 - Production on 화 Oct 5 23:46:43 1999
(c) Copyright 1998 Oracle Corporation.  All rights reserved.

연결할 곳: Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production
배열 인출 버퍼 크기 입력: 4096 >
엑스포트 파일: expdat.dmp > 그냥 엔터(디폴트 화일명은 expdat.dmp이다)

논리적 백업은 3가지가 있는데 아래에 있는 user, table과 아래에 나오지 않은 full백업이 있다
(full백업은 보통 dba만이 할 수 있다, 만일 백업만을 전담할 사용자를 둔다면, exp_full_database, imp_full_database 권한을 주면 된다.).
user는 사용자가 가진 스키마의 모든 것들을 export하는 것이고, table은 말 그대로 사용자의 지정된 table만을 export하는 것이다.
full은 전체 DB를 백업한다


(2)U(사용자), 또는 (3)T(테이블): (2)U > 여기서는 2을 선택했다
권한부여 엑스포트 (yes/no): yes > 그냥 엔터
테이블 데이터 엑스포트 (yes/no): yes > 그냥 엔터
확장 영역 압축 (yes/no): yes > 그냥 엔터
KO16KSC5601 문자 설정과 KO16KSC5601 NCHAR 문자 설정에서 엑스포트가 종료되었습니다
. LINUX 사용자를 위해 외래 함수 라이브러리 이름을 엑스포트합니다
. LINUX 사용자에 대한 개체 유형 정의를 엑스포트 합니다
LINUX의 개체를 엑스포트하려고 합니다 ...
. 데이터베이스 링크 엑스포트 중
. 순차 번호 엑스포트 중
. 클러스터 정의 엑스포트 중
. LINUX의 테이블을 엑스포트하려고 합니다 via 규정 경로...
. . 테이블                     S_CUSTOMER(를)을 엑스포트 중         15 행이 엑스포트됨
. . 테이블                         S_DEPT(를)을 엑스포트 중         12 행이 엑스포트됨
. . 테이블                          S_EMP(를)을 엑스포트 중         25 행이 엑스포트됨
. . 테이블                        S_IMAGE(를)을 엑스포트 중         19 행이 엑스포트됨
. . 테이블                    S_INVENTORY(를)을 엑스포트 중        114 행이 엑스포트됨
. . 테이블                         S_ITEM(를)을 엑스포트 중         62 행이 엑스포트됨
. . 테이블                     S_LONGTEXT(를)을 엑스포트 중         33 행이 엑스포트됨
. . 테이블                          S_ORD(를)을 엑스포트 중         16 행이 엑스포트됨
. . 테이블                      S_PRODUCT(를)을 엑스포트 중         33 행이 엑스포트됨
. . 테이블                       S_REGION(를)을 엑스포트 중          5 행이 엑스포트됨
. . 테이블                        S_TITLE(를)을 엑스포트 중          8 행이 엑스포트됨
. . 테이블                    S_WAREHOUSE(를)을 엑스포트 중          5 행이 엑스포트됨
. . 테이블                           TEST(를)을 엑스포트 중         16 행이 엑스포트됨
. 동의어 엑스포트 중
. 뷰 엑스포트 중
. 저장 프로시저 엑스포트 중
. 참조 무결성 제약조건 엑스포트 중
. 트리거 엑스포트 중
. 이후 테이블 처리를 엑스포트 중
. 스냅샷 엑스포트 중
. 스냅샷 로그 엑스포트 중
. 작업 대기열을 엑스포트 중
. 리프레쉬 그룹과 자식 엑스포트 중
엑스포트가 경고 없이 정상적으로 종료되었습니다.
[linux@localhost db]$ ls -l
total 96
-rw-rw-r--   1 linux    linux        3340 Aug 15 22:30 JdbcTest.class
-rw-r--r--   1 linux    linux        3112 Aug 15 22:43 JdbcTest.java
drwxrwxr-x   2 linux    linux        1024 Oct  1 01:10 db_ex
-rw-rw-r--   1 linux    linux       40960 Oct  5 23:46 expdat.dmp
-rw-r--r--   1 linux    linux       41841 Jun 30 11:59 summit.sql
-rw-rw-r--   1 linux    linux        4096 Oct  5 23:46 사용자관리-백업_리스토어.txt

kang이라는 사용자로 import를 수행한다.
[linux@localhost db]$ imp kang/kang
Import: Release 8.0.5.0.0 - Production on 화 Oct 5 23:48:1 1999
(c) Copyright 1998 Oracle Corporation.  All rights reserved.

연결할곳: Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production
임포트 파일: expdat.dmp >
삽입 버퍼 크기를 입력하십시오 (최소치는 4096) 30720>
엑스포트 파일은 규정 경로를 거쳐 EXPORT:V08.00.05 에 의해 생성되었습니다
경고: 개체는 다른 사용자 LINUX(이)가 엑스포트한 것입니다.
임포트 파일의 내용만 표시합니다. (yes/no): no >
개체 존재로 인해 발생한 생성 오류는 무시합니다. (yes/no): no >
권한부여 임포트 (yes/no): yes >
테이블 데이터 임포트 (yes/no): yes >
엑스포트 파일 전체를 임포트합니다. (yes/no): no >
사용자명:linux 여기서 kang이라고 입력하지 않도록 주의한다
테이블(T) 또는 분할(T:P)명을 입력하십시오. 널 목록은 사용자의 모든 테이블을 의미합니다.
테이블(T) 또는 분할(T:P)명을 입력하거나 완료 시에는 .을 입력하십시오.
. LINUX 개체를 KANG(으)로 임포트하는 중입니다.
. . 테이블                   "S_CUSTOMER"(를)을 임포트 중         15 행이 임포트되었습니다
. . 테이블                       "S_DEPT"(를)을 임포트 중         12 행이 임포트되었습니다
. . 테이블                        "S_EMP"(를)을 임포트 중         25 행이 임포트되었습니다
. . 테이블                      "S_IMAGE"(를)을 임포트 중         19 행이 임포트되었습니다
. . 테이블                  "S_INVENTORY"(를)을 임포트 중        114 행이 임포트되었습니다
. . 테이블                       "S_ITEM"(를)을 임포트 중         62 행이 임포트되었습니다
. . 테이블                   "S_LONGTEXT"(를)을 임포트 중         33 행이 임포트되었습니다
. . 테이블                        "S_ORD"(를)을 임포트 중         16 행이 임포트되었습니다
. . 테이블                    "S_PRODUCT"(를)을 임포트 중         33 행이 임포트되었습니다
. . 테이블                     "S_REGION"(를)을 임포트 중          5 행이 임포트되었습니다
. . 테이블                      "S_TITLE"(를)을 임포트 중          8 행이 임포트되었습니다
. . 테이블                  "S_WAREHOUSE"(를)을 임포트 중          5 행이 임포트되었습니다
. . 테이블                         "TEST"(를)을 임포트 중         16 행이 임포트되었습니다
사용 가능한 제약 조건에 관해서...
임포트가 경고 없이 정상적으로 종료되었습니다.
[linux@localhost db]$ sqlplus
SQL*Plus: Release 8.0.5.0.0 - Production on 화 Oct 5 23:48:37 1999
(c) Copyright 1998 Oracle Corporation.  All rights reserved.
사용자명 입력: kang
암호 입력:
Connected to:
Oracle8 Release 8.0.5.0.0 - Production
PL/SQL Release 8.0.5.0.0 - Production

정말 import가 되었는지 확인하자
SQL> select * from tab;
TNAME			       TABTYPE	CLUSTERID
------------------------------ ------- ----------
S_CUSTOMER		       TABLE
S_DEPT			       TABLE
S_EMP			       TABLE
S_IMAGE 		       TABLE
S_INVENTORY		       TABLE
S_ITEM			       TABLE
S_LONGTEXT		       TABLE
S_ORD			       TABLE
S_PRODUCT		       TABLE
S_REGION		       TABLE
S_TITLE 		       TABLE
S_WAREHOUSE		       TABLE
TEST			       TABLE
13 개의 행이 선택되었습니다.


다시 system으로 접속해서 kang이라는 사용자를 지운다.
이때 kang이라는 사용자의 schema에는 테이블이 존재하므로 cascade옵션을 사용해야 한다

SQL> connect system
암호 입력:
연결되었습니다.
SQL> drop user kang;
drop user kang
*
1행에 오류:
ORA-01922: 'KANG'(을)를 삭제하려면 CASCADE를 지정하여야 합니다

SQL> drop user kang cascade;
사용자가 삭제되었습니다.

추가: 2001-12-20
imp에서 show패러미터는 export파일의 내용을 보여주고, 실제 import는 수행하지 않는다.
보여주는 내용이 SQL문으로 되어 있으므로 어떤 경우, 유용하게 사용될 수 있다.

imp system/xxxxxx full=y show=y file=full_20011220.dmp log=exp_content.sql


복구과정
1. 가장 최근의 exp파일에서 full=y inctype=system으로 imp를 수행하여 data dictionary와 DB구조들을 재생성
   (이때 적용될 exp파일은 complete, cumulative, incremental의 종류에 관계없이 가장 최근의 exp파일이다.)
2. 가장 최근의 complete exp파일에서 full=y inctype=restore로 import한다.
   (나머지 exp파일들에 대해 full=y와 inctype=restore로 계속 수행한다)
3. 가장 최근의 complete exp파일 이후로 수행된 cumulative exp파일들을 처리
4. 가장 최근의 cumulative exp파일 이후로 수행된 incremental exp파일들을 처리

export시 DB를 restricted session에 두고,(alter system enable restricted session) 
exp 패러미터중 consistent를 Y에 두면 최소한의 읽기일관성 보장한다.
단, consistent패러미터는 complete, cumulative에서만 사용할 수 있다.
consistent패러미터는 incremental에서는 사용될 수 없으므로, incremental수행시에는
DB를 restricted session에 두고 수행하는 것이 좋다.


-- 읽기일관성 문제 예
테이블 데이터가 먼저 export되고, index는 그 다음에 수행된다.
따라서, 테이블데이터에 있지 않으나, 인덱스에는 해당 데이터가 있을 수도 있다.
export수행중, 변경된 데이터는 export파일에 저장되지 않는다.


conventional Vs direct
디폴트는 conventional path를 이용해 export된다.
conventional path는 SQL을 SQL*PLUS에서 수행하는 것과 동일한 방식으로 실행된다.
direct패러미터는 디폴트가 N이므로 명시적으로 Y값으로 설정해야 한다.
direct는 데이터 정의와 몇몇 SQL을 skip하여 수행되므로 백업의 속도가 빠르다.
direct path를 사용할 때는 buffer패러미터가 사용되지 않는다.


full=y로 수행된 export파일은 import시 user,table,full 모두에 사용될 수 있다

로그스위치

더보기

로그스위치

로그스위치는 로그파일에 모두 채워졌을때 발생한다.
리두로그그룹는 최소 2개, 각 리두로그그룹당 멤버는 최소 1개가 있어야 한다.
아래의 예에서는 3개의 리두로그그룹이 있고, 각 그룹당 멤버는 1개씩 있다. 
아래의 예에서 주의해서 볼 것은 status필드이다. CURRENT라고 되어 있는 것이 현재
활성화된 리두로그그룹이다. 
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TI                                      
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------                                      
         1          1         13     512000          1 NO  CURRENT                  53631 99/11/26                                      
         2          1         11     512000          1 NO  INACTIVE                 53629 99/11/26                                      
         3          1         12     512000          1 NO  INACTIVE                 53630 99/11/26                                      
SQL> alter system switch logfile; 강제로 로그스위치가 발생하도록 한다.
시스템이 변경되었습니다.
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TI                                      
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------                                      
         1          1         13     512000          1 NO  INACTIVE                 53631 99/11/26                                      
         2          1         14     512000          1 NO  CURRENT                  53655 99/11/26                                      
         3          1         12     512000          1 NO  INACTIVE                 53630 99/11/26                                      
SQL> alter system switch logfile;
시스템이 변경되었습니다.
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TI                                      
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------                                      
         1          1         13     512000          1 NO  INACTIVE                 53631 99/11/26                                      
         2          1         14     512000          1 NO  INACTIVE                 53655 99/11/26                                      
         3          1         15     512000          1 NO  CURRENT                  53656 99/11/26                                      
SQL> alter system switch logfile;
시스템이 변경되었습니다.
SQL> select * from v$log;
    GROUP#    THREAD#  SEQUENCE#      BYTES    MEMBERS ARC STATUS           FIRST_CHANGE# FIRST_TI                                      
---------- ---------- ---------- ---------- ---------- --- ---------------- ------------- --------                                      
         1          1         16     512000          1 NO  CURRENT                  53657 99/11/26                                      
         2          1         14     512000          1 NO  INACTIVE                 53655 99/11/26                                      
         3          1         15     512000          1 NO  INACTIVE                 53656 99/11/26
728x90

'database > oracle' 카테고리의 다른 글

오라클 날짜 관련 함수 (2006.09.05)  (0) 2025.05.10
sum () over () (2006.07.13)  (0) 2025.05.10
sql관련 함수정리 (2006.03.15)  (0) 2025.05.10
쿼리문 간단 정리 (2006.03.15 )  (0) 2025.05.10
sql & sql*plus 퍼오기(2005.05.27)  (0) 2025.05.10

+ Recent posts