TECH
QUESTION
자주하는 질문답변 입니다.
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 | |||
---|---|---|---|
등록된 코멘트가 없습니다. |