首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Oracle高级队列的实际情况是什么?

使用Oracle高级队列的实际情况是什么?
EN

Database Administration用户
提问于 2012-09-30 12:13:56
回答 5查看 26.4K关注 0票数 4

Oracle高级队列是实现功能需求的首选机制是什么情况?例如,从理论上讲,从银行账户A转到银行账户B的资金可能被视为两种不同的操作,并且可以单独实施--首先,将资金从账户A(更新)转入队列,然后将资金转移到帐户B(更新)。但是,显然不能这样做,因为这两个操作应该在一个一致的操作- in事务中完成。

也许只有在开发存储过程/函数以执行内部(通过DML操作和调用其他本地存储的proc/fnc)和外部(通过调用某些webservices)的逻辑时,才应该考虑高级队列。当使用这种对we服务的调用时,我们不能将其包装成一致的事务,所以唯一的方法是使用某种排队机制.

任何真实生活中的详细例子都将不胜感激。

我好奇的不是技术本身的细节,而是使用这种消息传递的真实情况,因为我以前没有这样做过。例如,为什么我需要传递一些数据(消息有效载荷)?

EN

回答 5

Database Administration用户

回答已采纳

发布于 2012-10-02 01:14:04

我用AQ

  • 数据库之间的事务
  • 实现否则需要使用触发器实现的业务规则(即必须在启动操作的同一表上执行操作)

通过使用队列,您可以执行以下操作:

  • 事务可以按您希望的顺序进行,而不是瞬间进行。例如插入一个数据库,将相同的记录复制到另一个数据库
  • 第二个事务现在独立于第一个事务,但是您仍然具有一致性。只有当第一次插入成功时,第二次AQ事务才会发生;如果第二次事务发生在另一个数据库上,则只有当第二个数据库准备好接收时才会发生。

以下是关于我如何在数据库之间使用AQ的更多信息。我不是专家,大部分代码都是从互联网上得到的。Oracle文档很长,但并没有真正帮助我。

首先创建队列:

代码语言:javascript
复制
BEGIN
  SYS.DBMS_AQADM.CREATE_QUEUE_TABLE
  (
    QUEUE_TABLE           =>        'QT_NEW_CASE'
   ,QUEUE_PAYLOAD_TYPE    =>        'FILE_ACTION'
   ,COMPATIBLE            =>        '8.1'
   ,STORAGE_CLAUSE        =>        '
                                     TABLESPACE USERS
                                     PCTUSED    0
                                     PCTFREE    10
                                     INITRANS   1
                                     MAXTRANS   255
                                     STORAGE    (
                                                 INITIAL          64K
                                                 NEXT             1M
                                                 MINEXTENTS       1
                                                 MAXEXTENTS       UNLIMITED
                                                 PCTINCREASE      0
                                                 BUFFER_POOL      DEFAULT
                                                )'
   ,SORT_LIST             =>        'ENQ_TIME'
   ,MULTIPLE_CONSUMERS    =>         FALSE
   ,MESSAGE_GROUPING      =>         0
   ,SECURE                =>         FALSE
   );
End;

在原始数据库上:

代码语言:javascript
复制
CREATE OR REPLACE TYPE FILE_ACTION                                                                                                                                                       AS OBJECT
(    ACTION VARCHAR2(20),
     CASE_ID NUMBER(10),
     OTHER VARCHAR2(20)
);

诚然,这一行动是粗糙的,但却是多才多艺的。这些要求是将从多个表到另一个数据库的更改漏斗,在数据库中需要进一步处理,而不需要接触应用程序代码。典型的调用是从触发器、其他过程或作业对包进行调用。

代码语言:javascript
复制
queue_util.add_file ('CLOSE', v_case_id,:NEW.ID);

包内

代码语言:javascript
复制
   PROCEDURE add_file_to_queue (action_in      IN VARCHAR2,
                                d_case_id_in   IN NUMBER,
                                d_other_in     IN VARCHAR2:= NULL)
   IS
      /******************************************************************************
      PURPOSE: when there is a change to a file (create, closed or reopen)  add the change to the queue of changes 
     ******************************************************************************/
      queue_options        SYS.DBMS_AQ.enqueue_options_t;
      message_properties   SYS.DBMS_AQ.message_properties_t;
      message_id           RAW (16);
      my_message           file_action;
      err_text             VARCHAR2 (2000);
      PRAGMA AUTONOMOUS_TRANSACTION;
   BEGIN
      my_message := file_action (action_in, d_case_id_in, d_other_in);
      DBMS_AQ.enqueue (queue_name           => 'NEW_CASE_QUEUE',
                       enqueue_options      => queue_options,
                       message_properties   => message_properties,
                       payload              => my_message,
                       msgid                => message_id);

      IF g_debugging
      THEN
        ;
      --insert debugging info if g_debugging is true
      END IF;

      COMMIT;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         err_text := SQLERRM;
         --logging error to another table

      WHEN OTHERS
      THEN
         err_text := SQLERRM;
         --more logging
   END add_file_to_queue;

-并将消息从队列中弹出

代码语言:javascript
复制
   PROCEDURE send_from queue (case_id_in IN NUMBER := NULL)
   IS
      /******************************************************************************
      PURPOSE:get the list of file changes and send them out
      *****************************************************************************/
      queue_options                DBMS_AQ.dequeue_options_t;
      message_properties           DBMS_AQ.message_properties_t;
      message_id                   file_action;
      v_file                       VARCHAR2 (20);
      v_case_id                    NUMBER (10);
      v_filename                   VARCHAR2 (500);
      v_action                     VARCHAR2 (20);
      v_other                      VARCHAR2 (20);
      v_err_id                     INTEGER;
      bad_data_ex EXCEPTION;
      v_err_text                   VARCHAR2 (50);

      TYPE cases_cur IS REF CURSOR;

      new_cases                    cases_cur;
   BEGIN
      IF case_id_in IS NULL
      THEN
         OPEN new_cases FOR
              SELECT   qt.msgid
                FROM   cqt_new_case qt
            ORDER BY   qt.enq_time;
      ELSE
         OPEN new_cases FOR
              SELECT   qt.msgid
                FROM   qt_new_case qt
               WHERE   qt.user_data.case_id = case_id_in
            ORDER BY   qt.enq_time;
      END IF;

      --should have added a check here to make sure
      --the other database is up and running
      LOOP
         BEGIN
            FETCH new_cases INTO   message_id;

            --reinitialize values to null
            v_case_id := NULL;
            v_filename := NULL;
            v_file := NULL;
            v_action := NULL;
            v_other := NULL;
            --to try and clear all locks
            COMMIT;
            EXIT WHEN new_cases%NOTFOUND;

            IF case_id_in IS NOT NULL
            THEN
               queue_options.deq_condition :=
                  'tab.user_data.case_id = ' || case_id_in;
            END IF;

            DBMS_AQ.dequeue (queue_name           => 'NEW_CASE_QUEUE',
                             dequeue_options      => queue_options,
                             message_properties   => message_properties,
                             payload              => my_message,
                             msgid                => message_id);
            v_case_id := my_message.case_id;
            v_action := my_message.action;
            v_other := my_message.other;

            IF v_case_id IS NOT NULL AND v_case_id > 0
            THEN
               IF g_debugging
               THEN
                 ;
               --insert your debugging information
               END IF;
            --continues on with lengthy data transforms
            --for actions like NEW, CLOSE, REOPEN
END SEND_FROM_QUEUE;

我今天当然会用不同的方式来写,但是它很有效.对于我来说,AQ的关键问题是,我从来没有在不同的数据库之间排队等待消息传递。这被描述为它的一个主要价值。然而,我仍然喜欢确保初始事务可以完成,而不考虑目标数据库的状态。如果在目标数据库中插入消息失败,则会记录错误,并发送电子邮件通知开发人员。

票数 4
EN

Database Administration用户

发布于 2012-10-01 02:51:53

我对甲骨文不像对Postgres那么熟悉。尽管如此,我将告诉您这样的排队方法是理想的(作为pg_消息_队列的作者):允许数据库事务具有非事务性的副作用,并且复杂度最小。一个简单的例子是“当我们提交一个事务,说我们已经发送了一个部件,让我们发送一封电子邮件出去通知客户。”

您可以在没有Oracle AQ的情况下做到这一点,但是Oracle AQ可能会使此变得更简单。关键因素是,这允许您对消息进行排队,以便在提交时它是可见的,并且在数据库事务提交而不是之前,消息将作为电子邮件的基础。如果您试图从事务内部发送消息,您将得到一些令人讨厌的失败案例:

  1. 如果消息发送失败,我们是否应该中止事务?
  2. 如果消息发送并随后回滚事务,我们如何取消发送电子邮件?我们不能。

另一个例子可能是松散耦合的应用程序,集成在消息队列上。每个应用程序可以在很大程度上不知道另一个应用程序的运行情况,但是当事务被提交时,消息就会发送给另一个应用程序。如果不能马上送到,没问题。我们会在有可能的时候处理它们。

因此,最基本的情况是,在许多情况下,您希望将逻辑集中在数据库周围,在这些情况下,您不能在单个事务中真正正确地完成所有事情。能够在db提交中向其他组件发送消息确实很有帮助。

当然,没有AQ,你可以自己建造一切。但它已经为你建造好了。

编辑:我在这里重读了甲骨文的文档,它们令人绝望地困惑,所以我不怪你在这里的混乱。如果我对他们谈论的事情不太熟悉的话,我就不确定我是否能跟上他们的脚步。我现在百分之百肯定,我的答案是符合目标的。

票数 7
EN

Database Administration用户

发布于 2017-01-20 17:58:28

在现实生活中,在数据库中执行特定操作时,可以使用AQ向客户发送通知。

考虑一个用户请求购买一个项目的例子。一旦收到付款,将通过在队列中填充详细信息来创建订单。此队列将有商店所有者和支付消息传递应用程序的订阅者。

因此,订阅者1,即商店所有者(任何要发送给店主的通知)将选择关于要发送的项目的消息。而另一个订户将准备关于购买商品的通知,因此在这种情况下,一旦消息被两个订户处理,订单就被标记为完整,并且队列中的消息被删除。

如果在处理订单过程中出现任何错误,将在异常队列中标记条目,然后可以在稍后处理异常队列消息。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/25161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档