理解Transactionscope超时

4

我目前对TransactionScope超时的理解如下:

如果事务运行时间超过设置的超时时间,当调用transaction.complete()方法时会抛出异常。因此,如果事务内的处理已经进行了X分钟,我们仍然需要等待X分钟后才能调用transaction.complete。

在我们的情况下,我们从webservice中使用TransactionScope - Web请求的最终用户将不得不等待X分钟,然后事务将被中止并返回异常。

但是,HttpWebRequest的默认超时时间为100秒(根据msdn)。由于客户端在100秒内超时,因此我们在TransactionScope中有1分钟的超时时间。这可以确保数据库一致性。

我的超时理解正确吗?

问题:我们希望尽量缩短最终用户知道事务结果的时间。为了最小化延迟,我们决定使用嵌套的TransactionScopes分割代码 - 每个事务的超时时间为15秒。如果子事务花费的时间超过15秒,我们将中止整个事务。

在这种情况下,子事务的超时似乎被忽略了。只有在父事务的超时被调用后,我才会收到异常。在下面的代码中,ChildTransaction()总是返回true。如何推荐最小化延迟?代码显示默认超时时间为1分钟,以使代码更简洁

    internal bool RootTransaction()
    {           
        using (TransactionScope transaction = new TransactionScope())
        {
            try
            {
                bool result = ChildTransaction();

                //The result is always true. 
                if (!result)
                    return result;                                     

                for (int counter = 0;counter <= 10;counter++)
                {                       
                    //Either sleep OR do some processing 
                    System.Threading.Thread.Sleep(5000);
                    //
                    //Dosomeprocess()
                }                    
                transaction.Complete();                    
                return true;
            }
            catch (Exception e)
            {                    
                return false;
            }
        }                           
    }

    internal bool ChildTransaction()
    {            
        using (TransactionScope transaction = new TransactionScope())
        {
            try
            {
    //Sleep for 70 seconds
                System.Threading.Thread.Sleep(70000);
                transaction.Complete();                    
            }                
            catch (Exception e)
            {
                return false;
            }                
        }
        return true;
    }

用真/假返回代码替换异常几乎从来不是一个好主意。我可以澄清一下:您是否将事务用作Web服务调用的一部分?这样的分布式事务可能会真正致命。还是事务局部于Web服务实现? - Marc Gravell
不,交易并不是 Web 服务调用的一部分。提到 Web 服务只是为了设置上下文。这些服务是原子性的,其中一些涉及需要事务的数据插入。此外,true false 只是用于测试目的。我们有单独的日志框架等来处理异常。 - user529265
K. 就记录而言,我不确定是否应该期望子事务得到尊重。最外层的事务规则使用 TS。超时时间不应该加倍;如果超时时间为 X 秒,则从它第一次执行任何操作开始计算 X 秒 - 而不是在调用时计算 X 秒再计算 X 秒。但这有点棘手,因为在您的示例中,您似乎没有涉及任何事务资源 - 这使得谈论特定行为变得困难。但超时时间是针对事务本身而不是操作的。 - Marc Gravell
超时时间没问题。默认情况下,如果总交易时间超过一分钟,它将被中止。我的问题是:1)如果子事务本身需要超过一分钟的时间,它不会抛出异常;2)事务超时总是在提交事务时检查(这可能需要超过一分钟,具体取决于其处理)。有什么推荐的方法可以最小化终端用户的等待时间?我需要我的终端用户在15秒内得到结果。因此,我将事务拆分为嵌套事务,并设置了15秒的超时时间。看起来子事务的超时时间没有被尊重。 - user529265
1个回答

2

试着这样看待:

在调用 trans.Complete() 或退出事务作用域时才会确定事务的长度。请看下面的代码:

using (var trans= new TransactionScope())
{
Threading.Sleep(99999);
trans.Complete()
}

在sleep例程内部无法抛出超时异常,如果可以抛出也没有意义。因此,使用事务超时(至少这样)只能保证如果事务花费的时间超过了您设置的超时时间,它将不会被提交。
如果您只是执行一个查询(我不知道您用事务做什么),那么您可以设置查询/命令超时时间(或者您称之为其他名称)。如果我没记错的话,在超时时间到期后,您的查询将立即返回。
另一种方法是设置您的Web服务请求超时时间,并假设由于事务中的某些原因,该Web服务需要太长时间才能响应。
编辑: 您可以尝试:
- 在不同的线程上启动事务,然后在主线程(Web服务调用使用的线程)上等待其完成(使用Thread.Join(timeout))。因此,如果它在您指定的超时时间之前没有终止,则您可以停止等待并返回超时错误(不要忘记信号其他线程以中止事务)。 - 假设您只在这些事务中执行SQL查询,则可以使用“BEGIN TRANSACTION”关键字在SQL脚本中指定事务(确实有点hacky)。然后,您只需指定命令超时并在单行代码中执行所有操作。但是,这要求您将所有事务中的操作移动到SQL脚本中,这可能或可能不可能...而且它并不简洁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接