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时表示超时无限长。无限长的设置主要对调试有用,调试过程中可能要逐步通过代码来隔离业务逻辑中的问题,并且在尝试确定问题期间不希望所调试的事务超时。在所有其他情况下使用无限长的超时时一定要格外小心,因为它会覆盖防止事务死锁的保护。

希望本文所述对大家的C#程序设计有所帮助。

(0)

相关推荐

  • C#事务处理(Execute Transaction)实例解析

    本文所述为C#事务处理(Execute Transaction)的一个实例,包含了创建SqlTransaction 对象并用SqlConnection对象的BeginTransaction()方法开始事务,创建保存SQL语句,将SqlCommand对象的CommandText属性设置为第一个INSERT语句,第一个INSERT语句在Customers表中增加一行,提交事务,使INSERT语句增加的两行在数据库中保存起来. 具体的实例代码如下: using System; using System

  • C#编程之事务用法

    本文实例讲述了C#编程之事务用法.分享给大家供大家参考,具体如下: ado.net2.0的SqlTransaction使用方法 /////ado.net1.0中使用Transacation(事务) string connectionString = "database=Northwind;pwd=admin;uid=sa;server=DATABASE-VPC\\SQL2005"; using (SqlConnection conn = new SqlConnection(connec

  • c# 应用事务的简单实例

    复制代码 代码如下: using (TransactionScope tr = new TransactionScope()) {     int i = this.deskmanager.addOpenDesk(account_c);     int j = this.deskmanager.updateDeskStatus(account_c.AccountC_desk, "有客");     if (i > 0 && j > 0)     {     

  • c#实现sqlserver事务处理示例

    复制代码 代码如下: private static void ExecuteSqlTransaction(string connectionString)    {        using (SqlConnection connection = new SqlConnection(connectionString))        {            connection.Open();            SqlCommand command = connection.CreateC

  • c#实现数据库事务示例分享

    复制代码 代码如下: using System;using System.Data.SqlClient; namespace ExecuteSqlTran{    class Program    {        class Result<T>        {            public T data;            public string Message;            public bool Success;            public string

  • C#执行SQL事务用法实例

    本文实例讲述了C#执行SQL事务用法.分享给大家供大家参考.具体分析如下: 1.通过存储过程. 2.通过C#中提供的Transaction.这里就来演示一下通过C#中提供的Transaction 执行SQL事务. WebForm3.aspx.cs页面 复制代码 代码如下: using System;  using System.Collections.Generic;  using System.Linq;  using System.Web;  using System.Web.UI;  us

  • C#处理Access中事务的方法

    本文实例讲述了C#处理Access中事务的方法.分享给大家供大家参考.具体如下: Access不能像SQL server一样直接执行多条语句,但是把多条语句绑成事务还是可以一起执行的. 所谓事务,就是把多件事情当做一件事情来处理.也就是大家同在一条船上! 由一个事务来完成多个表的同步操作,要么都执行成功,要么都不成功.下面举个例子,用C#实现Access数据库事务的处理方法: 向一个表提交数据,同时更新另一个表中的数据 using System; using System.Data; using

  • c# 执行事务函数代码

    复制代码 代码如下: /// <summary> /// 执行多条sql语句,实现事务 /// </summary> /// <param name="arraySql">多条sql语句</param> public int ExecutrSqlTran(System.Collections.ArrayList arraySql) { int itemnum; DbOpen(); SqlCommand cm = new SqlComman

  • C#中事务处理和非事务处理方法实例分析

    本文实例讲述了C#中事务处理和非事务处理方法.分享给大家供大家参考.具体如下: C#代码如下: String connectionString = ConfigurationManager.ConnectionStrings["DB_Constr"].ToString(); SqlConnection conn = null; SqlTransaction trans = null; try { conn = new SqlConnection(connectionString); i

  • C#中的事务用法实例分析

    本文实例讲述了C#中的事务用法.分享给大家供大家参考.具体如下: 直接用SQL语句创建事务, 当然不是什么稀奇事了, 好是好, 只是麻烦. 看看C#中怎么做吧: SqlTransaction Tran = DBConn.BeginTransaction(); cmdTmp.Transaction = Tran; try { cmdTmp.CommandText = "DELETE FROM xxx"; cmdTmp.ExecuteNonQuery(); cmdTmp.CommandTe

随机推荐