DBMS_ALERT包提供了注册、发送和接收告警的能力。

表 1. DBMS ALERT 函数/存储过程
函数/存储过程 返回类型 说明
REGISTER(name) N/A 使当前会话可以接收指定告警的通知信息。
REMOVE(name) N/A 取消接收指定告警的通知信息。
REMOVEALL N/A 从注册列表中删除此会话的所有告警。
SIGNAL(name, message) N/A 产生指定名称的告警。
WAITANY(name OUT, message OUT, status OUT, timeout) N/A 等待产生已注册的告警。
WAITONE(name, message OUT, status OUT, timeout) N/A 等待产生指定的告警。
PolarDB允许的最大并发告警数量为500。您可以通过设置postgresql.conf文件中dbms_alert.max_alerts的参数值来指定系统允许的最大并发告警数量。设置dbms_alert.max_alerts的参数值时,可使用您自己的编辑器打开/opt/PostgresPlus/9. 3AS/data路径下的postgresql.conf文件,按照下面的示例设置dbms_alert.max_alerts的参数值:
dbms alert.max alerts = alert count
说明 alert_count用于指定告警的最大并发数量。dbms_alert.max_alerts的默认值为100。如果要禁用这个功能特性,可以将dbms_alert.max_alerts的值设置为0。

为了保证dbms_alert.max_alerts正常工作,custom_variable_classes参数值中必须包含dbms_alert

custom variable classes = 'dbms_alert, ...'

编辑postgresql.conf文件后,您必须重启服务器。

REGISTER

当前会话可以接收指定告警的通知信息。

语法

REGISTER(name VARCHAR2) 

参数

参数名称 描述
name 被注册的告警名称。

示例

以下匿名代码块注册了一个名为alert_test的告警:
DECLARE
    v_name           VARCHAR2(30) := 'alert_test';
    v_msg            VARCHAR2(80);
    v_status         INTEGER;
    v_timeout        NUMBER(3) := 120;
BEGIN
    DBMS_ALERT.REGISTER(v_name);
    DBMS_OUTPUT.PUT_LINE('Registered for alert ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Waiting for signal...');
    DBMS_ALERT.WAITONE(v_name,v_msg,v_status,v_timeout);
    DBMS_OUTPUT.PUT_LINE('Alert name   : ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Alert msg    : ' || v_msg);
    DBMS_OUTPUT.PUT_LINE('Alert status : ' || v_status);
    DBMS_OUTPUT.PUT_LINE('Alert timeout: ' || v_timeout || ' seconds');
    DBMS_ALERT.REMOVE(v_name);
END;
执行代码块后的显示结果如下:
Registered for alert alert_test
Waiting for signal...

REMOVE

取消接收指定告警的通知信息。

语法

REMOVE(name VARCHAR2)

参数

参数名称 描述
name 被取消注册的告警名称。

REMOVEALL

从注册列表中删除此会话的所有告警。

语法

REMOVEALL

SIGNAL

产生指定名称的告警。

语法

SIGNAL(name VARCHAR2, message VARCHAR2)

参数

参数名称 描述
name 告警名称。
message 与告警相关的信息。

示例

以下匿名代码块发送了名称为alert_test的告警。
DECLARE
    v_name   VARCHAR2(30) := 'alert_test';
BEGIN
    DBMS_ALERT.SIGNAL(v_name,'This is the message from ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Issued alert for ' || v_name);
END; 
执行代码块后显示的结果如下:
Issued alert for alert_test  

WAITANY

等待产生已注册的告警。

语法

WAITANY(name OUT VARCHAR2, message OUT VARCHAR2, status OUT INTEGER, timeout NUMBER)

参数

参数名称 描述
name 告警名称。
message 与告警相关的信息。
status 返回的状态码。
  • 0:产生告警。
  • 1:告警超时。
timeout 等待产生告警的时间。单位:秒。

示例

以下匿名代码块使用存储过程WAITANY来接收命名为alert_test或any_alert的告警:
DECLARE
    v_name           VARCHAR2(30);
    v_msg            VARCHAR2(80);
    v_status         INTEGER;
    v_timeout        NUMBER(3) := 120;
BEGIN
    DBMS_ALERT.REGISTER('alert_test');
    DBMS_ALERT.REGISTER('any_alert');
    DBMS_OUTPUT.PUT_LINE('Registered for alert alert_test and any_alert');
    DBMS_OUTPUT.PUT_LINE('Waiting for signal...');
    DBMS_ALERT.WAITANY(v_name,v_msg,v_status,v_timeout);
    DBMS_OUTPUT.PUT_LINE('Alert name   : ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Alert msg    : ' || v_msg);
    DBMS_OUTPUT.PUT_LINE('Alert status : ' || v_status);
    DBMS_OUTPUT.PUT_LINE('Alert timeout: ' || v_timeout || ' seconds');
    DBMS_ALERT.REMOVEALL;
END;   
执行代码块显示的结果如下:
Registered for alert alert_test and any_alert
Waiting for signal...    
第二个会话中的匿名代码块为名为any_alert的告警发出的信号:
DECLARE
    v_name   VARCHAR2(30) := 'any_alert';
BEGIN
    DBMS_ALERT.SIGNAL(v_name,'This is the message from ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Issued alert for ' || v_name);
END;
执行代码块后的显示结果如下:
Issued alert for any_alert
控制流程返回第一个匿名代码块,然后执行剩余的代码:
Registered for alert alert_test and any_alert
Waiting for signal...
Alert name   : any_alert
Alert msg    : This is the message from any_alert
Alert status : 0
Alert timeout: 120 seconds

WAITONE

等待产生指定的告警。

语法

WAITONE(name VARCHAR2, message OUT VARCHAR2, status OUT INTEGER, timeout NUMBER)

参数

参数名称 描述
name 告警名称。
message 储过程SIGNAL发送的消息。
status 返回的状态码。
  • 0:产生告警。
  • 1:告警超时。
timeout 等待告警产生的时间。单位:秒。

示例

以下匿名代码块中,除使用存储过程WAITONE接收名称为alert_test的告警外,其余地方和使用存储过程WAITANY的示例类似。
DECLARE
    v_name           VARCHAR2(30) := 'alert_test';
    v_msg            VARCHAR2(80);
    v_status         INTEGER;
    v_timeout        NUMBER(3) := 120;
BEGIN
    DBMS_ALERT.REGISTER(v_name);
    DBMS_OUTPUT.PUT_LINE('Registered for alert ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Waiting for signal...');
    DBMS_ALERT.WAITONE(v_name,v_msg,v_status,v_timeout);
    DBMS_OUTPUT.PUT_LINE('Alert name   : ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Alert msg    : ' || v_msg);
    DBMS_OUTPUT.PUT_LINE('Alert status : ' || v_status);
    DBMS_OUTPUT.PUT_LINE('Alert timeout: ' || v_timeout || ' seconds');
    DBMS_ALERT.REMOVE(v_name);
END;
执行代码块后显示的结果如下:
Registered for alert alert_test
Waiting for signal...
第二个会话中的一个匿名块发送名称alert_test的告警信号:
DECLARE
    v_name   VARCHAR2(30) := 'alert_test';
BEGIN
    DBMS_ALERT.SIGNAL(v_name,'This is the message from ' || v_name);
    DBMS_OUTPUT.PUT_LINE('Issued alert for ' || v_name);
END;
执行代码块后显示的结果如下:
Issued alert for alert_test
第一个会话收到告警信息,控制流程返回到匿名代码块,再执行这个匿名代码块的剩余代码。
Registered for alert alert_test
Waiting for signal...
Alert name   : alert_test
Alert msg    : This is the message from alert_test
Alert status : 0
Alert timeout: 120 seconds

综合性示例

以下示例中,当表dept和emp发生改变时,您可以使用两个触发器发送告警信息。使用一个匿名代码块监听这些告警,并且当收到告警时,显示相关信息。

以下是表dept和emp上定义的触发器:
CREATE OR REPLACE TRIGGER dept_alert_trig
    AFTER INSERT OR UPDATE OR DELETE ON dept
DECLARE
    v_action        VARCHAR2(25);
BEGIN
    IF INSERTING THEN
        v_action := ' added department(s) ';
    ELSIF UPDATING THEN
        v_action := ' updated department(s) ';
    ELSIF DELETING THEN
        v_action := ' deleted department(s) ';
    END IF;
    DBMS_ALERT.SIGNAL('dept_alert',USER || v_action || 'on ' ||
        SYSDATE);
END;

CREATE OR REPLACE TRIGGER emp_alert_trig
    AFTER INSERT OR UPDATE OR DELETE ON emp
DECLARE
    v_action        VARCHAR2(25);
BEGIN
    IF INSERTING THEN
        v_action := ' added employee(s) ';
    ELSIF UPDATING THEN
        v_action := ' updated employee(s) ';
    ELSIF DELETING THEN
        v_action := ' deleted employee(s) ';
    END IF;
    DBMS_ALERT.SIGNAL('emp_alert',USER || v_action || 'on ' ||
        SYSDATE);
END;
当在其它会话中对表dept和emp进行更新操作时,在一个会话中执行以下这个匿名代码块:
DECLARE
    v_dept_alert     VARCHAR2(30) := 'dept_alert';
    v_emp_alert      VARCHAR2(30) := 'emp_alert';
    v_name           VARCHAR2(30);
    v_msg            VARCHAR2(80);
    v_status         INTEGER;
    v_timeout        NUMBER(3) := 60;
BEGIN
    DBMS_ALERT.REGISTER(v_dept_alert);
    DBMS_ALERT.REGISTER(v_emp_alert);
    DBMS_OUTPUT.PUT_LINE('Registered for alerts dept_alert and emp_alert');
    DBMS_OUTPUT.PUT_LINE('Waiting for signal...');
    LOOP
        DBMS_ALERT.WAITANY(v_name,v_msg,v_status,v_timeout);
        EXIT WHEN v_status != 0;
        DBMS_OUTPUT.PUT_LINE('Alert name   : ' || v_name);
        DBMS_OUTPUT.PUT_LINE('Alert msg    : ' || v_msg);
        DBMS_OUTPUT.PUT_LINE('Alert status : ' || v_status);
        DBMS_OUTPUT.PUT_LINE('------------------------------------' ||
            '-------------------------');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('Alert status : ' || v_status);
    DBMS_ALERT.REMOVEALL;
END;
执行代码块后显示结果如下:
Registered for alerts dept_alert and emp_alert
Waiting for signal...
用户mary对dept表和emp表执行以下操作:
INSERT INTO dept VALUES (50,'FINANCE,,,CHICAG0');
INSERT INTO emp (empno,ename,deptno) VALUES (9001,'J0NES',50);
INSERT INTO emp (empno,ename,deptno) VALUES (9002,'ALICE',50);           
用户john对dept表执行以下操作:
INSERT INTO dept VALUES (60,'HR','L0S ANGELES');
以下显示内容是从触发器中接收告警信号的匿名代码块显示的输出内容:
Registered for alerts dept_alert and emp_alert
Waiting for signal...
Alert name   : dept_alert
Alert msg    : mary added department(s) on 25-OCT-07 16:41:01
Alert status : 0
-------------------------------------------------------------
Alert name   : emp_alert
Alert msg    : mary added employee(s) on 25-OCT-07 16:41:02
Alert status : 0
-------------------------------------------------------------
Alert name   : dept_alert
Alert msg    : john added department(s) on 25-OCT-07 16:41:22
Alert status : 0
-------------------------------------------------------------
Alert status : 1