2

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

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

到目前为止,这只适用于入队:

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()

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

//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();
    }
}

出队总是提交事务并从队列中永久删除消息,即使在执行回滚而不是提交时也是如此。任何人都知道为什么它不能与出队一起使用?

4

2 回答 2

0

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

于 2018-02-17T00:34:09.417 回答
0

Oracle 队列有一个属性是 max_retries. 一旦达到这个数字,如果事务被回滚,消息将从队列中移除并添加到异常队列中。我在互联网上的某个地方读到,默认情况下此值为 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

于 2021-05-11T00:54:55.210 回答