dbms_aq.dequeue 应该永远循环吗?
Should dbms_aq.dequeue loop forever?
这是我使用 Oracle Advanced Queueing 的第一步...
Szenario:我有一个 运行 应用程序,其中有许多多个独立进程向中央控制器报告以处理后续步骤。简化了进程是通过 cron 或通过刚刚完成的回调启动的 process.The 回调来自远程主机,通过 http -> php -> DB,基本上是在远程进程完成后的一个 http 调用主持人。
完整的控制器逻辑是在 pl/sql 中编写的,考虑了单例概念,因此只有一个进程应该同时执行控制器逻辑。事实上,在 99% 的调用中,这是没有必要的,但这不是我目前可以改变的事情(也不是一般的架构)。
为了确保这一点,实际上有一个错误的互斥实现,伪代码
$mutex = false;
while( not $mutex )
{
$mutex = getMutex();
if( $mutex )
executeController();
else
sleep(5);
}
其中互斥量是一个单字段table,其值为 0 (=> "free") 或 1 (=> "busy" )
此 "beautiful" 构造的结果是充满 "Hey! Got no mutex! Waiting..." 的日志文件。等待的进程越多,他们等待的时间就越长,无法控制下一个进程。有时负载太重以至于 apache 首先分叉并最终死掉...
解决方案
所以我的第一个 "operation" 是用 Oracle Advanced Queuing 替换互斥锁,并将控制器作为单一使用者。好处:在 apache 层内不再有 "busy waiting",严格先到先得。
( 因为所有的 DB-Actions 都发生在同一个 oracle-schema 中,这可以通过标准对象,pl/sql-方法来实现。但是为什么要重新发明轮子,如果有 dbms -包?)
据我所知,在此上下文中使用侦听功能(轮询排队的项目)比注册功能(在消息到达时安排操作)要好得多。
基本上一切正常,我设法:
- 创建消息类型
- 创建队列-table
- 创建队列
- 开始队列
- 将 USER 添加为订阅者
- 创建入队程序
- 创建用于处理和出队的过程
- 创建一个程序来侦听队列并在消息到达时调用 "process & dequeue" 函数。
当然,监听器应该是 24/7 活动的,所以我没有指定 "wait" 时间。一般来说,根据一天中的不同时间,他至少每隔几分钟就会 "something to do",更有可能每隔几秒,有时更多。
现在这是我的问题(如果它真的是一个问题),我只是根据目前找到的例子写的:
CREATE OR REPLACE PROCEDURE demo_aq_listener IS
qlist dbms_aq.aq$_agent_list_t;
agent_w_msg sys.aq$_agent;
BEGIN
qlist(0) := sys.aq$_agent(USER, 'demo_aq_queue', NULL);
LOOP
dbms_aq.listen(agent_list => qlist, agent => agent_w_msg);
DEMO_AQ_DEQUEUE();--process & dequeue
END LOOP;
END;
/
调用该过程基本上符合我的预期:它保持 "up" 并处理排队的消息。
但这是这样做的方法吗?如果没有排队的消息,它会做什么? "Sleeping" 在 dbms_aq.listen-routine 或 "Looping as fast as it can" 中,所以我只是实现了 "busy waiting" 的另一种方式?可能有超时(可能在 oss 级别或其他地方)我只是没有达到?
这里是包含队列定义等的完整代码:demo_dbms_aq_with_listener.sql
更新
通过进一步的测试,我才意识到我似乎比我希望的更缺乏理解:(
在 "execution level" 上根本不使用侦听器,只是循环出列函数具有相同的效果:它等待 first/next 消息
CREATE OR REPLACE PROCEDURE demo_aq_listener IS
BEGIN
LOOP
DEMO_AQ_DEQUEUE();
END LOOP;<br>
END;
/
</pre>
至少这样更容易测试,只调用
BEGIN
DEMO_AQ_DEQUEUE();
END;
/
</pre>
也只是等待第一条消息。这让我完全困惑,我是否需要听众,我正在做的事情是否有任何意义:(
结论
我根本不需要监听器,因为我只有一个消费者可以以相同的方式处理所有消息。
但 key/core 问题保持不变:是否可以将 DBMS_AQ.DEQUEUE 保持在 "maybe active waiting" 循环中,因为它会整天收到消息在短时间内?
(您会在上面的链接 sql 文件中找到 DEMO_AQ_DEQUEUE())
迟到总比不到好,一切都好,就是闲着等着:
1) Whilst the DEQUEUE is in sleep mode (WAIT FOREVER), I can see the session is waiting on the event - "Streams AQ: waiting for messages in the queue", that is an IDLE wait class and not actually consuming ANY resources, correct ?
Correct. It's similar to waiting on a row lock on a table. You just "sit there"
这是我使用 Oracle Advanced Queueing 的第一步...
Szenario:我有一个 运行 应用程序,其中有许多多个独立进程向中央控制器报告以处理后续步骤。简化了进程是通过 cron 或通过刚刚完成的回调启动的 process.The 回调来自远程主机,通过 http -> php -> DB,基本上是在远程进程完成后的一个 http 调用主持人。
完整的控制器逻辑是在 pl/sql 中编写的,考虑了单例概念,因此只有一个进程应该同时执行控制器逻辑。事实上,在 99% 的调用中,这是没有必要的,但这不是我目前可以改变的事情(也不是一般的架构)。
为了确保这一点,实际上有一个错误的互斥实现,伪代码
$mutex = false;
while( not $mutex )
{
$mutex = getMutex();
if( $mutex )
executeController();
else
sleep(5);
}
其中互斥量是一个单字段table,其值为 0 (=> "free") 或 1 (=> "busy" )
此 "beautiful" 构造的结果是充满 "Hey! Got no mutex! Waiting..." 的日志文件。等待的进程越多,他们等待的时间就越长,无法控制下一个进程。有时负载太重以至于 apache 首先分叉并最终死掉...
解决方案
所以我的第一个 "operation" 是用 Oracle Advanced Queuing 替换互斥锁,并将控制器作为单一使用者。好处:在 apache 层内不再有 "busy waiting",严格先到先得。
( 因为所有的 DB-Actions 都发生在同一个 oracle-schema 中,这可以通过标准对象,pl/sql-方法来实现。但是为什么要重新发明轮子,如果有 dbms -包?)
据我所知,在此上下文中使用侦听功能(轮询排队的项目)比注册功能(在消息到达时安排操作)要好得多。
基本上一切正常,我设法:
- 创建消息类型
- 创建队列-table
- 创建队列
- 开始队列
- 将 USER 添加为订阅者
- 创建入队程序
- 创建用于处理和出队的过程
- 创建一个程序来侦听队列并在消息到达时调用 "process & dequeue" 函数。
当然,监听器应该是 24/7 活动的,所以我没有指定 "wait" 时间。一般来说,根据一天中的不同时间,他至少每隔几分钟就会 "something to do",更有可能每隔几秒,有时更多。
现在这是我的问题(如果它真的是一个问题),我只是根据目前找到的例子写的:
CREATE OR REPLACE PROCEDURE demo_aq_listener IS
qlist dbms_aq.aq$_agent_list_t;
agent_w_msg sys.aq$_agent;
BEGIN
qlist(0) := sys.aq$_agent(USER, 'demo_aq_queue', NULL);
LOOP
dbms_aq.listen(agent_list => qlist, agent => agent_w_msg);
DEMO_AQ_DEQUEUE();--process & dequeue
END LOOP;
END;
/
调用该过程基本上符合我的预期:它保持 "up" 并处理排队的消息。
但这是这样做的方法吗?如果没有排队的消息,它会做什么? "Sleeping" 在 dbms_aq.listen-routine 或 "Looping as fast as it can" 中,所以我只是实现了 "busy waiting" 的另一种方式?可能有超时(可能在 oss 级别或其他地方)我只是没有达到?
这里是包含队列定义等的完整代码:demo_dbms_aq_with_listener.sql
更新
通过进一步的测试,我才意识到我似乎比我希望的更缺乏理解:(
在 "execution level" 上根本不使用侦听器,只是循环出列函数具有相同的效果:它等待 first/next 消息
CREATE OR REPLACE PROCEDURE demo_aq_listener IS BEGIN LOOP DEMO_AQ_DEQUEUE(); END LOOP;<br> END; / </pre>
至少这样更容易测试,只调用
BEGIN DEMO_AQ_DEQUEUE(); END; / </pre>
也只是等待第一条消息。这让我完全困惑,我是否需要听众,我正在做的事情是否有任何意义:(
结论
我根本不需要监听器,因为我只有一个消费者可以以相同的方式处理所有消息。
但 key/core 问题保持不变:是否可以将 DBMS_AQ.DEQUEUE 保持在 "maybe active waiting" 循环中,因为它会整天收到消息在短时间内?
(您会在上面的链接 sql 文件中找到 DEMO_AQ_DEQUEUE())
迟到总比不到好,一切都好,就是闲着等着:
1) Whilst the DEQUEUE is in sleep mode (WAIT FOREVER), I can see the session is waiting on the event - "Streams AQ: waiting for messages in the queue", that is an IDLE wait class and not actually consuming ANY resources, correct ?
Correct. It's similar to waiting on a row lock on a table. You just "sit there"