本文基于一份十年前的测试笔记整理,完整展示了 Oracle Advanced Queuing(AQ)的配置与使用流程,旨在推广这个强大却常被忽视的 Oracle 功能模块。
一、什么是 Oracle AQ?
Oracle AQ(Advanced Queuing,高级队列)是 Oracle 数据库内置的消息队列机制,支持异步通信、可靠传输、事务一致性、跨数据库传播等特性。
它可以广泛应用于:
-
系统间消息解耦
-
异步任务处理
-
审计日志收集
-
与 JMS 接轨等场景
二、测试环境概述
-
源库(LCODUAT): Oracle 10.2.0.4,SID =
ora10204 -
目标库(LPHSUAT2): Oracle 10.2.0.4,SID =
orcl -
测试用户:
temp_admin,授予 DBA 权限 -
通信方式: 数据库链接(DBLINK)
三、基本对象定义与队列配置
-- 创建测试类型
CREATE OR REPLACE TYPE temp_admin.TEST_SAF_STDIN_TYP AS OBJECT (
fun VARCHAR2(1000),
silly NUMBER(8)
);
创建队列表和队列
BEGIN
DBMS_AQADM.CREATE_QUEUE_TABLE(
queue_table => 'TEST_SAF_STDN_TAB',
queue_payload_type => 'SYS.ANYDATA',
multiple_consumers => TRUE
);
DBMS_AQADM.CREATE_QUEUE(
queue_name => 'TEST_SAF_STDN_Q',
queue_table => 'TEST_SAF_STDN_TAB'
);
DBMS_AQADM.START_QUEUE(queue_name => 'TEST_SAF_STDN_Q');
END;
添加订阅者
DECLARE
sub SYS.AQ$_AGENT;
BEGIN
sub := SYS.AQ$_AGENT('sub1', NULL, NULL);
DBMS_AQADM.ADD_SUBSCRIBER(
queue_name => 'TEST_SAF_STDN_Q',
subscriber => sub,
delivery_mode => DBMS_AQADM.PERSISTENT
);
END;
四、消息发送与接收
Enqueue 示例(入队)
DECLARE
e_opt DBMS_AQ.ENQUEUE_OPTIONS_T;
m_prop DBMS_AQ.MESSAGE_PROPERTIES_T;
m_handle RAW(16);
message ANYDATA;
BEGIN
message := ANYDATA.CONVERTOBJECT(TEST_SAF_STDIN_TYP('testtesttest', 172));
DBMS_AQ.ENQUEUE(
queue_name => 'TEST_SAF_STDN_Q',
enqueue_options => e_opt,
message_properties => m_prop,
payload => message,
msgid => m_handle
);
COMMIT;
END;
Dequeue 示例(出队)
DECLARE
d_opt DBMS_AQ.DEQUEUE_OPTIONS_T;
m_prop DBMS_AQ.MESSAGE_PROPERTIES_T;
m_handle RAW(16);
message ANYDATA;
obj TEST_SAF_STDIN_TYP;
ret PLS_INTEGER;
BEGIN
d_opt.navigation := DBMS_AQ.FIRST_MESSAGE;
d_opt.consumer_name := 'sub1';
d_opt.wait := DBMS_AQ.NO_WAIT;
DBMS_AQ.DEQUEUE(
queue_name => 'TEST_SAF_STDN_Q',
dequeue_options => d_opt,
message_properties => m_prop,
payload => message,
msgid => m_handle
);
ret := message.GETOBJECT(obj => obj);
DBMS_OUTPUT.PUT_LINE('Stuff: ' || obj.fun || ' and ' || obj.silly);
COMMIT;
END;
五、跨库传播测试(Queue Propagation)
我们通过 DBLINK 实现两个库之间的异步消息传播:
-- 源库创建 DBLINK
CREATE DATABASE LINK LPHSUAT2
CONNECT TO temp_admin IDENTIFIED BY temp_admin
USING 'ORCL';
-- 目标库也需要反向 DBLINK
CREATE DATABASE LINK LCODUAT
CONNECT TO temp_admin IDENTIFIED BY temp_admin
USING 'ORA10204';
启用传播计划
BEGIN
DBMS_AQADM.SCHEDULE_PROPAGATION(
queue_name => 'TEST_SAF_STDN_Q',
destination => 'LPHSUAT2'
);
END;
可选:启用/禁用/修改传播计划
-- 停用
BEGIN
DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE(
queue_name => 'TEST_SAF_STDN_Q',
destination => 'LPHSUAT2'
);
END;
-- 修改调度策略
BEGIN
DBMS_AQADM.ALTER_PROPAGATION_SCHEDULE(
queue_name => 'TEST_SAF_STDN_Q',
destination => 'LPHSUAT2',
duration => '1',
next_time => 'SYSDATE + 1/1440',
latency => '32'
);
END;
-- 启用
BEGIN
DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE(
queue_name => 'TEST_SAF_STDN_Q',
destination => 'LPHSUAT2'
);
END;
六、调试与故障处理
常见问题:
-
ORA-12514: 目标库未启动或监听未识别服务名
-
J000 进程未工作: 可手动 kill 后由 PMON 重启
-
DBLINK 超时: 检查防火墙/TNS 配置/监听状态
观察视图:
-- 队列状态
SELECT * FROM dba_queues WHERE owner = 'TEMP_ADMIN';
-- 传播计划状态
SELECT * FROM dba_queue_schedules
WHERE schema = 'TEMP_ADMIN' AND qname = 'TEST_SAF_STDN_Q';
-- 消息队列内容
SELECT * FROM AQ$TEST_SAF_STDN_TAB;
七、总结与推荐
Oracle AQ 虽然已有多年历史,但在实际项目中却常被忽视。相比外部消息中间件,它具备以下优势:
-
集成度高: 无需外部组件,即可事务一致
-
可控性强: 支持复杂订阅者模型、调度机制
-
跨库通信: 原生 DBLINK 支持异步传播
-
易于管理: 系统视图和调度机制完善
适合场景:
-
核心系统间的可靠消息传递
-
异步任务的简易实现
-
审计/日志/业务事件通知等
如果你在项目中需要轻量级的消息中间件,Oracle AQ 可能就是你最不该忽略的答案。


被折叠的 条评论
为什么被折叠?



