在我们的开发环境中,一切都很顺利,但是在我们的一个客户的UAT环境中(他们有大量数据),会出现两个交替的错误(有时是一个,有时是另一个...):
1. 无法加入分布式事务 2. 事务已终止。(内部异常:事务超时)
我们目前为事务使用了一天的超时时间(仅用于测试目的)。
在UAT环境上运行该进程后,大约10分钟后就会因为以上错误之一而停止,远远没有达到超时值。
以下是第二个错误的堆栈跟踪片段:
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还单独持久化了一些子项,如果有的话,整个项当然应该在持久化子项时出现任何问题时回滚)
希望通过这个补充,能更容易地解决这个问题!