Condividi tramite


Override the System.Transactions default timeout of 10 minutes in the code

Problem :

We were using System.Transactions to initiate distributed transactions against SQL Server. The transaction were getting aborted after about 10 minutes even though the System.Transactions has a timeout set to 200 minutes.

DTC timeout (in the Component Services) is set to 0 (infinite) on both app server and sql server.

DTCTrace.log from app server :
===============================
pid=3680 ;tid=5376 ;time=03/07/2008-08:20:22.717 ;seq=6 ;eventid=TRANSACTION_BEGUN ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"transaction got begun description : '<NULL>'"
pid=3680 ;tid=4404 ;time=03/07/2008-08:20:24.389 ; seq=7 ;eventid=TRANSACTION_PROPOGATED_TO_CHILD_NODE ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"transaction propagated to '<SQL Server machine name>' as transaction child node #1"
pid=3680 ;tid=1596 ;time=03/07/2008-08:30:24.217 ;seq=8 ;eventid=RECEIVED_ABORT_REQUEST_FROM_BEGINNER ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"received request to abort the transaction from beginner"

pid=3680 ;tid=1596 ;time=03/07/2008-08:30:24.217 ;seq=9 ;eventid=TRANSACTION_ABORTING ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a;"transaction is aborting"
pid=3680 ;tid=1596 ;time=03/07/2008-08:30:24.217 ;seq=10;eventid=CHILD_NODE_ISSUED_ABORT ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"abort request issued to transaction child node #1 'ASSURITYFS001'"
pid=3680 ;tid=4404 ;time=03/07/2008-08:30:24.217 ;seq=11;eventid=CHILD_NODE_ACKNOWLEDGED_ABORT ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"received acknowledgement of abort request from transaction child node #1 'ASSURITYFS001'"

pid=3680 ;tid=4404 ;time=03/07/2008-08:30:24.217 ;seq=12;eventid=TRANSACTION_ABORTED ;tx_guid=a49298cd-709a-4fbe-a637-2fc6c4ab029a ;"transaction has been aborted"

Resolution :

By default all the distributed transactions initiated using System.Transactions have the default timeout of 10 minutes. If we try to override this timeout in the code or in the app.config file it will be adjusted down to 10 minutes. To get around the problem :

1. Added the following section in the machine.config file to set the maxTimeout to 1 hour :

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

2. We modified the System.Transactions section in machine.config by setting the allowExeDefinition attribute to “MachineToApplication” (from MachineOnly). After this, we were able to override the machine.config timeout of 10 minutes in the code and that allowed the transaction to complete successfully.

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

Comments

  • Anonymous
    April 19, 2010
    I have the exact same problem with a WCF service deployed on windows 2008 server. The transactions times out after ten minutes although the service is not done with the operation.I've added both:<configuration><system.transactions>  <machineSettings maxTimeout="01:00:00" /></system.transactions></configuration>and:<sectionGroup name="system.transactions" type="System.Transactions.Configuration.TransactionsSectionGroup, System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null">     <section name="defaultSettings" type="System.Transactions.Configuration.DefaultSettingsSection, System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" />     <section name="machineSettings" type="System.Transactions.Configuration.MachineSettingsSection, System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" allowDefinition="MachineOnly" allowExeDefinition="MachineToApplication" />   </sectionGroup>to my machine.config file, because thats how I understood your solution. Unfortunately, the transactions still times out after 10 minutes.Do you have any idea what Im might be missing?Best regards /Cobi
  • Anonymous
    June 25, 2010
    The way I interpret the Ajit's statements is that you do either 1. (which affects the whole machine), or you implement 2. and override the transaction timeout within the code.I'm hoping this is going to work, I've got the same problem!
  • Anonymous
    June 25, 2010
    The way I interpret Ajit's statements is that you do either 1. (which affects the whole machine), or you implement 2. and override the transaction timeout within the code.I'm hoping this is going to work, I've got the same problem!
  • Anonymous
    October 06, 2010
    Apologize for the delay in replying. For some reason, I did not receive the notfications about the comments above.We need to follow both the steps.Make sure you are not setting a lower timeout value in app/web.config of the WCF service.Reference :blogs.msdn.com/.../how-to-change-system-transactions-timeout.aspx
  • Anonymous
    January 19, 2013
    Or you can do it with Reflection and change the value at runtime after it has been loaded from the config file.  This would only be good for this session of this app, but it is often all you need.  Here's a subroutine in vb syntax Public Shared Sub OverrideTransactionScopeMaximumTimeout(ByVal timeOut As TimeSpan)     Dim oSystemType As System.Type = GetType(Transactions.TransactionManager)     Dim oCachedMaxTimeout As System.Reflection.FieldInfo = oSystemType.GetField("_cachedMaxTimeout",                                                                                 Reflection.BindingFlags.NonPublic Or                                                                                 Reflection.BindingFlags.[Static])     Dim oMaximumTimeout As System.Reflection.FieldInfo = oSystemType.GetField("_maximumTimeout",                                                                               Reflection.BindingFlags.NonPublic Or                                                                               Reflection.BindingFlags.[Static])     oCachedMaxTimeout.SetValue(Nothing, True)     oMaximumTimeout.SetValue(Nothing, timeOut)     'For testing to confirm value was changed     'Dim oValue As TimeSpan = CType(oMaximumTimeout.GetValue(Transactions.TransactionManager.MaximumTimeout), TimeSpan) End Sub
  • Anonymous
    May 12, 2013
    SpicyMikey - just Awesome!  Still in process of testing but I'd much rather to change the MaxTimeout in code.  For C# programs, imaging trying to distribute changes to client PCs by editing "machine.config".  Horrible!!Here is the C# version of your code for those doing C#.  I hope it is right.  Still testing but look OK.
        private void OverrideTransactionScopeMaximumTimeout(TimeSpan timeOut)    {        // 1. create a object of the type specified by the fully qualified name        Type oSystemType = typeof(global::System.Transactions.TransactionManager);        System.Reflection.FieldInfo oCachedMaxTimeout = oSystemType.GetField(&quot;_cachedMaxTimeout&quot;, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);        System.Reflection.FieldInfo oMaximumTimeout = oSystemType.GetField(&quot;_maximumTimeout&quot;, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);        oCachedMaxTimeout.SetValue(null, true);        oMaximumTimeout.SetValue(null, timeOut);        // For testing to confirm value was changed        // MessageBox.Show(string.Format(&quot;DEBUG SUCCESS!! &nbsp;Maximum Timeout for transactions is &#39;{0}&#39;&quot;, TransactionManager.MaximumTimeout.ToString()));    }
  • Anonymous
    October 22, 2013
    thanks Buzzwah