Oracle高级队列 - 出列提交/回滚

时间:2017-07-25 10:38:15

标签: c# .net oracle transactions advanced-queuing

我们正在尝试使用Oracle AQ为.NET 4.7中的应用程序构建排队系统。

基本上,我们的问题是我们希望将dequeueing进程包装在包含其他指令的高级事务中,并且能够在执行queue.Dequeue()指令后“手动”提交或回滚。

到目前为止,这仅适用于Enqueueing:

using (var tr = con.BeginTransaction())
{
    try
    {
        enqMsg.SenderId = new OracleAQAgent("SUBSCRIBER1");
        enqMsg.Payload = new OracleXmlType(con, new XDocument(
            new XElement("workflowexecution",
                new XElement("id", i),
                new XElement("workflowname", Guid.NewGuid().ToString().Substring(0, 8)),
                new XElement("requestsource", Guid.NewGuid().ToString().Substring(0, 6)))).ToString());

        queue.Enqueue(enqMsg);

        //Other instructions here...

        tr.Commit();
    }
    catch (Exception)
    {
        tr.Rollback();
    }
}

采用相同的方法,我们正在尝试执行

queue.Dequeue()

然后提交或回滚,但这似乎不起作用。这是Dequeueing片段:

//Queue declaration
queue = new OracleAQQueue("QueueName", con)
{
    MessageType = OracleAQMessageType.Xml,
    NotificationConsumers = new[] { "SUBSCRIBER1" },
    DequeueOptions =
    {
        ConsumerName = "SUBSCRIBER1",
        DequeueMode = OracleAQDequeueMode.Remove,
        Visibility = OracleAQVisibilityMode.OnCommit,
    }
};

//Dequeueing process
using (var tr = con.BeginTransaction())
{
    try
    {
        OracleAQMessage _deqMsg = queue.Dequeue();

        //read the payload 
        var reader = _deqMsg?.Payload as XmlTextReader;

        if (reader != null)
        {
            reader.Read();
            Console.WriteLine("Received message from queue: " + reader.ReadOuterXml());
        }                     

        //Further instructions...
        tr.Commit();
    }
    catch (Exception ex)
    {
        tr.Rollback();
    }
}

Dequeueing始终提交事务并从队列中永久删除消息,即使在执行Rollback而不是Commit时也是如此。任何人都知道为什么它不与Dequeueing合作?

2 个答案:

答案 0 :(得分:0)

在交易开始后设置出队选项或将其传递给queue.Dequeue()

答案 1 :(得分:0)

Oracle 队列有一个属性是 max_retries。一旦达到此数量,如果事务回滚,消息将从队列中删除并添加到异常队列中。 我在 Internet 上的某个地方读到,默认情况下该值为 5,并且在测试我创建的队列(Oracle 数据库 11.2.0.1.0 SE)时确认了这一点。因此,默认情况下,似乎在尝试出列 5 次后,消息将从正常队列中删除并添加到其异常队列中。这是oracle手册中属性max_retries的定义。

<块引用>

限制可以尝试使用 REMOVE 模式对消息进行出队的次数。 max_retries 的最大值为 2**31 -1。

<块引用>

如果 RETRY_COUNT 大于 MAX_RETRIES,则消息将移至异常队列。当应用程序在执行出队后发出回滚时,RETRY_COUNT 会增加。如果出队事务因服务器进程终止(包括 ALTER SYSTEM KILL SESSION)或实例上的 SHUTDOWN ABORT 而失败,则 RETRY_COUNT 不会增加。

<块引用>

请注意,所有单消费者队列和兼容 8.1 或更高版本的多消费者队列都支持 max_retries,但不支持兼容 8.0 的多消费者队列。

来源:https://docs.oracle.com/database/121/ARPLS/d_aqadm.htm#ARPLS109