【问题标题】:Default Transaction Timeout默认事务超时
【发布时间】:2010-11-23 19:23:02
【问题描述】:

我曾经使用 TransactionOptions.Timeout 设置事务超时,但为了便于维护,我决定使用配置方法:

 <system.transactions>
    <defaultSettings timeout="00:01:00" />
  </system.transactions>

当然,在放入之后,我想测试它是否正常工作,因此将超时时间减少到 5 秒,然后运行一个持续时间比这更长的测试 - 但事务似乎没有中止!如果我调整测试以将 TransactionOptions.Timeout 设置为 5 秒,则测试按预期工作

经过调查,我认为问题似乎与 TransactionOptions.Timeout 有关,即使我不再使用它。

我仍然需要使用TransactionOptions,所以我可以设置IsolationLevel,但是我不再设置Timeout值,如果我在创建它后查看这个对象,超时值是00:00:00,相当于无穷大。这是否意味着我在配置文件中设置的值被忽略了?

总结一下:

  • 是否无法混合配置 设置和使用 交易选项
  • 如果没有,是否有 任何方式来提取配置设置 在运行时,并使用它来设置 超时属性
  • [Edit] OR 设置默认隔离级别而不使用 TransactionOptions

【问题讨论】:

  • 你在哪个配置文件中设置了这个?在哪个配置部分?
  • 根目录下的 app.confing 中。也在 web.config 中,但上面的测试是针对 app.config 的。

标签: .net configuration transactions timeout


【解决方案1】:

您可以使用 TransactionManager.DefaultTimeout 从配置中获取(已验证的)默认超时。

TransactionOptions 是一个封装了超时和隔离级别的结构体。当使用默认构造函数初始化struct 时,它总是将结构成员初始化为其默认值:

TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.Timeout == default(TimeSpan); // TimeSpan.Zero
transactionOptions.IsolationLevel == default(IsolationLevel); // IsolationLevel.Serializable

如果要指定IsolationLevel 并使用默认超时:

new TransactionOptions()
{
    IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require
    Timeout = TransactionManager.DefaultTimeout
};

【讨论】:

  • 这是我一直希望的答案!不幸的是,我给你答案为时已晚,但 TransactionManager.DefaultTimeout 绝对是我想要的。感谢发帖!
  • 我还注意到微软也在他们的documentation on System.Transactions 中使用了这种技术。感谢您提供有用的信息!
  • ILSpy 中的 FWIW Groveling 在 .NET 4.0 中显示默认值为 1 分钟,请记住这是一个实现细节,因此可能会发生变化,请使用上述内容再次检查此值!:// System. Transactions.Configuration.DefaultSettingsSection [ConfigurationProperty("timeout", DefaultValue = "00:01:00"), TimeSpanValidator(MinValueString = "00:00:00", MaxValueString = "10675199.02:48:05.4775807")]
  • @aolszowka TransactionManager.DefaultTimeout的值配置文件中指定的值。默认值确实是1分钟,可以通过编辑DefaultSettingsSection.Timeout来修改,所以不需要复查!
  • machineSettings 或 TransactionManager.DefaultTimeout ?
【解决方案2】:

您可以混合使用 system.transaction 配置设置和 TransactionOption 类的使用,但您需要注意一些事项。

如果您使用 TransactionOption 和 指定一个Timeout 值,该值 将用于 system.transactions/defaultTimeout 价值。

以上是我认为您的问题的症结所在。您正在使用 TransactionOption 指定 isolation 级别,并且作为副作用,您将获得 infinite 超时值,因为无限是 TransactionOption 的默认超时值如果未指定。不过,我不太清楚为什么会这样……默认为默认事务超时是有意义的。

您可以实现自己的 TransactionOptions 助手类,其中包括从 app.config 读取的默认值(如果找到)或默认为可以使用的 TransactionOption 类的合理值。

无论如何,您仍然可以通过使用 system.transaction/machineSettings/maxTimeout 值来限制这一点。这是一个管理设置,只能通过 machine.config 进行配置。如果你从 app/web.config 尝试,你会得到一个 ConfigurationException。

<system.transactions>
    <machineSettings maxTimeout="00:00:30" />
</system.transactions>

ma​​xTimeout 设置后,无论您指定什么超时值,最大值都将限制为 maxTimeout 值。默认的 maxTimeout 是 00:10:00,即 10 分钟,因此您实际上不会在事务中遇到无限超时。

您还可以在事务中使用的数据库连接上显式设置事务 IsolationLevel。像这样?

   var connectionString = "Server=.;Database=master;Trusted_Connection=True;";

            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                using (var conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    var sqlTransaction = conn.BeginTransaction(System.Data.IsolationLevel.Serializable);

                    // do database work
                    //
                    sqlTransaction.Commit();


                }

                // do other work..
                //

                scope.Complete();

            }

在您的测试中,您可能需要确保重新生成 app.config 以便重新生成。在我的测试中,我似乎需要终止 *.vshost.exe 进程才能让它接受 system.transaction 配置设置更改——尽管我觉得这可能是侥幸。仅供参考..

【讨论】:

    【解决方案3】:

    对于Reflector来说,使用TransactionScope的构造函数设置事务超时的基本规则如下:

    DefaultTimeOut 由下面满足的第一条规则确定:

    • 如果构造函数有TimeSpan 参数,DefaultTimeout 就是那个参数
    • 如果构造函数有TransactionOption参数,则DefaultTimeout为transactionOption.TimeOut
    • 如果构造函数有TransactionScopeOption参数,则DefaultTimeout为scopeOption.TimeOut
    • 如果构造函数没有超时参数,则 DefaultTimeout 是在应用程序或 Web 配置文件中指定的值。
    • 否则,DefaultTimeOut 为 1 分钟。

    MaxTimeOut 为 10 分钟,除非在 machine.config 中指定了另一个值。

    事务的有效超时小于大于零的 MaxTimeOut 和 DefaultTimeOut。如果 MaxTimeOut 和 DefaultTimeOut 都为零,则有效超时是long.MaxValue 表示的滴答数(无穷大)。

    如果TransactionScope 实例没有创建新事务,要么是因为事务被传递到其构造函数中,要么是因为事务范围选项不需要它(例如,当存在环境事务并且需要 TransactionScopeOption 时) ,但是在构造函数中仍然传递了timeOut参数,启动了一个计时器。当超时时间过去时,底层事务的TimeOut() 方法被调用。在这种情况下不使用 DefaultTimeOut 和 MaxTimeOut 属性。

    如果是transactionScopeOption == TransactionScopeOption.Supress,超时被忽略,没有任何作用。

    如果 machine.config 中的相关部分被覆盖(注意 allowDefintion 和 allowExeDefinition 属性的值),也可以在 app/web 配置文件中定义 MaxTimeOut:

    <sectionGroup name="system.transactions" type="System.Transactions.Configuration.TransactionsSectionGroup, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null">
        <section name="defaultSettings" type="System.Transactions.Configuration.DefaultSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
        <section name="machineSettings" type="System.Transactions.Configuration.MachineSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" allowDefinition="MachineToApplication" allowExeDefinition="MachineToApplication"/>
    </sectionGroup>
    

    为了快速参考,这里是 TransactionScope 构造函数:

    public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption);
    public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption);
    public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions);
    public TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout);
    public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout);
    public TransactionScope(TransactionScopeOption scopeOption);
    

    【讨论】:

      【解决方案4】:

      使用 TransactionOptions 时忽略配置文件设置。在大多数情况下,创建 TransactionScope 将创建 CommittableTransaction 的实例。 CommittableTransaction 的无参数构造函数将使用配置文件设置作为其默认超时。采用 TransactionOptions 或 TimeSpan 的 TransactionScope 构造函数将调用 CommittableTransaction 类的重载之一,而不是无参数版本。因此,如果您想使用该值,您必须自己从配置文件中获取它。

      当我遇到这个问题时,我将以下代码放在一个小的 TransactionOptionsFactory 类中。

      
      Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
      ConfigurationSectionGroup sectionGroup = configuration.GetSectionGroup("system.transactions");
      DefaultSettingsSection defaultSettings = (DefaultSettingsSection) sectionGroup.Sections["defaultSettings"];
      TransactionOptions options = new TransactionOptions();
      options.Timeout = defaultSettings.Timeout;
      options.IsolationLevel = IsolationLevel.ReadCommitted;
      

      【讨论】:

      • 抱歉,迈克,我会奖励你赏金的,但我显然比赏金截止日期晚了一个小时。该解决方案将非常巧妙地解决我的问题。遗憾的是,API 对此并不清楚。
      • 不用担心,马特。我很高兴它有所帮助。
      【解决方案5】:
      void Main()
      {
          var maximumTimeout = TransactionManager.MaximumTimeout;//This step is necessary to init _maximumTimeout value, 
      
          FieldInfo fieldInfo = typeof(TransactionManager).GetFields(BindingFlags.NonPublic | BindingFlags.Static).Single(item => item.Name == "_maximumTimeout");
          var customMaximumTimeout = TimeSpan.FromHours(1);
          fieldInfo.SetValue(null, customMaximumTimeout);
          maximumTimeout = TransactionManager.MaximumTimeout;
      
          Console.WriteLine(maximumTimeout);//01:00:00
          // use TransactionScope
      }
      

      【讨论】:

      • 正如弗朗茨简明扼要地指出的那样——你可以通过反射来做到这一点。我在这篇 MSDN 文章的 cmets 中找到了另一种方法:blogs.msdn.com/b/ajit/archive/2008/06/18/… - 不幸的是,我公司的 DevOps 情况并不是我需要的,所以我没有简单的方法来更新 machine.config处理节点并将设置应用于未来的节点。使用反射对我来说是一个很好的解决方法。
      【解决方案6】:

      把我现在的想法记下来:

      • 无法混合配置设置和使用TransactionOptions
      • 在运行时提取配置设置的唯一方法是将 app.config 读取为 XML 文件
      • 默认隔离级别只能通过事务选项完成,或者在 WCF 中使用属性在服务级别完成

      【讨论】:

      • 至第二个要点:有一个用于访问配置文件的 api。请参阅我的答案中的代码以了解一种方法。您不必求助于将其作为 xml 文件读取。
      猜你喜欢
      • 2015-01-15
      • 2017-12-30
      • 2011-08-20
      • 2018-01-22
      • 2012-02-12
      • 1970-01-01
      • 2012-07-17
      • 2015-08-26
      • 2017-12-25
      相关资源
      最近更新 更多