oracle 11g PL/SQL Programming学习十二
来源:互联网 发布:92式重机枪 知乎 编辑:程序博客网 时间:2024/06/06 07:06
----------------------------------------------------------------------------
-----------------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_emp14:17:51 2 AFTER INSERT OR UPDATE OR DELETE OF empno, ename, sal, deptno ON emp_bak14:17:51 3 FOR EACH ROW14:17:51 4 BEGIN14:17:51 5 IF :old.empno IS NULL THEN14: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 THEN14: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 ELSE14:17:51 21 DBMS_ALERT.SIGNAL('EVENT_MESSAGE_QUEUE'14:17:51 22 ,:old.ename || ':Update#2');14:17:51 23 INSERT INTO messages_alerts14:17:51 24 VALUES14: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.4814:17:53 SCOTT@orcl> insert into emp_bak(empno,ename) values(999,'Cryking');已创建 1 行。已用时间: 00: 00: 00.3214:19:01 SCOTT@orcl> delete from emp_bak where empno=7788;已删除 1 行。已用时间: 00: 00: 00.0014:19:43 SCOTT@orcl> update emp_bak set ename=ename||'123' where empno=999;已更新 1 行。已用时间: 00: 00: 00.0014: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> BEGIN14: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> DECLARE14: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 BEGIN14: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) THEN14:26:35 9 DBMS_OUTPUT.PUT_LINE('A timeout has happened.');14:26:35 10 ELSE14: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> DECLARE14: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 BEGIN14: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) THEN14:26:35 9 DBMS_OUTPUT.PUT_LINE('A timeout has happened.');14:26:35 10 ELSE14: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:InsertPL/SQL 过程已成功完成。已用时间: 00: 00: 24.86
成功获取到发送到的信号警报.
以上为一个基本的跨用户信号警报发送、接收流程.
注意如果发生了多个信号警报,CRY用户下只会收到最后一个信号警报.(基于事务控制的管道的缺点)
DBMS_ALERT操作和DBMS_PIPE相似.单个的信号进入到私有管道(像一个本地缓冲区),就像本地缓冲区一样.
这个私有管道只能保存一个信号值.所以接收者只能收到一个事务中最后一个信号警报.
- oracle 11g PL/SQL Programming学习十二
- oracle 11g PL/SQL Programming学习一
- oracle 11g PL/SQL Programming学习二
- oracle 11g PL/SQL Programming学习三
- oracle 11g PL/SQL Programming学习四
- oracle 11g PL/SQL Programming学习五
- oracle 11g PL/SQL Programming学习六
- oracle 11g PL/SQL Programming学习七
- oracle 11g PL/SQL Programming学习八
- oracle 11g PL/SQL Programming学习九
- oracle 11g PL/SQL Programming学习十
- oracle 11g PL/SQL Programming学习十一
- oracle 11g PL/SQL Programming学习十三
- oracle 11g PL/SQL Programming学习十四
- oracle 11g PL/SQL Programming学习十五
- oracle 11g PL/SQL Programming学习十六
- oracle 11g PL/SQL Programming学习十七
- Oracle Database 11g PL/SQL Programming
- myeclipse编辑新字母就会覆盖掉后面的字母解决方法
- 开源框架:Alcatraz
- 使用DLL文件中封装的窗口
- Java 反射的使用
- 关于oracle和sqlserver中创建uuid的方法以及级联查询的使用
- oracle 11g PL/SQL Programming学习十二
- Linux学习笔记二:gvim初步配置和man手册安装
- WordPress的RSS订阅优化
- opencv中的人脸检测
- 牡丹江四省赛总结
- Building Web Apps in WebView
- 将"3-4.5/6*7"之类的式子字符提取出数字
- 比较两个字符串的大小
- 我把think in java看了几次