【脚本】Registering an AFTER SUSPEND Trigger

Registering an AFTER SUSPEND Trigger

 

In the followingexample, a system wide AFTER SUSPEND trigger is created andregistered as user SYS at the database level. Whenever a resumablestatement is suspended in any session, this trigger can have either of twoeffects:

 

1If an undosegment has reached its space limit, then a message is sent to the DBA and the statement is aborted.

2If any otherrecoverable error has occurred, the timeout interval is reset to 8 hours.

Here are the statementsfor this example:

-- Hundsun@Askerain
--If the error is related to undo segments, log error, send email
--to DBA, and abort the statement. Otherwise, set timeout to 8 hours.
--
--sys.rbs_error is a table which is to be
--created by a DBA manually and defined as
--(sql_text VARCHAR2(1000), error_msg VARCHAR2(4000),
--suspend_time DATE)

  -- drop table sys.rbs_error avoid corruption
DROP TABLE sys.rbs_error;

  -- create table sys.rbs_error to record resumable error information
CREATE TABLE sys.rbs_error(sql_text VARCHAR2(1000),error_msg VARCHAR2(4000),suspend_time DATE);

  -- create a trigger to set strategies and report error information
CREATE OR REPLACE TRIGGER resumable_space_trigger
  AFTER SUSPEND ON DATABASE
  -- declare transaction in this trigger is autonomous
  -- this is not required because transactions within a trigger are always autonomous
DECLARE
     PRAGMA AUTONOMOUS_TRANSACTION;
     cur_sid           NUMBER;
     cur_inst          NUMBER;
     errno             NUMBER;
     err_type          VARCHAR2;
     object_owner      VARCHAR2;
     object_type       VARCHAR2;
     table_space_name  VARCHAR2;
     object_name       VARCHAR2;
     sub_object_name   VARCHAR2;
     error_txt         VARCHAR2;
     msg_body          VARCHAR2;
     ret_value         BOOLEAN;
     mail_conn        UTL_SMTP.CONNECTION;
BEGIN
     --Get session ID
     SELECT DISTINCT (SID) INTO cur_SID FROM V$MYSTAT;
     --Get instance number
     cur_inst := userenv('instance');
     --Get space error information
     ret_value := DBMS_RESUMABLE.SPACE_ERROR_INFO(err_type,object_type,object_owner,
                       table_space_name,object_name,sub_object_name);

  IF OBJECT_TYPE = 'UNDO SEGMENT' THEN        /* LOG ERROR */
         INSERT INTO sys.rbs_error(SELECT SQL_TEXT, ERROR_MSG, SUSPEND_TIME 
         FROM DBMS_RESUMABLE WHERE SESSION_ID = cur_sid AND INSTANCE_ID = cur_inst);       
     SELECT ERROR_MSG INTO error_txt FROM DBMS_RESUMABLE 
     WHERE SESSION_ID = cur_sid and INSTANCE_ID = cur_inst;
     -- Send email to receipient through UTL_SMTP package
     msg_body := 'Subject: Space Error Occurred Space limit reached for undo segment'||object_name ||'on'||
                         TO_CHAR(SYSDATE,' Month dd, YYYY, HH :MIam')||'. Error message was '||error_txt;
     mail_conn := UTL_SMTP.OPEN_CONNECTION('localhost', 25);
     UTL_SMTP.HELO(mail_conn, 'localhost');
     UTL_SMTP.MAIL(mail_conn, 'oracle@localhost');
     UTL_SMTP.RCPT(mail_conn, 'oracle@localhost');
     UTL_SMTP.DATA(mail_conn, msg_body);
     UTL_SMTP.QUIT(mail_conn);
     -- Abort the statement
     DBMS_RESUMABLE.ABORT(cur_sid);
  ELSE
     -- Set timeout to 8 hours
     DBMS_RESUMABLE.SET_TIMEOUT(28800);
  END IF;
     /* commit autonomous transaction */
     COMMIT;   
END;
/

 

 

猜你喜欢

转载自askerain.iteye.com/blog/2290157
今日推荐