设为首页 收藏本站
查看: 715|回复: 0

[经验分享] oracle 11g PL/SQL Programming学习十二

[复制链接]

尚未签到

发表于 2016-8-4 09:45:40 | 显示全部楼层 |阅读模式
----------------------------------------------------------------------------

-----------------PL/SQL学习笔记系列 By Cryking-----------------

------------------------转载请注明出处,谢谢!------------------------

  

DBMS_ALERT内置包

DBMS_ALERT是11g提供的第二种会话间通信的工具.

DBMS_ALERT是一种异步事务控制机制.

它发布一个事件,其他用户通过注册他们感兴趣的警报来订阅事件.

这种发布订阅模式的好处是消除了轮询守护进程.

轮询守护是一种后台进程,它一直循环直到找到一个事件.事件触发器给轮询守护进程一个信号,

使其执行另一个程序或终止某个程序.

DBMS_ALERT是通过使用DBMS_PIPE包来实现公共管道.

所以DBMS_ALERT也使用DBMS_PIPE在SGA的内存结构.

DBMS_ALERT包里只有存储.

有所不同的是DBMS_ALERT维护一个新的内存结构,用来启用发布订阅进程.

这个内存结构包含了一系列管道和信息接收器.



REGISTER存储

原型:

REGISTER(signal_name)

功能:

订阅一个或多个警报.参数为有效的信号名.



REMOVE存储

原型:

REMOVE(signal_name)

功能:

取消订阅一个或多个警报.参数为有效的信号名.



REMOVEALL存储

没有参数

功能:

取消所有订阅的警报.



SET_DEFAULTS存储

原型:

SET_DEFAULTS(event_polling_in_seconds)

功能:

设置事件轮询时间,默认是5秒.如果你增加时间,可能会遗漏信号.



SIGNAL存储

原型:

SIGNAL(signal_name, signal_message)

功能:

发送信号.

注意信号名不能超过30个字符.

signal_message不能超过1800字节.



想详细了解DBMS_ALERT的,请查看官方文档:

http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_alert.htm#CHDCFHCI



DBMS_ALERT包的使用



建立触发器来发送信号警报
12:14:39 SCOTT@orcl> --建立警报信息表
14:17:43 SCOTT@orcl> CREATE TABLE messages_alerts(
14:17:43   2  MESSAGE VARCHAR2(50)
14:17:43   3  );

表已创建。

已用时间:  00: 00: 00.70
--创建触发器来发送信号警报
14:17:44 SCOTT@orcl> CREATE OR REPLACE TRIGGER signal_emp
14:17:51   2    AFTER INSERT OR UPDATE OR DELETE OF empno, ename, sal, deptno ON emp_bak
14:17:51   3    FOR EACH ROW
14:17:51   4  BEGIN
14:17:51   5    IF :old.empno IS NULL THEN
14:17:51   6      -- Check for no previous row - an inserts.
14:17:51   7      -- 发送插入数据信号警报
14:17:51   8      DBMS_ALERT.SIGNAL('EVENT_MESSAGE_QUEUE'
14:17:51   9                       ,:new.ename || ':Insert');
14:17:51  10      INSERT INTO messages_alerts VALUES (:new.ename || '[:Insert]');
14:17:51  11    ELSIF :new.empno IS NULL THEN
14:17:51  12      -- Check for no current row - a deletes.
14:17:51  13      -- 发送删除数据信号警报
14:17:51  14      DBMS_ALERT.SIGNAL('EVENT_MESSAGE_QUEUE'
14:17:51  15                       ,:old.ename || ':Delete');
14:17:51  16      INSERT INTO messages_alerts VALUES (:old.ename || '[:Delete]');
14:17:51  17    ELSE ---- 发送更新数据信号警报
14:17:51  18      IF :new.ename IS NULL THEN DBMS_ALERT.SIGNAL('EVENT_MESSAGE_QUEUE',:new.ename ||':Update#1');
14:17:51  19      INSERT INTO messages_alerts VALUES (:new.ename || '[Update#1]');
14:17:51  20    ELSE
14:17:51  21      DBMS_ALERT.SIGNAL('EVENT_MESSAGE_QUEUE'
14:17:51  22                       ,:old.ename || ':Update#2');
14:17:51  23      INSERT INTO messages_alerts
14:17:51  24      VALUES
14:17:51  25        (:old.ename || '[:Update#2]');
14:17:51  26    END IF;
14:17:51  27  END IF;
14:17:51  28  END;
14:17:52  29  /

触发器已创建

已用时间:  00: 00: 00.48
14:17:53 SCOTT@orcl> insert into emp_bak(empno,ename) values(999,'Cryking');

已创建 1 行。

已用时间:  00: 00: 00.32
14:19:01 SCOTT@orcl> delete from emp_bak where empno=7788;

已删除 1 行。

已用时间:  00: 00: 00.00
14:19:43 SCOTT@orcl> update emp_bak set ename=ename||'123' where empno=999;

已更新 1 行。

已用时间:  00: 00: 00.00
14:20:20 SCOTT@orcl> select * from messages_alerts;

MESSAGE
--------------------------------------------------
Cryking[:Insert]
SCOTT[:Delete]
Cryking[:Update#2]

已选择3行。

已用时间:  00: 00: 00.00





注册感兴趣的警报
--注意是在不同用户下了,注册'EVENT_MESSAGE_QUEUE'信号警报
14:24:52 CRY@orcl> BEGIN
14:24:58   2  DBMS_ALERT.REGISTER('EVENT_MESSAGE_QUEUE');
14:24:58   3  END;
14:24:59   4  /

PL/SQL 过程已成功完成。

已用时间:  00: 00: 00.06





好了,让我们来看一下警报发送的流程.(基于上面的触发器)

先在CRY用户下执行匿名块,来等待获取信号警报
14:25:00 CRY@orcl> DECLARE
14:26:35   2    -- Define OUT mode variables required from WAITONE.
14:26:35   3    message VARCHAR2(30 CHAR);
14:26:35   4    status  INTEGER;
14:26:35   5  BEGIN
14:26:35   6    -- Register interest in an alert.
14:26:35   7    DBMS_ALERT.WAITONE('EVENT_MESSAGE_QUEUE', message, status, 30);
14:26:35   8    IF (STATUS <> 0) THEN
14:26:35   9      DBMS_OUTPUT.PUT_LINE('A timeout has happened.');
14:26:35  10    ELSE
14:26:35  11      DBMS_OUTPUT.PUT_LINE('Alert Messages Received');
14:26:35  12      DBMS_OUTPUT.PUT_LINE('-----------------------');
14:26:35  13      DBMS_OUTPUT.PUT_LINE(message);
14:26:35  14    END IF;
14:26:35  15  END;
14:26:36  16  /





此时会一直等待,直到超时,超时时间为30秒.

新开SQL*PLUS窗口
--向表插入数据,触发触发器发送信号警报
14:24:52 SCOTT@orcl> insert into emp_bak(empno,ename) values(900,'Cryking0');

已创建 1 行。

已用时间:  00: 00: 00.01
--注意要提交才会发送信号警报
14:26:54 SCOTT@orcl> commit;

提交完成。

已用时间:  00: 00: 00.00



此时在原来CRY用户的窗口下出现
14:25:00 CRY@orcl> DECLARE
14:26:35   2    -- Define OUT mode variables required from WAITONE.
14:26:35   3    message VARCHAR2(30 CHAR);
14:26:35   4    status  INTEGER;
14:26:35   5  BEGIN
14:26:35   6    -- Register interest in an alert.
14:26:35   7    DBMS_ALERT.WAITONE('EVENT_MESSAGE_QUEUE', message, status, 30);
14:26:35   8    IF (STATUS <> 0) THEN
14:26:35   9      DBMS_OUTPUT.PUT_LINE('A timeout has happened.');
14:26:35  10    ELSE
14:26:35  11      DBMS_OUTPUT.PUT_LINE('Alert Messages Received');
14:26:35  12      DBMS_OUTPUT.PUT_LINE('-----------------------');
14:26:35  13      DBMS_OUTPUT.PUT_LINE(message);
14:26:35  14    END IF;
14:26:35  15  END;
14:26:36  16  /
Alert Messages Received
-----------------------
Cryking0:Insert

PL/SQL 过程已成功完成。
已用时间:  00: 00: 24.86



成功获取到发送到的信号警报.

以上为一个基本的跨用户信号警报发送、接收流程.
注意如果发生了多个信号警报,CRY用户下只会收到最后一个信号警报.(基于事务控制的管道的缺点)

DBMS_ALERT操作和DBMS_PIPE相似.单个的信号进入到私有管道(像一个本地缓冲区),就像本地缓冲区一样.

这个私有管道只能保存一个信号值.所以接收者只能收到一个事务中最后一个信号警报.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-252623-1-1.html 上篇帖子: oracle 执行计划获取的几种方式 下篇帖子: ORACLE学习笔记系列(14)聚合函数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表