oracle 队列表

来源:互联网 发布:电子电路仿真软件下载 编辑:程序博客网 时间:2024/06/06 12:24
---oracle 队列表


    第一次接触这玩意,发现网上介绍它的资料也不多,找到一篇前辈的博客,比较详细,但过程太长,乍读不易理解,
故写结合他的文章,及自己的测试和官方文档上的一些资料整理成本文。不妥之处,忘指正。(对这玩意也没什么实际的使用经验,只是将测试的过程整理下来)


一、概述
 前言
1、一般系统的应用可以分为:立即要执行和可以延迟要执行的事情,区分这个很重要。 
为了提高系统的性能,缩短系统等待时间,引入队列技术。 
队列是一种能将应用程序的处理工作有效地划分为前台任务和后台任务的技术。当处理容量允许时,这种技术通过存储消息、确定消息处理的优先顺序和向应用程序
提交消息来发挥作用。它使你能够平衡本地计算机的负荷,或将任务分配到远程计算机。 为了减少用户的等待时间,应用程序可以让说明需要后台处理的消息排入队
列。然后就可以从页面的呈递过程中去掉该处理任务。由一个后台进程来读取并队列处理这些消息,或者甚至可以交由一个单独的系统来处理它们。 
队列可以实现各个系统之间的数据共享,消息通信。 


2、功能概述 
书写本文的目的:利用oracle高级队列实现pl/sql代码,为其它语言实现高级队列的功能作接口。 


Oracle高级队列有一下好处: 
a 高级队列管理是Oracle数据库的一个特性,它提供消息队列管理功能。这是一个非常可靠、安全和可伸缩的消息管理系统,因为它使用与其他基于Oracle技术的应用程序相同的数据库特性。 
b 高级队列管理的一个很大优点是它可以通过PL/SQL、Java或C来访问,这样你就可以把来自一个Java servlet的消息入队列和使PL/SQL存储过程中的相同消息出队列。 
c 高级队列管理的另一个优点是你可以利用这一软件通过Oracle Net Services (SQL*Net)、HTTP(S)和SMTP,在远程节点之间传播消息。高级队列甚至可以通过消息网关与非Oracle的消息管理系
  统(如IBM MQSeries)相集成。 
d Oracle高级队列管理提供了单消费者队列和多消费者队列。单消费者队列只面向单一的接收者。多消费者队列可以被多个接收者使用。当把消息放入多消费者队列时,应用程序的程序员必须显
  式地在消息属性中指定这些接收者,或者建立决定每条消息的接收者的基于规则的订阅过程。 


3、队列的开发主要有:队列的管理和队列的操作。 
 具体开发步骤如下: 
a 首先确定应用的需求,是否适合使用高级队列?使用高级队列预计提高性能的预期值 
b 确定队列包体结构。 
c 队列管理。 
d 队列操作。 


二、实验过程(only one consumer )
I、创建相应的队列表及队列
1、授予测试用户相应的权限
Grant aq_administrator_role To testuser; 
grant execute on sys.dbms_aq To testuser; 
grant execute on sys.dbms_aq_admin To testuser; 


2、创建源数据表 并插入测试数据
CREATE table mt_struc_t 
( id number(5) ,
  name varchar2(30),
  age varchar2(30)
) ;


insert into mt_struc_t values(1,'aaa','10');
insert into mt_struc_t values(2,'bbb','20');
insert into mt_struc_t values(3,'ccc','30');


3、创建一个集合类型的对象(其实就是你所需要的队列表的表结构)
CREATE OR REPLACE Type mt_struc As Object
( id number(5) ,
  name varchar2(30),
  age varchar2(30)
) ;


4、创建队列表
begin
   sys.dbms_aqadm.create_queue_table(queue_table=>'sms_mt_tab', queue_payload_type=>'mt_struc');
end ;
  --此时你再查看该表,看看其结构与普通表有什么异同
  select * from sms_mt_tab ;


5、创建队列 (此处我直接copy过来的,每个队列有的用处也易懂)
begin 
 sys.dbms_aqadm.create_queue(queue_name=>'sms_mt_queue', queue_table=>'sms_mt_tab');
 sys.dbms_aqadm.create_queue(queue_name=>'sms_mt_queue_exception',queue_table=>'sms_mt_tab',queue_type=>sys.dbms_aqadm.EXCEPTION_QUEUE);
 sys.dbms_aqadm.create_queue(queue_name=>'sms_mt_queue_backup', queue_table=>'sms_mt_tab');
end ;


II、入队测试
1、、创建入队的存储过程,定义入队的方法
create or replace procedure proc_test_in( p_equeue_name In varchar2, --队列名单大写字母,主队列:SMS_MT_QUEUE 备份队列:SMS_MT_QUEUE_BACKUP
                                          p_body In mt_struc_t%Rowtype,--入参,记录类型,数据源头直接调用(引用类型)
                                          p_level In Number:=3, --优先级别1-5,数值越小越快
                                          p_delay In Number:=0, --入队延迟时间,单位:秒
                                          p_res_str OUT VARCHAR2, --0 成功 其它失败
                                          p_msg_id OUT Varchar2 --返回的msgid,主键
                                          )
Is
 v_enqueue_options sys.dbms_aq.enqueue_options_t;
 v_message_properties sys.dbms_aq.message_properties_t;
 v_body mt_struc;---之前定义的集合类型
 v_message_handle raw(16);
begin
 p_res_str:='正常';
 v_body:=mt_struc(p_body.id ,
                  p_body.name ,
                  p_body.age ) ;
--4设置属性和参数---
--指定异常队列
v_message_properties.exception_queue:='SMS_MT_QUEUE_EXCEPTION';
--设置优先级别
v_message_properties.priority :=p_level;
--设置延时时间--秒
v_message_properties.delay :=p_delay;
 sys.dbms_aqadm.start_queue(p_equeue_name,enqueue=>true, dequeue=> true);  --第一个参数是传进来的队列名
 sys.dbms_aq.enqueue(queue_name=>p_equeue_name,
                 enqueue_options=>v_enqueue_options,
                 message_properties=>v_message_properties,
                 payload=>v_body,
                 msgid=>v_message_handle);
  P_MSG_ID:=v_message_handle ;
  Commit;
  p_res_str:='0';
Exception
     When Others Then
               p_res_str:='异常';


Rollback;               
end proc_test_in;


2、根据实际需要,创建一个调用入入队方法的存储过程,将源表的值入队
create or replace procedure proc_test_in_call   
(   
p_equeue_name In varchar2,--队列名单大写字母,主队列:SMS_MT_QUEUE 备份队列:SMS_MT_QUEUE_BACKUP   
p_res_str out Varchar2,   
p_msg_id OUT Varchar2   
) /*   
功能:测试入队   
*/   
Is  
Cursor cur_push Is  
Select * From mt_struc_t;   
v_row_push  mt_struc_t%Rowtype;   
v_exe_res varchar2(200);   
v_message_handle raw(16);   
begin  
p_res_str:='-1';   
Open cur_push;   
Loop   
Fetch cur_push Into v_row_push;   
Exit When cur_push%Notfound;   
proc_test_in(p_equeue_name,v_row_push,3,0,v_exe_res,v_message_handle);   
End Loop;   
Close cur_push;   
p_res_str:=v_exe_res;    
p_msg_id:=v_message_handle;   
Exception   
When Others Then  
p_res_str:=Sqlerrm;   
Rollback;    
end proc_test_in_call;  


3、执行入队
declare
  p_res_str  VARCHAR2(200); --0 成功 其它失败
   p_msg_id  Varchar2 (200); --返回的msgid,主键
begin
  proc_test_in_call('sms_mt_queue',p_res_str,p_msg_id);      
  dbms_output.put_line(p_res_str ||''||p_msg_id);  
end ;


---注、执行本匿名快,数据将被写入队列,此时你可以查看out参数的返回值
 以及查看队列表是否有值(以上测试成功)
select * from sms_mt_tab ; ---对列表
Select Count(1) From sms_mt_tab Where q_name='SMS_MT_QUEUE' ; --不同的队列可以控制不同的消息入队


III、出队测试(将存入队列的值拿出去,并得到相应的返回值)
1、创建出队的过程(方法)
create or replace procedure proc_test_out   
(   
p_equeue_name In varchar2, --队列名单大写字母,主队列:SMS_MT_QUEUE 备份队列:SMS_MT_QUEUE_BACKUP   
p_id Out number, 
p_name out varchar2,    
p_age out varchar2)  
Is/*   
功能: 出队列,返回给java程序   
*/   
v_Dequeue_Options Dbms_Aq.Dequeue_Options_t;   
v_Message_Properties Dbms_Aq.Message_Properties_t;   
v_Message_Handle Raw(16);   
v_Body_queue Mt_Struc;   
 
---写日志区域   
vProTip VARCHAR2(255);   
vErrorCode VARCHAR2(20);   
vErrorMsg VARCHAR2(2000);   
v_count Number; 


Begin  
  
---执行出队列操作   
Select Count(0) Into v_count From sms_mt_tab Where q_name=p_equeue_name ;   
If v_count >0 Then  
dbms_aqadm.start_queue(p_equeue_name,enqueue=>true, dequeue=> true); 
  
Dbms_Aq.Dequeue(Queue_Name => p_equeue_name,    
Dequeue_Options => v_Dequeue_Options,   
Message_Properties => v_Message_Properties,    
Payload => v_Body_queue,    
Msgid => v_Message_Handle);   


p_id := v_Body_queue.id ;  
p_name :=v_Body_queue.name ;
p_age := v_Body_queue.age ;


Commit;  
End If;  
Exception   
When Others Then  
vProTip:='出队过程异常!';   
vErrorCode:=SQLCODE;   
vErrorMsg:=SQLERRM;   
Rollback;   
end proc_test_out;  


-------------
2、出队测试(将队列返回值答应出来了,实际用的时候可以传给对应的变量)
declare
p_id number(5); 
p_name  varchar2(200);   
p_age varchar2(200);
begin
proc_test_out('SMS_MT_QUEUE',p_id,p_name,p_age);
dbms_output.put_line(p_id||' '||p_name||' '||p_age);
end ;


3、查看队列表是否有值(看每执行一次,队列表的数据是不是少了一条。)
select * from mt_struc_t ; ---普通表
select * from sms_mt_tab ; ---对列表
Select Count(1) From sms_mt_tab Where q_name='SMS_MT_QUEUE' ;


IV、关于创建队列表的语法,及选项的含义(官方文档)
Creating a Queue Table
DBMS_AQADM.CREATE_QUEUE_TABLE(
   queue_table          IN      VARCHAR2,
   queue_payload_type   IN      VARCHAR2,
   [storage_clause      IN      VARCHAR2        DEFAULT NULL,]
   sort_list            IN      VARCHAR2        DEFAULT NULL,
   multiple_consumers   IN      BOOLEAN         DEFAULT FALSE,
   message_grouping     IN      BINARY_INTEGER  DEFAULT NONE,
   comment              IN      VARCHAR2        DEFAULT NULL,
   primary_instance     IN      BINARY_INTEGER  DEFAULT 0, 
   secondary_instance   IN      BINARY_INTEGER  DEFAULT 0,
   compatible           IN      VARCHAR2        DEFAULT NULL,
   secure               IN      BOOLEAN         DEFAULT FALSE);
   
This procedure creates a queue table for messages of a predefined type. It has the following required and optional parameters:


Parameter Description 
queue_table This required parameter specifies the queue table name. 
Mixed case (upper and lower case together) queue table names are supported if database compatibility is 10.0, but the names must be enclosed in double quote marks. So abc.efg means the schema is ABC and the name is EFG, but "abc"."efg" means the schema is abc and the name is efg.


Queue table names must not be longer than 24 characters. If you attempt to create a queue table with a longer name, error ORA-24019 results.
 
queue_payload_type This required parameter specifies the payload type as RAW or an object type. See "Payload Type" for more information. 
storage_clause     This optional parameter specifies a tablespace for the queue table. See "Storage Clause" for more information. 
sort_list          This optional parameter specifies one or two columns to be used as sort keys in ascending order. It has the format sort_column1,sort_column2. See "Sort Key" for more information. 
multiple_consumers This optional parameter specifies the queue table as single-consumer or multiconsumer. The default FALSE means queues created in the table can have only one consumer for each message. TRUE means queues created in the table can have multiple consumers for each message. 
message_grouping   This optional parameter specifies whether messages are grouped or not. The default NONE means each message is treated individually. TRANSACTIONAL means all messages enqueued in one transaction are considered part of the same group and can be dequeued as a group of related messages. 
comment            This optional parameter is a user-specified description of the queue table. This user comment is added to the queue catalog. 
primary_instance   This optional parameter specifies the primary owner of the queue table. Queue monitor scheduling and propagation for the queues in the queue table are done in this instance. The default value 0 means queue monitor scheduling and propagation is done in any available instance. 
                    You can specify and modify this parameter only if compatible is 8.1 or higher.
 secondary_instance This optional parameter specifies the owner of the queue table if the primary instance is not available. The default value 0 means that the queue table will fail over to any available instance. 
                You can specify and modify this parameter only if primary_instance is also specified and compatible is 8.1 or higher.
compatible         This optional parameter specifies the lowest database version with which the queue table is compatible. The possible values are 8.0, 8.1, and 10.0. If the database is in 10.1-compatible mode, then the default value is 10.0. If the database is in 8.1-compatible or 9.2-compatible mode, then the default value is 8.1. If the database is in 8.0-compatible mode, then the default value is 8.0. The 8.0 value is deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). 
                       For more information on compatibility, see "Oracle Streams Advanced Queuing Compatibility Parameters".
secure             This optional parameter must be set to TRUE if you want to use the queue table for secure queues. Secure queues are queues for which AQ agents must be associated explicitly with one or more database users who can perform queue operations, such as enqueue and dequeue. The owner of a secure queue can perform all queue operations on the queue, but other users cannot unless they are configured as secure queue users