好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C#中分布式事务的超时处理问题

C#中分布式事务的超时处理问题

事务是个很精妙的存在,我们在数据层、服务层、业务逻辑层等多处地方都会使用到。

       在这里我只说下 TransactionScope 这个微软推荐使用的隐式事务。它是从 Framework 2.0 开始引入的一个事务管理类,在使用隐式事务时,事务完成前   程序应调用 TransactionScope 的 Complete() 方法,将事务提交,然后利用 Dispose() 释放事务对象。若执行期间出现错误,事务将自动回滚。

    比如:
     using  ( ransactionScope  scope =  new   TransactionScope ())

     {

         //to do something

        scope.Complete();

     }

 在这里个人建议用 using 来创建 ,因为using实现了IDispose接口,它会隐式的调用 TransactionScope 对象的 Dispose 方法,即使发生异常时也是如此,能确保 在事务结束或者异常的时候也能正确的释放资源。其实我们反编译一下,它的内部实现就是一个 try...finally 代码块,这样也就不难理解 using 的作用了。

 说主题,在某地市的某库升级中,为避免程序运行中产生脏数据以及数据更新不一致导致的重复同步情况,在可能产生上述问题的考虑下,我用这个 TransactionScope 来对上述的操作进行事务处理。 在本机的测试环境中,运行结果是正常的,当然这个运行正常的前提是数据量较小的情况下,我每次只对一条或者十几条数据的不同表进行insert和update。然而部署到生产环境针对真实数据运行之后,发现这个事务总是回滚,一直无法正常提交。程序也就没法正常跑起来。因为生产环境中的数据有60W左右,insert一次、update一次,最后再insert一条同步语句,前2个操作都是比较耗时的。我切换回测试环境调试了一下,逐行运行,发现当执行完第一个insert之后,执行第二个update时发生异常了。这个异常由 TransactionScope 抛出,异常提示是:事务已中止。这个错误,在数据量小的情况下不会发生,数据量大一些就出现了,这个是不是和事务处理的时间长短有关呢?因为我明显感觉到在这次调试的时候,执行的时间比之前数据量只有一条的时候长了很多,至少花费 1 分钟以上。于是 google 一下,验证了我的想法。
       TransactionScope 有些重载函数是可以接受 TimeSpan 类型的值,这个就是事务的超时时间了。当事务实现隔离的时候,事务范围内的资源将会被锁定,如果一些事务长期占有资源,那将很容易造成死锁,为了避免这个问题, TransactionScope 事务会定义一个超时限制,这个超时默认值为 60 秒。如果事务超过此时间,即使没有发生异常,也会自动中止。上面问题的原因算是找到了,知道了原因,那么也就很好解决了。我们可以在 Web.Config  中配置 : 
< configuration >

 < system.transactions >

    < defaultSettings   timeout = " 00:05:00 "  />

 </ system.transactions >

</ configuration >

 

或者在 using 的时候就定义好超时时间:

 

using  ( TransactionScope  ts =  new   TransactionScope ( TransactionScopeOption .Required,
new   TimeSpan (0, 5, 0)))

或者先初始化事物行为的附加信息,然后定义超时时间:

TransactionOptions  tOpt =  new   TransactionOptions ();

tOpt.IsolationLevel =  IsolationLevel .ReadCommitted;  // 设置 TransactionOptions 模式

tOpt.Timeout =  new   TimeSpan (0, 5, 0);  //  设置超时时间为 5 分钟                         
using  ( TransactionScope  ts =  new   TransactionScope ( TransactionScopeOption .Required, tOpt))  

我这里定义的是 5 分钟,其实整个过程处理起来也就第一次处理历史数据需要 1 到 2 分钟时间,以后每天只需处理几十条数据,这个时间基本是秒级别的。
       这里说明下,   超时时间如果设置为 0 时表示超时无限长。无限长的设置主要对调试有用,调试过程中可能要逐步通过代码来隔离业务逻辑中的问题,并且在尝试确定问题期间不希望所调试的事务超时。在所有其他情况下使用无限长的超时时一定要格外小心,因为它会覆盖防止事务死锁的保护。 [ 这段说明摘抄至 MSDN]

作者: 牦牛
出处: http://maoniu602.cnblogs.com/
关于:我等因无形而恐惧,于是挥下刀刃,以假面之名...... 
说明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

标签:  C#

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于C#中分布式事务的超时处理问题的详细内容...

  阅读:48次