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 -包?)

据我所知,在此上下文中使用侦听功能(轮询排队的项目)比注册功能(在消息到达时安排操作)要好得多。

基本上一切正常,我设法:

当然,监听器应该是 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"

https://asktom.oracle.com/pls/apex/asktom.search?tag=writing-a-stand-alone-application-to-continuously-monitor-a-database-queue-aq