2008. 10. 8. 15:28

[oracle]Broken된 Job을 자동으로 재실행 시키는 방법

--------------------------------------------------------------------------------
BROKEN된 JOB을 자동으로 재실행 시키는 방법
=========================================


1. broken job
~~~~~~~~~~~~~~
Oracle에서 특정 작업을 주기적으로 실행시키기 위해서는 job을 이용하게 된다.
이것은 snp라는 background process가 각 job의 interval간격으로 작업을 실행
하는데, snapshot과 같은 것이 job의 대표적인 예이며, dbms_job package를
이용하여 직접 job을 등록 및 관리, 삭제가 가능하다.

이러한 job이 문제가 발생하여 수행이 오류가 발생하면 1분, 2분, 4분, 8분과
같은 간격으로 자동으로 재실행을 하게 되고, 이 주기가 해당 job의 inerval보다
크게 되면 그때부터는 interval간격마다 job을 실행하도록 시도한다. job의
interval이 1분보다 작으로 interval간격대로 시도하고, 예를 들어 interval이
2분 20초마다이면, 1분, 2분, 이후에는 2분 20초 마다씩 새로 fail된 job을
실행해 본다. 이렇게 fail이 발생한 job을 자동으로 재실행하는 것은 최대 16번
이며, 16번 시도후에는 job이 broken상태가 되어 더 이상 snp process는 시도를
하지 않게 된다.

oracle이 이렇게 16번 시도 후 job을 broken상태로 하는 이유는 16번 시도 때까지
문제가 해결되지 않은 job이라면, 예를 들어 network이 장시간 down되어 snapshot
refresh가 안 되는 것과 같이 문제가 장기화될 가능성이 많고 그러한 job을 계속
시도해 보는 것 자체가 cpu를 많이 소모하는 낭비되는 작업이라는 판단 때문이다.

그러나 일단 job이 broken되면, 그 job을 fail 상태로 만든 원인이 제거된 후에도
여전히 실행되지 않은 상태로 있게 되어 db admin이 수시로 broken된 job이 있는
지를 확인하고 manual하게 dbms_job.run등을 실행하여 다시 실행하도록 할 필요가
있다.

이러한 db admin 작업을 덜고 database 자체에서 broken job에 대해서도 계속
run을 시도하고자 하는 경우 이 문서를 이용하여 작업하면 된다.


2. dba_jobs view에 대해서
~~~~~~~~~~~~~~~~~~~~~~~~~~

dba_jobs(혹은 user_jobs)는 등록된 job에 관한 여러가지 정보를 사용자게 제공
한다.

특히 job의 broken과 관련하여 중요한 몇개의 column에 대해서 살펴본다.

broken : 해당 job이 broken되었으면 Y, 그렇지 않으면 N로 나타난다.
failures : job이 시도되었으나 fail된 숫자이다. 이 숫자가 16이 되면 broken이
Y가 되어 더 이상 snp process는 시도하지 않게 되어 이 숫자도
증가가 되지 않는다.
단, dbms_job.run을 user가 manual하게 실행해도 여전히 문제가 발생
하면 이 숫자가 이미 16이상이라도 시도할 때마다 계속 1씩 증가한다.

next_date: job이 다음에 실행될 시간이다.
job이 실행을 시작하는 시점에 last_date + interval = next_date로
계산한 후 job 실행이 끝나면 (혹은 오류 발생 후) 시작 시점에
계산된 next_date값이 dba_jobs에 기록되어 확인이 가능해 진다.
이 시간이 과거로 되어 있으면, failures가 0이고 broken이 N이라
하더라도 snp는 그 job을 run하려고 시도하지 않는다.

this_date: 이것은 현재 실행되는 job이 실행을 시작한 시간을 나타낸다. 이미
실행이 끝난 job이라면 이 부분은 null로 나타나면 이 컬럼에 값이
있는 job에 대해서는 dba_jobs_running에도 정보가 나타난다.


3. broken된 job을 실행되도록 하는 procedure

먼저, broken된 job을 찾아 broken을 false로 만들어 주고 snp가 다시 실행하도록
next_date를 지정해 주는 procedure를 만든다.
이 procedure는 아래 3-2와 같으며 수행한 기록을 남기기 위해 job_log라는
table을 만들었는데 이 부분은 빼도 무관하다.

3-1 log table 생성
아래 procedure를 실행시키기 전에 먼저 이와 같이 table을 만든다.

SQL> create table job_log (jobno number,
jobname varchar2(30),
jobdate date);

3-2 broken job을 snp가 다시 실행하도록 하기 위해 다음과 같은 release_job을
관리하고자 하는 job의 owner에서 생성한다.

(1) broken job을 선택할 때 dba_jobs 대신에 user_jobs를 이용한다.
dbms_job package는 항상 해당 owner의 job만을 대상으로 작동하므로,
dba_jobs를 확인하고 보이는 job에 대해서 연산하면 owner가 아닌 경우
그러한 job이 없다는 오류가 발생하게 된다.

(2) dbms_job.run을 바로 실행하지 않은 이유는 dbms_job.run은 procedure
내에서 call하지 못하도록 정의되어 실제 사용하면 오류가 발생하거나
수행이 되지 않는다.

(3) broken='Y' 뿐 아니라 failures가 15이상인 것을 함께 check하는 이유는
이 procedure로 인해 일단 broken이 N로 변경된 상태에서 여전히 오류가
있으면 다음 수행 때 broken이 N여서 제외되기 때문이다.

(4) dbms_job.change의 세번째 argument가 next_date인데 이렇게 next_date를
원하는 시간, 혹은 약간의 미래로 맞추어 놓아야 release_job이 수행된
이후 snp가 이 시간에 broken으로 모아진 job을 실행하게 된다.

(5) 결국 broken으로 선택된 job들을 release_jobs가 수행될 때마다 한번씩
snp process로 하여금 다시 시도되도록 지정되어 진다.

(6) procedure source
create or replace procedure release_jobs as
cursor my_broken_jobs is
select job, what from user_jobs where broken = 'Y' or failures > 15;
begin
for broken_jobs in my_broken_jobs
loop
begin
dbms_job.broken(broken_jobs.job,FALSE);
dbms_job.change(broken_jobs.job, null, sysdate+1/1440, null);
insert into job_log values (broken_jobs.job,
broken_jobs.what,
sysdate);
commit;
Exception
when others then
null;
end;
end loop;
end;
/


4. release_jobs를 job으로 등록한다.

위에서 정의한 release_job을 job으로 등록하여 broken된 job을 찾아 실행해주는
작업 자체가 주기적으로 실행되도록 한다.
release_jobs 자체는 network을 타거나 space를 필요로 하는 등의 작업이 아니라,
fail이 발생할 우려는 거의 없다.
이 release_jobs를 등록한 job의 next_date가 미래이고 fail이 없는지만 확인하면,
나머지 broken job들은 여기에서 등록된 job이 관리하게 된다.

SQL>variable job number;
SQL>exec dbms_job.submit(:job, 'RELEASE_JOBS;',sysdate,'sysdate+1/1440');
SQL>exec dbms_job.run(:job);
SQL>commit;
 
출처 : http://kr.blog.yahoo.com/jhoony73/590306.html?p=1&pm=l

2008. 10. 8. 15:27

cron에 hot backup 수행방법

hot.sh
# @(#)local.profile 1.8 99/03/26 SMI
umask 022
stty istrip
export ORACLE_BASE=/u01/ora901
export ORACLE_HOME=/u01/ora901
export ORACLE_SID=ORA901
export ORACLE_OWNER=ora901
export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data
export TNS_ADMIN=$ORACLE_HOME/network/admin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib
export NLS_LANG=American_America.KO16KSC5601
export PATH=$PATH:.:$ORACLE_HOME/bin:/bin:/usr/bin:/usr/ccs/bin:/usr/sbin:/bin:/etc
export EDITOR=vi
/u01/ora901/bin/sqlplus /nolog @/u01/ora901/hot.sql
*********************************************************************

*********************************************************************
hot.sql
connect / as sysdba
set echo on
spool backup.log
rem Starting Hot Backup
!echo 'ORACLE_SID='$ORACLE_SID
!date
archive log list
rem Backup system tablespace
alter tablespace users begin backup;
!date
!cp  /u02/ora901_data/oradata/ORA901/users01.dbf /u02/ora901_data/oradata/ORA901/users01.bak
alter tablespace users end backup;
spool off
exit
*********************************************************************

blade:/var/spool/cron/crontabs #
25 19 * * * su - ora901 -c /u01/ora901/hot.sh
crontab -e가 안될경우
export EDITOR=vi 를 해주시면 됩니다.
환경변수에 디폴트 에디터가 vi로 설정이 되어있지 않아서 이런 문제가 발생합니다.
 
출처 : http://blog.empas.com/myungho/3957282
 

2008. 10. 8. 15:26

[oracle]rowid와 rownum의 정의와 사용법

1 . rowid와 rownum의 정의와 사용법을 알고 싶습니다..

rowid : 테이블에 있는 해당 로우를 찾기위해 사용되는 논리적인 정보
ROWID를 분석해보면
AAAArs AAD AAAAUa AAA
------ --- ------ ---
1 2 3 4
1) 6자리 : 데이터 오브젝트 번호
2) 3자리 : 상대적 파일 번호
3) 6자리 : 블록 번호
4) 3자리 : 블록내의 행 번호

어떤곳에서는 "물리적인 정보"라고 적혀있기도 하지만, 곰곰히 생각해보면 물리적인
정보보다는 오라클이 사용하는 "논리적인 정보"라고 보는것이 맞다고 생각됩니다.

rownum : 결과집합에 대한 가상의 순번
따라서 같은 SQL이라고 하더라도, 다른 rownum 을 가질수 있다.


2.각각이 언제,어떻게 사용하는건지 그 둘의 차이점은 뭔지 알려주시면 대단히 감사하겟습니다..

업무에 따라, 혹은 활용면에 있어 여러 각도로 사용할 수 있겠지만, 지금 생각나는 몇가지만
적어본다면,

1) rowid

가.행을 찾아가는 가장 빠른 방법이 rowid 라는 것을 이용.
update emp
set sal = 999
where rowid in (select rowid from emp where ename like 'A%');
==> 따라서 인덱스의 활용과도 연관성이 있을거라 생각됩니다. 인덱스는 인덱스 컬럼과 rowid를
가지고 있으니까요.

나.데이터가 non-unique 한 환경일때, 데이터에 "유일성"을 부여할수있다.
예를 들면, 이전 페이지에 나왔던 데이터가 다음 페이지에 중복되어 나오는것을 방지할수있다.
이순신이라는 사람이 10건 있다고 할때, 이전페이지에 7건이 나왔다고 하면 "다음"버튼을 누르
면 나머지 3명의 이순신이 나와야되는 업무가 있을때 like 를 쓰게되면 10명 모두 나오게 된다.
이때 rowid를 적절히 이용하면 이들에게도 유일성을 보장할 수 있다.
select * from emp
where ename || rowid > :ename || :before_rowid

참고로, 이 원리는 MSSQL2000에서도 그대로 반영되고 있습니다.
MSSQL2000의 인덱스페이지를 살펴보면, unique 일 경우에는 4byte의 "?"컬럼이 생기지않지만,
non-unique 할때는 4byte의 "?" 컬럼이 생겨 값들의 유일성을 보장하고 있는 것을 알수있습니다.
결국 unique라는 옵션 하나만 잘 사용해도 엄청난 수행속도를 보장받을수 있는거죠.

2) rownum

가.개발시 테스트 용도로 사용
100만건의 테이블을 잘못 select 하면 그 결과가 다 나올때까지 기다리는 경우가 있는데.
이때 where rownum < 10; 를 추가하여 실행시키면 기다릴필요가 없겠죠? (물론 ctrl+c 해도 되지
만...)
약간의 응용력만 있다면, 이 기능도 충분히 업무에 활용할수있다고 봅니다. (ex.게시판)

나. copy_t 테이블 생성시...
create table qq_t
as
select rownum no, to_char(rownum, '09') c_no from cdr -- cdr 테이블은 최소한 100건 이상
where rownum<100;

그외에도 개인의 응용력에 따라 유용하게 사용할 수 있을거라 생각됩니다.

from en-core forum
 
출처 : http://blog.empas.com/goldenant/5477949