Oracle

게시글 보기
작성자 유건데이타 등록일 2015-06-24
제목 DBMS_ALERT
유건데이타의 log observer와 비슷한 개념으로 보면 됩니다


DBMS_ALERT이란?
==================
DBMS_ALERT은 DATABASE에 일어나는 변화를 자동으로 알려줄 수 있는 Function이다.
Application은 관심있는 Table에 대해 일어나는 변화에 대한 확인을 언제든지 받을
수 있게 된다. 이렇게 되기 위해서 해당 TABLE에 대해 변화가 일어났을 때 ALERT을
줄 수 있는 몇개의 PROGRAM이 DATABASE에 등록되어 있어야 한다.

DBMS_ALERT은 어떤 TABLE에 대해 일어나는 INSERT, UPDATE, DELETE등의 변화를
MONITORING하는 PRO*C PROGRAM등에 이용될 수 있겠다.

ALERT을 사용하려면?
=====================
다른 DBMS PACKAGES와 마찬가지로 DBMS_ALERT PACKAGE는 SYS가 OWNER이며
CATPROC.SQL을 실행하여 생성된다. DBMS_ALERT PACKAGE를 사용하려면
이 PACKAGE에 대한 EXECUTE PRIVILEGE가 있어야 한다.

SQL> GRANT EXECUTE ON DBMS_ALERT TO USER_NAME;

한번 EXECUTE PRIVILEGE를 받으면 다른 SQL*PLUS, PRO*C, PRO*COBOL, PL/SQL같은
다른 ORACLE TOOL에서 DBMS_ALERT을 사용할 수 있다.

DBMS_ALERT을 어떻게 실행되는가?
==================================
여기에서는 몇 개의 SESSION 간에 ALERT이 어떻게 사용되는지 설명하기 위해
DBMS_ALERT PACKAGE중 4개의PROCEDURE를 사용하겠다.

REGISTER PROCEDURE:
이 PROCEDURE는 ALERT를 등록한다.
하나의 SESSION에서 여러개의 ALERT을 등록할 수 있다.
DBMS_ALERT.REGISTER( ALERT_NAME IN VARCHAR2);

SIGNAL PROCEDURE:
이 PROCEDURE는 ALERT에 SIGNAL을 보내고,MESSAGE를 보낸다.
SIGNAL을 TRANSACTION에서 COMMIT을 만나야지만 영향이 있게 된다.
만약 TRANSACTION에서 ROLL BACK을 하면 SIGNAL을 아무런 영향을 받지 않는다.
DBMS_ALERT.SIGNAL(ALERT_NAME IN VARCHAR2,
MESSAGE IN VARCHAR2);

WAITONE PROCEDURE:
이 PROCEDURE는 SESSION이 특정한 ALERT이 발생되기를 기다리게 한다.
SIGNAL이 실행되면, MESSAGE는 WATING하고 있는 모든 SESSION에 전달되게 된다.
TIME-OUT SECONDS에 지정된 시간 내에 SIGNAL이 오지 않으면 WAITONE은 STATUS 1을
RETURN하게 된다. 그 전에 ALERT이 일어나면 STATUS 0를 RETURN한다.
TIME-OUT시간은 USER가 선택적으로 지정할 수 있다.
DBMS_ALERT.WAITONE(ALERT_NAME IN VARCHAR2,
MESSAGE OUT VARCHAR2,
STATUS OUT INTEGER,
TIME-OUT IN NUMBER);
만약 한 SESSION에서 여러개의 ALERT을 사용할 경우에는 WAITANY PROCEDURE를
사용하여야 한다.


REMOVE PROCEDURE:
이 PROCEDURE는 등록LIST에서 해당 ALERT명을 삭제하는 기능을 한다.
DBMS_ALERT.REMOVE(ALERT_NAME IN VARCHAR2);

더 자세한 사항은 ORACLE7 SERVER APPLICATION DEVELOPER'S GUIDE 참조 바람

SAMPLE
==========
DBMS_ALERT과 TRIGGER를 이용하여 SESSION간에 TABLE에 관련된 정보를 전달하는 과정을
본다.
세번째 SESSION에서 EMP TABLE에 UPDATE, DELETE, INSERT문장을 실행하면 SIGNAL을
보내는 DB TRIGGER가 FIRE되게 된다.
그러면 기다리고 있는 2개의 PRO*C,PL/SQL SESSION에서 SIGNAL을 받아
MESSAGE를 내게 되는 것이다.

첫번째 SESSION은 PRO*C PROGRAM이다.
이 SESSION에서는 I_GOT_IT이라는 이름의 ALERT를 지정하여 SIGNAL을 기다린다.
======================================================
#include
#include
#define UNAME_LEN 20
#define PWD_LEN 40
VARCHAR username[UNAME_LEN];
VARCHAR password[PWD_LEN];


EXEC SQL BEGIN DECLARE SECTION;
int status;
int timeout=20;
varchar name[40];
char message[100];
short name_ind;
short message_ind;
short status_ind;
EXEC SQL END DECLARE SECTION;

#include


/* Declare error handling function. */
void sql_error();


main()
{
strncpy((char *) username.arr, "SCOTT", UNAME_LEN);
username.len = strlen((char *) username.arr);
strncpy((char *) password.arr, "TIGER", PWD_LEN);
password.len = strlen((char *) password.arr);

EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--\n");

EXEC SQL CONNECT :username IDENTIFIED BY :password;
printf("\nConnected to ORACLE as user: %s\n", username.arr);


strcpy((char *)name.arr, "I_GOT_IT");
name.len = strlen((char *) name.arr);

memset(message,'\0',100);
EXEC SQL EXECUTE
BEGIN
DBMS_ALERT.REGISTER(:name);
END;
END-EXEC;
printf("\n WE ARE WAITING FOR WAITONE SIGNAL\t%s\n\n",name.arr);
EXEC SQL EXECUTE
BEGIN
DBMS_ALERT.WAITANY(:name:name_ind, :message:message_ind,
:status:status_ind, :timeout);
END;
END-EXEC;
if (!status)
{
printf("\n WE HAVE RECEIVED THE SIGNAL \t\n\n");
printf("\n THE MESSAGE THAT HAS BEEN RECEIVED IS\t%s\n\n", message);
printf("\n THE STATUS\t\t THE TIME\n");
printf("\n\t %d \t\t %d\n\n", status, timeout);
printf("\nG'day.\n\n\n");
}
else
printf("NO MESSAGE HAS BEEN RECEIVED. EXIT SESSION\n\n");
EXEC SQL EXECUTE
BEGIN
DBMS_ALERT.REMOVE(:name);
END;
END-EXEC;
EXEC SQL COMMIT WORK RELEASE;
exit(0);
}
======================================================
두번째 SESSION은 PL/SQL이다.
이 SESSION에서도 I_GOT_IT이라는 이름의 ALERT을 지정하여 SIGNAL을 기다린다.
======================================================
DECLARE
status NUMBER;
timeout NUMBER;
message CHAR(30);
name VARCHAR2(20);
BEGIN
name:='I_GOT_IT';
timeout:=20;
DBMS_ALERT.REGISTER(name);
DBMS_ALERT.WAITANY(name, message, status, timeout);
IF status = 0 THEN
DBMS_OUTPUT.PUT_LINE(' RECEIVED SIGNAL ' || name);
DBMS_OUTPUT.PUT_LINE('THE MESSAGE THAT HAS BEEN RECEIVED IS ' || message);
ELSE
DBMS_OUTPUT.PUT_LINE('NO MESSAGE HAS BEEN RECEIVED. EXIT SESSION');
END IF;
DBMS_ALERT.REMOVE(name);
END;
/
======================================================


세번째 SESSION을 SQL*PLUS에서 SQL을 실행하는 SESSION이다.
이 SESSION은 먼저 다음과 같이 단순하게 I_GOT_IT이라는 ALERT을
다음과 같이 등록한 후 INSERT, UPDATE, DELETE등의 SQL을 실행한다.
SQL> EXECUTE DBMS_ALERT.REGISTER ('I_GOT_IT');


위의 3개의 SESSION을 생성하기 전에 사용자는 먼저 다음과 같은
TRIGGER를 등록해 놓아야 한다.
======================================================================
CREATE OR REPLACE TRIGGER my_trig
AFTER INSERT OR UPDATE OR DELETE on EMP
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS_ALERT.SIGNAL('I_GOT_IT', 'INSERT INTO EMP ' || :new.ename );
END IF;
IF UPDATING THEN
DBMS_ALERT.SIGNAL('I_GOT_IT', 'UPDATE ENAME TO ' || :new.ename );
END IF;
IF DELETING THEN
DBMS_ALERT.SIGNAL('I_GOT_IT', 'DELETE FROM EMP ' || :old.ename );
END IF;
END;
/
======================================================================

위의 PRO*C,PL/SQL SESSION을 실행한 후 3번째의 SQL*PLUS SESSION을 실행한다.
SQL*PLUS SESSION에서 다음과 같은 SQL문장을 실행한 후 COMMIT한다.
SQL> UPDATE EMP SET ENAME= 'HADI' WHERE EMPNO = 7844;
COMMIT되고나면 TRIGGER가 FIRE되어 SIGNAL이 실행되고,
PRO*C, PL/SQL SESSION에서 ALERT을 받아 MESSAGE를 내게 된다.

from otn
오라클 유지보수 유건데이타
Comment
등록된 코멘트가 없습니다.