scope oracle,关于c#:TransactionScope和Oracle的问题

我们已经编写了一个使用ODP.NET与Oracle数据库(11g)通讯的C#3.5客户端。

此应用程序具有批处理过程,在该过程中,将执行长时间运行的任务,以对TransactionScope中的数据库进行各种调用。

在我们的开发环境中,一切都进行得很好,但是在我们的一个客户(拥有大量数据)的UAT环境中,会发生两个交替的错误(有时一个,有时另一个...)错误:

无法加入分布式交易

交易已中止。 (内部例外:事务超时)

我们目前为交易使用一天的超时(出于测试目的)。

在UAT环境上运行上述过程会导致在大约30分钟后停止运行。 10分钟以上情况之一,因此无法接近超时值。

这是第二个错误的stacktrace的片段:

at System.Transactions.TransactionStatePromotedAborted.CreateAbortingClone(InternalTransaction tx)

at System.Transactions.DependentTransaction..ctor(IsolationLevel isoLevel, InternalTransaction internalTransaction, Boolean blocking)

at System.Transactions.Transaction.DependentClone(DependentCloneOption cloneOption)

at System.Transactions.TransactionScope.SetCurrent(Transaction newCurrent)

at System.Transactions.TransactionScope.PushScope()

at System.Transactions.TransactionScope..ctor(TransactionScopeOption scopeOption)

at System.Transactions.TransactionScope..ctor()

at Application.Domain.DataAccess.Oracle.EntityDaoBase`2.SaveItem(TEntity item, EntityReference`1 user)

该过程尝试将一个项目保存到事务范围内的数据库中,但是堆栈跟踪显示该构造函数已被TransactionScope类选中,这意味着它将创建一个新的TransactionScope。

我到目前为止正确吗?

因为我不太了解TransactionScope的内部工作原理,但是似乎当您在范围内调用方法时,它将创建一个新的事务(假定继承自环境事务)。

如果我是对的,可能是这个新事务没有继承正确的超时(而是默认的),所以嵌套事务会导致此超时异常吗?

如果没有,对它可能有什么想法?另外,在环境事务中调用的方法中没有定义嵌套的事务。

任何帮助将不胜感激!

编辑1:

该函数的简化代码段:

public void SomeLengthyBatchProcess()

{

using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))

{

foreach (var item in Items)

{

SaveItemToDB(item);

}

transaction.Complete();

}

}

public void SaveItemToDB(object item)

{

using (var transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(1, 0, 0, 0)))

{

// Performing data persistency here

transaction.Complete();

}

}

编辑2:

好的,事实证明,'SaveItemToDB'方法中存在一个嵌套事务。在仔细研究了一位同事编写的代码之后,我看到它定义了自己的TransactionScope,但是没有选项和超时。

修改此方法以使其具有与超时相同的参数后,我再次在客户的服务器上运行了该代码,但仍然没有运气(再次,由于超时,事务中止了错误)。

所以我的问题现在如下:

是否有必要为嵌套事务定义超时值,或者它们是否从环境事务中继承超时值?

当所有事务作用域的超时设置都相同(大概是我不知道的内部工作方式除外)并且超时值定义为1天时(在该异常发生之后),可能发生超时异常约。 10分钟?

是否可以防止Oracle为连接字符串相同的事务创建分布式事务?

可能是分布式事务的额外开销导致异常,例如事务中止了吗?

我更新了代码段,以便更好地反映情况。

(顺便说一句,第二个嵌套事务是必需的,因为DAL还单独保留一些子项(如果存在),并且如果在保留子项时出现任何错误,则整个项目当然应该回滚)

希望通过添加此内容,可以更轻松地阐明此问题!

因为找不到解决方案,所以我们决定停止使用TransactionScope来实现我们的目的,并自行安排回滚。

我发现TransactionScope和Oracle不能很好地融合在一起,也许SQL Server可以更好地处理它,但这不是我们的选择。

谢谢阅读。

machine.config中的默认事务超时为10分钟...这可能就是您超时的原因。

首先解决主要问题:

How is it possible that a timeout exception can occur when the timeout setting is (presumably, aside from inner workings that I do

not know about) the same for all transaction scopes and has a timeout

value defined of 1 day, where the exception occurs after approx. 10

minutes?

TransactionManager.MaximumTimeout属性是您尝试通过作用域设置的任何内容的上限。在您的系统上,它设置为10 minutes,但是根据文档

This value can be set in the MachineSettingsSection of the config file.

至于其他问题:

Is it necessary to define timeout values for nested transactions or do they inherit this from the ambient transaction?

启动事务的范围(即,任何RequiresNew范围,任何最外部的Required范围以及在嵌套堆栈上一级具有Suppress范围的任何Required范围)都将建立transaction timeout,并且在我阅读源代码时,此超时不受嵌套作用域的影响。

但是,参与现有事务的每个嵌套范围(即,在堆栈上一级具有Required或RequiresNew范围的任何Required范围)都将建立自己的范围超时,该超时将在上述事务超时之外运行。

事务超时和作用域超时在内部的实现方式有所不同,但是,如果这些超时中的任何一个命中,则将回滚尚未进行Complete() d的事务。

顺便说一句,前面提到的TransactionManager.MaximumTimeout仅适用于事务超时。范围超时没有上限。并不是真的很重要,因为最短的超时仍然很重要。

Is it possible to prevent Oracle from creating a distributed transaction for transactions where the connectionstring is the same?

只要在任何时间点只有一个"物理"数据库连接打开,作用域就不会升级为DTC。如果我没记错的话,尽管看起来似乎与此相反(尽管当时它不适用于该版本?),但它适用于Oracle ODP.Net。

即使对于嵌套作用域,对于不同的数据库(只要它们位于同一服务器上),您可能也可能无法阻止并发连接。

虽然是个老问题,但希望这个答案能对您有所帮助...

对于长时间运行的事务,尤其会发生这种情况,因为基础IDbConnection不会长时间保持打开状态,并且会为transactionscope的各个部分(连接池)创建新的连接。出于同样的原因,如果返回并使用了相同的打开连接,则长事务可能会成功,否则它将失败。对此的唯一解决方案是控制连接的创建并确保整个过程中仅使用一个连接。

我知道这是一个古老的问题,但由于我已经看过很多了,因此我将对其进行补充。

您正在使用RAC吗?您是否曾与DBA一起查看过是否正在锁定/阻塞。我已经将System.Transactions与Oracle一起使用了多年,而我遇到类似问题的唯一一次是当我们使用RAC时,还需要进行其他配置。

发生的事情是这样的:您开始事务并在事务期间打开连接(很好)。但是,没有为分布式事务处理配置oracle服务(这是该服务上的一个简单复选框选项)。因此,额外的连接开始跨越RAC群集中的多个实例,并且相关事务之间互不了解,从而导致.net进程自行阻塞。

这是一个简单的修复。您正在使用的oracle服务仅需要启用DTP。

您可以显示一段代码吗?从您提到的内容中,我唯一能找到的就是与System.Transactions有关。讨论在这里。当然,他们的"解决方案"是确保您至少使用ODP.NET 11.1.0.6.20或更高版本。

感谢您的回复。 香港专业教育学院已经看过那篇文章,它没有帮助。 我将用代码片段更新原始问题。

我更新了这篇文章,似乎这里还有其他事情……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值