【发布时间】:2016-06-24 14:01:48
【问题描述】:
我们的服务可以与 SQL Server 或 Oracle 后端一起使用。我们刚刚开始添加消息传递功能以允许我们的服务与仅 Oracle 的应用程序进行通信,并决定使用 NServiceBus。决定放置 NServiceBus 订阅/队列/等。在应用程序的数据库上,因此 NServiceBus 始终使用 Oracle。
当服务与 SQL Server 后端一起使用时,一切正常。但是,当我们尝试将服务与 Oracle 后端(与应用程序和 NServiceBus 使用的数据库完全分开的数据库,通常在不同的服务器上)一起使用时,我们会遇到异常。
异常详情:
- 异常文本:“连接已经是本地或分布式事务的一部分”或有时“无法加入分布式事务”(最小 VM 测试环境改为“无法加载 OraMTS”)
- 异常发生在我们的数据库层调用
connection.Open() - 连接的连接字符串是标准的
Data Source=foo;User Id=bar;Password=baz - 该服务正在使用非托管 Oracle 提供程序
- 服务在开始处理消息时使用装饰器进行连接,然后断开连接;删除装饰器并在服务启动时(在设置 NServiceBus 之前)连接服务可以解决问题,但这意味着如果该连接发生任何事情,则必须重新启动服务
异常文本让我们认为连接正在尝试加入 NServiceBus 的 TransactionScope。那是对的吗?如果是这样,是否有一些选项我们可以添加到连接字符串或在连接本身上配置以使其避免加入环境 TransactionScope?
请注意,我们在代码中使用了 BeginTransaction;我们知道它与 TransactionScope 不兼容,但我们之前的代码中从未有过 TransactionScope,也不想成为一个 TransactionScope,在任何情况下,我们的例外情况都是甚至在我们调用 BeginTransaction 之前就已经发生了。
【问题讨论】:
-
这可能是因为分布式事务协调器 (MSDTC) 没有运行,或者运行 NServiceBus 端点的用户帐户不允许使用 MSDTC。在您对自己问题的回答中,您找到了一种禁用此功能的方法,但请确保您了解其含义。几乎无法保证您的消息会安全到达或发送。您可能会开始丢失消息。
-
@DennisvanderStelt NServiceBus 将 MSDTC 列为一项要求,因此我们仔细检查了这一点。请注意,我们修改了 我们的 连接到数据库的连接字符串,而不是 NServiceBus 的 连接。
-
你仔细检查了什么? MSMQ、SQL Server 和 Oracle 都可以加入同一个分布式事务,但没有必须。您可以使用
TransactionScope创建一个新的环境事务,而不是让它登记。但这取决于你在做什么,在最后一条评论之后,我不能 100% 理解你想要达到的目标。 -
@DennisvanderStelt 我们根本没有尝试使用分布式事务。我们的服务从 NServiceBus 接收消息,处理它们,并将结果存储在数据库中。但是当它试图连接到数据库时,它一直被 NSB 的 分布式事务所吸引。我们希望避免加入 NSB 的分布式事务,而不会弄乱 NSB 正在做的任何事情,这就是下面的答案。
-
NServiceBus 默认不创建分布式事务,它们被创建是因为使用了多个资源管理器。所以 msmq 和 sql-server,或者 sql-server 和 oracle,或者 msmq 和 oracle。从 msmq 读取然后打开数据库连接时,两个事务都被“吸入”到分布式事务中。只使用一个资源管理器(例如,只使用 Oracle)来确保它不会。 DTC 以一定成本提供高可靠性。在放弃可靠性之前可能会三思而后行?
标签: c# oracle transactions nservicebus