Oracle 高级队列(AQ)

适用对象:初步了解oracle高级队列人群

注意事项:

序号

注意事项

1

JMS监听部分可参考官方文档:

http://docs.oracle.com/cd/e12839_01/web.1111/e13738/aq_jms.htm#jmsad565

2

JMS监听部分基本参照以下网站内容:

http://blog.csdn.net/scorpio3k/article/details/49406209

3

本文仅为按作者本身的项目经历编写,不包含全部oracle高级队列功能

目录

Oracle 高级队列(AQ). 0

一.前言... 3

二.功能概述... 3

三.创建Oracle高级队列... 4

1.Oracle高级队列所需权限... 4

2.创建队列结构—TYPE. 4

3.创建队列表... 5

4.创建队列... 5

5.队列管理... 5

6.队列创建管理完整步骤... 7

四.JMS监听并处理Oracle 高级队列... 10

1. 准备工作:. 10

2. 创建连接参数类:. 10

3. 创建消息转换类:. 10

4. 主类进行消息处理:. 11

1 前言

一般系统的应用可以分为:立即要执行和可以延迟要执行的事情,区分这个很重要。为了提高系统的性能,缩短系统等待时间,引入队列技术。

队列是一种能将应用程序的处理工作有效地划分为前台任务和后台任务的技术。当处理容量允许时,这种技术通过存储消息、确定消息处理的优先顺序和向应用程序提交消息来发挥作用。它使你能够平衡本地计算机的负荷,或将任务分配到远程计算机。

为了减少用户的等待时间,应用程序可以让说明需要后台处理的消息排入队列。然后就可以从页面的呈递过程中去掉该处理任务。由一个后台进程来读取并队列处理这些消息,或者甚至可以交由一个单独的系统来处理它们。

队列可以实现各个系统之间的数据共享,消息通信。

2 功能概述

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

Oracle高级队列有一下好处:

(1)高级队列管理是Oracle数据库的一个特性,它提供消息队列管理功能。这是一个非常可靠、安全和可伸缩的消息管理系统,因为它使用与其他基于Oracle技术的应用程序相同的数据库特性。

(2)高级队列管理的一个很大优点是它可以通过pl/sql、java或c来访问,这样你就可以把来自一个java servlet的消息入队列和使pl/sql存储过程中的相同消息出队列。

(3)高级队列管理的另一个优点是你可以利用这一软件通过Oracle net services (sql*net)、http(s)和smtp,在远程节点之间传播消息。高级队列甚至可以通过消息网关与非Oracle的消息管理系统(如ibm mqseries)相集成。

(4)Oracle高级队列管理提供了单消费者队列和多消费者队列。单消费者队列只面向单一的接收者。多消费者队列可以被多个接收者使用。当把消息放入多消费者队列时,应用程序的程序员必须显式地在消息属性中指定这些接收者,或者建立决定每条消息的接收者的基于规则的订阅过程。

Oracle 高级队列具体开发步骤如下:

(1)首先确定应用的需求,是否适合使用高级队列?使用高级队列预计提高性能的预期值

(2)赋予数据库账户相应aq权限。

(3)确定队列包体结构,即创建type。

(4)创建队列表及队列。

(5)队列管理

3 创建Oracle高级队列

3.1 Oracle高级队列所需权限

赋予权限和角色:

grant connect, resource to账户名;

grant aq_user_role to账户名;

grant aq_administrator_role to 账户名;

grant execute on sys.dbms_aqadm to账户名;

grant execute on sys.dbms_aq to账户名;

grant execute on sys.dbms_aqin to账户名;

grant execute on sys.dbms_aqjms to账户名;

3.2 创建队列结构—TYPE

create or replace type 类型名称 as object

(

字段一     字段类型,

字段二     字段类型,

字段三     字段类型,

字段四     字段类型,

…………………………

字段n      字段类型

);

3.3 创建队列表

begin

sys.dbms_aqadm.create_queue_table

(

queue_table        => '队列表名',

queue_payload_type => ' type类型',            --之前定义的type类型

sort_list          => 'priority,enq_time',    --按优先级和入列时间排序

multiple_consumers => false,                  --多消费者

comment            => '自己加注解',

auto_commit        => false                   --手动控制事务

);

end;

3.4 创建队列

begin

sys.dbms_aqadm.create_queue

(

queue_name     => '队列名',

queue_table    => '队列表名',                      --之前创建的队列表

queue_type     => sys.dbms_aqadm.normal_queue,

max_retries    => 3,                               --取队列失败后重试次数

retry_delay    => 1,                               --重试前等待

retention_time => 0                                 --取队列后保持时间,不保持

);

end;

3.5 队列管理

3.5.1 启动队列:

begin

sys.dbms_aqadm.start_queue

(queue_name => '队列名',enqueue => true ,dequeue => true );

end;

3.5.2 插入队列:

declare

v_message    队列类型(type);

v_msgid      raw(16);

v_options    dbms_aq.enqueue_options_t;

v_properties dbms_aq.message_properties_t;

v_recipients dbms_aq.aq$_recipient_list_t;

begin

v_message := task_c(字段一  => 字符串,

字段二  => 字符串,

字段三  => 字符串,

字段四  => 字符串,

………………………

字段n  => 字符串);

v_properties.priority :=数字;                   --该消息的优先级别,默认为1

v_options.visibility  := dbms_aq.immediate;     --立即入列

dbms_aq.enqueue(queue_name         => '队列名',

enqueue_options    => v_options,

message_properties => v_properties,

payload            => v_message,

msgid              => v_msgid);

end;

3.5.3 暂停队列:

begin

sys.dbms_aqadm.stop_queue ( queue_name => '队列名');

end;

3.5.4 删除队列:

begin

sys.dbms_aqadm.drop_queue ( queue_name => '队列名');

end;

3.5.5 删除队列表:

begin

sys.dbms_aqadm.drop_queue_table (queue_table   =>  '队列表名');

end;

3.6 队列创建管理完整步骤

在aquser账户中创建高级队列,高级队列结构为callid,msg_id,report_time,sms_report,respurl,send_times,队列名称为sms_queue。

开发步骤:

(1)赋予权限:

grant connect, resource to aquser;

grant aq_user_role to aquser;

grant aq_administrator_role to aquser;

grant execute on sys.dbms_aqadm to aquser;

grant execute on sys.dbms_aq to aquser;

grant execute on sys.dbms_aqin to aquser;

grant execute on sys.dbms_aqjms to aquser;

(2)创建队列结构(type):

create or replace type sms_queue_type as object

(

callid      varchar2(1024),

msg_id      varchar2(1024),

report_time varchar2(1024),

sms_report  varchar2(1024),

respurl     varchar2(1024),

send_times  varchar2(1024)

);

(3)创建队列表:

begin

sys.dbms_aqadm.create_queue_table

(

queue_table        => 'sms_queue_table',

queue_payload_type => 'sms_queue_type',

sort_list          => 'priority,enq_time',

multiple_consumers => false,

comment            => 'queue for test',

auto_commit        => false

);

end;

(4)创建队列:

begin

sys.dbms_aqadm.create_queue

(

queue_name     => 'sms_queue',

queue_table    => 'sms_queue_table',

queue_type     => sys.dbms_aqadm.normal_queue,

max_retries    => 3,

retry_delay    => 1,

retention_time => 0

);

end;

(5)启动队列:

begin

sys.dbms_aqadm.start_queue

(queue_name => 'sms_queue',enqueue => true ,dequeue => true );

end;

(6)建立入队存储:

CREATE OR REPLACE procedure sms_enqueue(in_callid      varchar2,

in_msg_id      varchar2,

in_report_time varchar2,

in_sms_report  varchar2,

in_respurl     varchar2,

in_send_times  number,

out_result     out varchar2,

out_sqlerrm    out varchar2) as

/*声明变量*/

v_Message    SMS_QUEUE_TYPE;

v_MsgId      RAW(16);

v_options    DBMS_AQ.ENQUEUE_OPTIONS_T;

v_properties DBMS_AQ.MESSAGE_PROPERTIES_T;

v_Recipients DBMS_AQ.AQ$_RECIPIENT_LIST_T;

v_sqlerrm    varchar2(512);

begin

/*对列字段赋值*/

v_Message := SMS_QUEUE_TYPE(callid      => in_callid,

msg_id      => in_msg_id,

report_time => in_report_time,

sms_report  => in_sms_report,

respurl     => in_respurl,

send_times  => in_send_times);

/*让消息立即进入队列*/

v_options.visibility := DBMS_AQ.IMMEDIATE;

/*入队操作*/

dbms_aq.enqueue(queue_name         => 'sms_queue',

enqueue_options    => v_options,

message_properties => v_properties,

payload            => v_Message,

msgid              => v_MsgId);

/*异常处理*/

exception

WHEN OTHERS THEN

v_sqlerrm   := SQLERRM;

out_result  := '-1';

out_sqlerrm := v_sqlerrm;

end;

(6)删除队列:

begin

sys.dbms_aqadm.stop_queue ( queue_name => 'sms_queue');

end;

begin

sys.dbms_aqadm.drop_queue ( queue_name => 'sms_queue');

end;

begin

sys.dbms_aqadm.drop_queue_table (queue_table   =>  'sms_queue_table');

end;

drop type voicechange.sms_queue_type;

4 JMS监听并处理Oracle 高级队列

4.1 准备工作:

Java使用JMS进行相应的处理,需要使用Oracle提供的jar,在Oracle安装目录可以找到:在linux中可以使用find命令进行查找,例如:find `pwd` -name 'jmscommon.jar'

需要的jar为:

app/oracle/product/12.1.0/dbhome_1/rdbms/jlib/jmscommon.jar

app/oracle/product/12.1.0/dbhome_1/jdbc/lib/ojdbc7.jar

app/oracle/product/12.1.0/dbhome_1/jlib/orai18n.jar

app/oracle/product/12.1.0/dbhome_1/jlib/jta.jar

app/oracle/product/12.1.0/dbhome_1/rdbms/jlib/aqapi_g.jar

4.2 创建连接参数类:

实际使用时可以把参数信息配置在properties文件中,使用spring进行注入。

package org.kevin.jms;

c class JmsConfig

{

public String username = "数据库账户名";

public String password = "数据库账户密码";

public String jdbcUrl = "jdbc:oracle:thin:@数据库TNS:端口号:名称";

public String queueName = "监听的队列名称";

}

4.3 创建消息转换类:

package org.kevin.jms;

import java.sql.SQLException;

import oracle.jdbc.driver.OracleConnection;

import oracle.jdbc.internal.OracleTypes;

import oracle.jpub.runtime.MutableStruct;

import oracle.sql.CustomDatum;

import oracle.sql.CustomDatumFactory;

import oracle.sql.Datum;

import oracle.sql.STRUCT;

@SuppressWarnings("deprecation")

public class QUEUE_MESSAGE_TYPE implements CustomDatum, CustomDatumFactory {

public static final String _SQL_NAME = "QUEUE_MESSAGE_TYPE";

public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

MutableStruct _struct;

// 12表示字符串

static int[] _sqlType = { 12 };

static CustomDatumFactory[] _factory = new CustomDatumFactory[1];

static final QUEUE_MESSAGE_TYPE _MessageFactory = new QUEUE_MESSAGE_TYPE();

public static CustomDatumFactory getFactory() {

return _MessageFactory;

}

public QUEUE_MESSAGE_TYPE() {

_struct = new MutableStruct(new Object[1], _sqlType, _factory);

}

public Datum toDatum(OracleConnection c) throws SQLException {

return _struct.toDatum(c, _SQL_NAME);

}

public CustomDatum create(Datum d, int sqlType) throws SQLException {

if (d == null)

return null;

QUEUE_MESSAGE_TYPE o = new QUEUE_MESSAGE_TYPE();

o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);

return o;

}

public String getContent() throws SQLException {

return (String) _struct.getAttribute(0);

}

}

4.4 主类进行消息处理:

package org.kevin.jms;

import java.util.Properties;

import javax.jms.Message;

import javax.jms.MessageConsumer;

import javax.jms.MessageListener;

import javax.jms.Queue;

import javax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.Session;

import oracle.jms.AQjmsAdtMessage;

import oracle.jms.AQjmsDestination;

import oracle.jms.AQjmsFactory;

import oracle.jms.AQjmsSession;

public class Main {

public static void main(String[] args) throws Exception {

JmsConfig config = new JmsConfig();

QueueConnectionFactory queueConnectionFactory = AQjmsFactory.getQueueConnectionFactory(config.jdbcUrl,

new Properties());

QueueConnection conn = queueConnectionFactory.createQueueConnection(config.username, config.password);

AQjmsSession session = (AQjmsSession) conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

conn.start();

Queue queue = (AQjmsDestination) session.getQueue(config.username, config.queueName);

MessageConsumer consumer = session.createConsumer(queue, null, QUEUE_MESSAGE_TYPE.getFactory(), null, false);

consumer.setMessageListener(new MessageListener() {

@Override

public void onMessage(Message message) {

System.out.println("ok");

AQjmsAdtMessage adtMessage = (AQjmsAdtMessage) message;

try {

QUEUE_MESSAGE_TYPE payload = (QUEUE_MESSAGE_TYPE) adtMessage.getAdtPayload();

System.out.println(payload.getContent());

} catch (Exception e) {

e.printStackTrace();

}

}

});

Thread.sleep(1000000);

}

}

oracle 队列的更多相关文章

  1. Oracle队列实现

    Oracle队列实现 -- 核心技术点:for update 创建测试表 create table t ( id       number primary key, processed_flag va ...

  2. Oracle AWR报告指标全解析-11011552

    1-5 Top 5 Timed EventsWaits : 该等待事件发生的次数, 对于DB CPU此项不可用Times : 该等待事件消耗的总计时间,单位为秒, 对于DB CPU 而言是前台进程所消 ...

  3. oracle 11g RAC 的一些基本概念(四)

    RAC   在Grid Infrastructure安装完以后,我们把注意力转移到集群上的Oracle软件的安装上来.我们看到,Grid Infrasctructure提供了运行RAC的框架,包括集群 ...

  4. oracle AWR详解

    原文地址:https://blog.csdn.net/elvis_lfc/article/details/52326148 啥是AWR? =============================== ...

  5. JMS监听Oracle AQ

    该文档中,oracle版本为11g,jdk版本1.8,java项目为maven构建的springboot项目,springboot的版本为2.1.6,并使用了定时任务来做AQ监听的重连功能,解决由于外 ...

  6. ODAC(V9.5.15) 学习笔记(二)控件列表

    ODAC的控件有26个,简单介绍如下: TOraSession  管理Oracle的连接  TOraQuery  使用SQL进行数据获取,自动将更新提交数据库  TSmartQuery    在处理字 ...

  7. 2007-10的PWX OracleCdc问题解答

    1. 捕获增量的底层机制是什么?(例如日志.触发器.LogMiner) PWX利用Oracle的LogMiner来提取来自于Oracle的增量, LogMiner是由Oracle数据库提供的,如果当前 ...

  8. oracle实例恢复之检查点队列

    chain即链. oracle中链有很多种,LRU.LRUW.checkpoint queue等,都是干什么的呢??? LRU将可用块(干净的块)串起来.LRUW将脏块串起来,指导DBWR进程率先将冷 ...

  9. Oracle 中的作业队列和队列调度

    一,启动执行作业的进程       在 Oracle 中,是使用 “作业队列协调进程(CJQ0)” 这个协调数据库实例的作业队列的后台进程,来监视作业队列中的作业表(JOB$),并启动作业队列进程(J ...

随机推荐

  1. jquery中获取元素的几种方式小结

    1 从集合中通过指定的序号获取元素 html: 复制代码代码如下: <div> <p>0</p> <p>1</p> <p>2&l ...

  2. (dp)343. Integer Break

    Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...

  3. flume 读取tcp写到hdfs

    # Please paste flume.conf here. Example: # Sources, channels, and sinks are defined per # agent name ...

  4. 第一篇英文短文《It All Starts With A Dream》

    http://www.ximalaya.com/#/17209107/sound/6883165 Dreaming. Do you or don’t you? Do you dream about t ...

  5. Java多线程之并发协作生产者消费者设计模式

    两个线程一个生产者个一个消费者 需求情景 两个线程,一个负责生产,一个负责消费,生产者生产一个,消费者消费一个 涉及问题 同步问题:如何保证同一资源被多个线程并发访问时的完整性.常用的同步方法是采用标 ...

  6. Stanford CS1 Compilers PA2J notes

    [题记·碎碎念] 斯坦福这门Compilers原本放在Coursera上,当年错过档期很是可惜,后来发现他们自己的MOOC站放了一个self paced版本,真是普大喜奔,趁着放假有空学学. 这门课的 ...

  7. 庆祝下:iOS 开发者企业级计划(299美元/年帐户+邓白氏码免费) 和 Windows Phone公司应用(公司帐户99美元+Symantec企业证书299美元/年))顺利发布成功

    时间:2013-11-15,地址:http://192.168.0.8  网站可下载三个终端应用直接安装IOS,Windows Phone,Android iOS: 企业版IDP通过 iTunes.使 ...

  8. tls/ssl证书生成和格式转换

    生成密钥:openssl genrsa -out my.key 2048 生成csr申请文件:openssl req -sha256 -new -key my.key -out my.csr 生成自签 ...

  9. js中array的filter用法

    function bouncer(arr) { // Don't show a false ID to this bouncer. arr = arr.filter(function(val) { i ...

  10. Monkey基础

    一.Monkey工具简介 Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序 ...