您的位置:68399皇家赌场 > 集群主机 > C#中跨库事务处驾驭决方案,

C#中跨库事务处驾驭决方案,

发布时间:2019-05-05 07:46编辑:集群主机浏览(192)

    现实代码如下:

    C#中跨库事务管理消除方案,

      近来新接手了1项业务,在那之中有3个主意,供给对专门的职业表进行写入数据,之后记录到日志表中。那有个别代码原先是先行者写的,他从不动用此外方案,只是简短的调用Ado.net推行了三次写库操作。由此常常现身系统使用者不断发邮件说多少不正常,经过查看原因尽管在于写库操作中,有有个别表写入退步,然而任何表写入成功,导致出现了数据不等同的标题。后来本想改用事务,但意识日志表和作业表不在同四个数据库下,乃至不在同贰个IP下,对于这些主题素材,我想开了有以下消除方案。

    由ado.net管理的业务改为自身手动提交业务和Commit或许RollBack操作:

    step一:遵照连接字符串和sql分类,存入Dictionary<string,string>中,Key为一而再字符串,Value为针对此数据库的Sql语句,多条用分号隔断;

    step二:遍历此Dictionary,张开这一个连接;

    step3:对于各个连接,张开专门的职业;

    step肆:实行针对种种连接的sql,出现错误则整个rollback,不然全部commit;

    step伍:关闭连接,记录运转状态,记录日志。

    实际代码如下:

      1         //提交事务用的sql
      2         public const string MultiTran = @"BEGIN TRAN
      3                                             {0}";
      4 
      5         /// <summary>
      6         /// 事务返回的信息
      7         /// </summary>
      8         public struct TransInfo
      9         {
     10             /// <summary>
     11             /// sql总条数
     12             /// </summary>
     13             public int Total;
     14             /// <summary>
     15             /// 事务执行是否成功
     16             /// </summary>
     17             public bool IsSuccess;
     18             /// <summary>
     19             /// 失败时的sql
     20             /// </summary>
     21             public string WrongMessage;
     22         }        
     23 
     24         /// <summary>
     25         /// 跨库事务异常对象
     26         /// </summary>
     27         public class TransException : Exception
     28         {
     29             public TransException(string message) : base(message)
     30             {
     31             }
     32 
     33             public string wrongSQL { get; set; }
     34             public string wrongAt { get; set; }
     35             /// <summary>
     36             /// 已经打开的连接
     37             /// </summary>
     38             public List<SqlConnection> DoneConnection = new List<SqlConnection>();
     39             /// <summary>
     40             /// 出现错误的连接
     41             /// </summary>
     42             public SqlConnection CurrentConnection;
     43             /// <summary>
     44             /// 覆盖Exception中的Message字段,使其可写
     45             /// </summary>
     46             public new string Message { get; set; }
     47         }
     48 
     49         /// <summary>
     50         /// 多操作sql,使用事务,用于多库事务
     51         /// <para>
     52         /// 返回值TransInfo字段:IsSuccess 是否成功,
     53         /// Total sql总条数,
     54         /// WrongAt 失败的sql语句
     55         /// </para>
     56         /// </summary>
     57         /// <param name="sqlwithconn">执行的sql和连接字符串列表key:sql,value:连接字符串</param>
     58         /// <param name="connectionString">连接字符串</param>
     59         /// <returns>sadf</returns>
     60         public static TransInfo RunSqlInTrans(Dictionary<string, string> sqlwithconn)
     61         {
     62             var sqltable = new Dictionary<string, string>();
     63             var conntable = new Dictionary<string, SqlConnection>();
     64 
     65             foreach (var i in sqlwithconn)
     66             {
     67                 if (!sqltable.Keys.Contains(i.Value))
     68                 {
     69                     sqltable.Add(i.Value, i.Key); //sqltable的key是连接字符串,value是sql语句
     70                     conntable.Add(i.Value, new SqlConnection(i.Value));    //key是连接字符串,value是连接对象
     71                 }
     72                 else
     73                 {
     74                     sqltable[i.Value]  = ";"   i.Key;
     75                 }
     76             }
     77 
     78             try
     79             {
     80                 var wrongEx = new TransException("");
     81                 foreach (var i in sqltable)
     82                 {
     83                     //遵照晚开早关原则,在此处打开数据库连接
     84                     conntable[i.Key].Open();
     85                     //连接打开后,将连接对象放入异常处理对象中做记录
     86                     wrongEx.DoneConnection.Add(conntable[i.Key]);
     87                     var dc = new SqlCommand(string.Format(MultiTran, i.Value), conntable[i.Key]);
     88                     try
     89                     {
     90                         dc.ExecuteNonQuery();
     91                     }
     92                     catch (Exception ex)
     93                     {
     94                         //出现异常,抛出异常处理对象
     95                         wrongEx.CurrentConnection = conntable[i.Key];
     96                         wrongEx.wrongAt = i.Key;
     97                         wrongEx.wrongSQL = sqltable[i.Key];
     98                         wrongEx.Message = ex.Message;
     99                         throw wrongEx;
    100                     }
    101                 }
    102                 //全部执行完毕没有发现错误,提交事务
    103                 foreach (var i in conntable)
    104                 {
    105                     var dc = new SqlCommand("COMMIT TRAN", i.Value);
    106                     dc.ExecuteNonQuery();
    107                     i.Value.Close();
    108                 }
    109                 return new TransInfo()
    110                 {
    111                     IsSuccess = true,
    112                     Total = sqlwithconn.Count,
    113                     WrongMessage = ""
    114                 };
    115 
    116             }
    117             catch (TransException e)   //1.回滚所有操作2.关闭所有已经打开的数据库连接4.生成错误对象
    118             {
    119                 foreach (var i in e.DoneConnection)
    120                 {
    121                     if (!i.Equals(e.CurrentConnection))
    122                     {
    123                         var dc = new SqlCommand("ROLLBACK TRAN", i);
    124                         dc.ExecuteNonQuery();
    125                     }
    126                     i.Close();
    127                 }
    128                 return new TransInfo()
    129                 {
    130                     IsSuccess = false,
    131                     Total = sqlwithconn.Count,
    132                     WrongMessage = string.Format("在连接{0}中,操作{1}出现错误,错误信息:{2}", e.wrongAt, e.wrongSQL, e.Message)
    133                 };
    134             }
    135         }
    

     那样消除了跨库数据表管理有时因为互连网难题或任何偶然性问题变成的数量差异等的主题素材。可是这一个化解方案最大的标题不怕在乎质量问题上,比方倘诺有多少个库假如为A,B,C,D,在这之中C库的数额修改写入相比较复杂,那么在A,B库开启事务后,必须等待C和D库达成或失利后,事务才方可停止,连接本领放出,那一年,A库和B库就是地处挂起状态,借使处在高IO的生产条件中的话,这几个天性的损失只怕是致命的,所以那些方案不得不用来轻易的sql管理,而且管理sql不能太多大概太复杂。而且出现互联网波动的话,损失会更加大。幸运的是自己所接手的那几个业务,是在内网蒙受中,同时只用两句sql在四个库中,所以用那些方案难题比很小。

    计算:针对那一个主题素材,我觉着当下设计数据库时,能防止跨库就必将在防止。

    假使大家有何越来越好的缓和方案以来,希望和大家多多交流和指教。

     

    近来新接手了一项工作,个中有二个格局,需求对作业表张开写入数据,之后记录到日志表中。那有的代码原...

    其它,多数事务特点使得该服务不可能提供二个安然无恙的回滚操作。

    step伍:关闭连接,记录运转景况,记录日志。

    可用性:布满式服务能一贯保证可用状态。当用户产生八个请求后,服务能在个别时间内再次来到结果。

    小结:针对那些题目,笔者以为当初设计数据库时,能防止跨库就一定要幸免。

    ▌达成珍视因素:

      近日新接手了壹项业务,在那之中有3个艺术,须要对业务表进行写入数据,之后记录到日志表中。那1部分代码原先是前人写的,他未有行使别的方案,只是简短的调用Ado.net施行了一回写库操作。由此平常出现系统使用者不断发邮件说多少不正常,经过查看原因尽管在于写库操作中,有某些表写入失败,可是任何表写入成功,导致出现了数据不一致样的主题素材。后来本想改用事务,但意识日志表和作业表不在同叁个数据库下,以致不在同一个IP下,对于这几个难点,笔者想开了有以下化解方案。

    一.两阶段提交(二PC, Two-phase Commit)方案;

     那样化解了跨库数据表管理有时因为互联网难点或其余偶然性难点形成的多少不平等的问题。但是这些化解方案最大的主题素材即便在乎质量难点上,举个例子假使有多少个库即使为A,B,C,D,在那之中C库的数目修改写入比较复杂,那么在A,B库开启事务后,必须等待C和D库达成或停业后,事务才方可了结,连接技艺放出,那个时候,A库和B库正是居于挂起状态,若是处在高IO的生产条件中的话,这么些特性的损失也许是致命的,所以这些方案不得不用来轻便的sql管理,而且管理sql不能够太多或许太复杂。而且出现网络波动的话,损失会越来越大。幸运的是本身所接手的这些专业,是在内网情状中,同时只用两句sql在五个库中,所以用那几个方案问题比非常的小。

    履新数据库数据后同时排除缓存数据。数据库数据更新后,同步删除缓存中多少,使得下次对物品详细情况的得到第2手从数据库中获得,并联合签名到缓存。

    step二:遍历此Dictionary,展开那几个连接;

    二.eBay 事件队列方案;

    皇家赌场,step叁:对于每种连接,打开工作;

    壹致性理论

     

    ▌最后1致性:弱1致性的一种样式,数据更新成功后,系统不应允当即能够回去最新写入的值,不过保证最终会重返上1次革新操作的值。

    step一:根据连接字符串和sql分类,存入Dictionary<string,string>中,Key为一连字符串,Value为针对此数据库的Sql语句,多条用分号隔离;

    ■ 扩大超时机制。

    step4:实践针对各类连接的sql,出现谬误则整个rollback,不然一切commit;

    ▌要消除本场景下缓存和数据库数据分裂等的主题素材大家有以下三种缓和方案:

      1         //提交事务用的sql
      2         public const string MultiTran = @"BEGIN TRAN
      3                                             {0}";
      4 
      5         /// <summary>
      6         /// 事务返回的信息
      7         /// </summary>
      8         public struct TransInfo
      9         {
     10             /// <summary>
     11             /// sql总条数
     12             /// </summary>
     13             public int Total;
     14             /// <summary>
     15             /// 事务执行是否成功
     16             /// </summary>
     17             public bool IsSuccess;
     18             /// <summary>
     19             /// 失败时的sql
     20             /// </summary>
     21             public string WrongMessage;
     22         }        
     23 
     24         /// <summary>
     25         /// 跨库事务异常对象
     26         /// </summary>
     27         public class TransException : Exception
     28         {
     29             public TransException(string message) : base(message)
     30             {
     31             }
     32 
     33             public string wrongSQL { get; set; }
     34             public string wrongAt { get; set; }
     35             /// <summary>
     36             /// 已经打开的连接
     37             /// </summary>
     38             public List<SqlConnection> DoneConnection = new List<SqlConnection>();
     39             /// <summary>
     40             /// 出现错误的连接
     41             /// </summary>
     42             public SqlConnection CurrentConnection;
     43             /// <summary>
     44             /// 覆盖Exception中的Message字段,使其可写
     45             /// </summary>
     46             public new string Message { get; set; }
     47         }
     48 
     49         /// <summary>
     50         /// 多操作sql,使用事务,用于多库事务
     51         /// <para>
     52         /// 返回值TransInfo字段:IsSuccess 是否成功,
     53         /// Total sql总条数,
     54         /// WrongAt 失败的sql语句
     55         /// </para>
     56         /// </summary>
     57         /// <param name="sqlwithconn">执行的sql和连接字符串列表key:sql,value:连接字符串</param>
     58         /// <param name="connectionString">连接字符串</param>
     59         /// <returns>sadf</returns>
     60         public static TransInfo RunSqlInTrans(Dictionary<string, string> sqlwithconn)
     61         {
     62             var sqltable = new Dictionary<string, string>();
     63             var conntable = new Dictionary<string, SqlConnection>();
     64 
     65             foreach (var i in sqlwithconn)
     66             {
     67                 if (!sqltable.Keys.Contains(i.Value))
     68                 {
     69                     sqltable.Add(i.Value, i.Key); //sqltable的key是连接字符串,value是sql语句
     70                     conntable.Add(i.Value, new SqlConnection(i.Value));    //key是连接字符串,value是连接对象
     71                 }
     72                 else
     73                 {
     74                     sqltable[i.Value]  = ";"   i.Key;
     75                 }
     76             }
     77 
     78             try
     79             {
     80                 var wrongEx = new TransException("");
     81                 foreach (var i in sqltable)
     82                 {
     83                     //遵照晚开早关原则,在此处打开数据库连接
     84                     conntable[i.Key].Open();
     85                     //连接打开后,将连接对象放入异常处理对象中做记录
     86                     wrongEx.DoneConnection.Add(conntable[i.Key]);
     87                     var dc = new SqlCommand(string.Format(MultiTran, i.Value), conntable[i.Key]);
     88                     try
     89                     {
     90                         dc.ExecuteNonQuery();
     91                     }
     92                     catch (Exception ex)
     93                     {
     94                         //出现异常,抛出异常处理对象
     95                         wrongEx.CurrentConnection = conntable[i.Key];
     96                         wrongEx.wrongAt = i.Key;
     97                         wrongEx.wrongSQL = sqltable[i.Key];
     98                         wrongEx.Message = ex.Message;
     99                         throw wrongEx;
    100                     }
    101                 }
    102                 //全部执行完毕没有发现错误,提交事务
    103                 foreach (var i in conntable)
    104                 {
    105                     var dc = new SqlCommand("COMMIT TRAN", i.Value);
    106                     dc.ExecuteNonQuery();
    107                     i.Value.Close();
    108                 }
    109                 return new TransInfo()
    110                 {
    111                     IsSuccess = true,
    112                     Total = sqlwithconn.Count,
    113                     WrongMessage = ""
    114                 };
    115 
    116             }
    117             catch (TransException e)   //1.回滚所有操作2.关闭所有已经打开的数据库连接4.生成错误对象
    118             {
    119                 foreach (var i in e.DoneConnection)
    120                 {
    121                     if (!i.Equals(e.CurrentConnection))
    122                     {
    123                         var dc = new SqlCommand("ROLLBACK TRAN", i);
    124                         dc.ExecuteNonQuery();
    125                     }
    126                     i.Close();
    127                 }
    128                 return new TransInfo()
    129                 {
    130                     IsSuccess = false,
    131                     Total = sqlwithconn.Count,
    132                     WrongMessage = string.Format("在连接{0}中,操作{1}出现错误,错误信息:{2}", e.wrongAt, e.wrongSQL, e.Message)
    133                 };
    134             }
    135         }
    

    CAP理论

    由ado.net管理的业务改为和谐手动提交业务和Commit恐怕RollBack操作:

    遍及式事务的目标是涵养分库数据一致性,而跨库事务会境遇各个不可控制的标题,如个别节点恒久性宕机,像单机事务同样的ACID是力不从心奢望的。此外,产业界有名的CAP理论也告知大家,对布满式系统,须求将数据一致性和系统可用性、分区容忍性放在天平上同台思索。

    设若大家有哪些更加好的消除方案以来,希望和我们多多调换和指教。

    ■ 两品级之间插入计划阶段。

    在遍布式系统中,一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)3个要素最多只可以同时满足多个,不可兼得。其中,分区容忍性又是必备的。

    ■ 单点难点。

    1、二PC方案——强1致性

    分区容忍性:特指对网络分区的容忍性。

    4.缓存数码最终一致性。

    ▌强一致性:数据更新成功后,大肆时刻有所别本中的数据没什么区别的,一般采纳1块的不2诀要完毕。

    核心情想:

    对购物转账等电商和金融业务,中间件层的二PC最大难点在于业务不可知,1旦出现不可抗力或意外的一致性破坏,如数据节点恒久性宕机,业务难以依据二PC的日志进行填空。金融意况下,数据壹致性是珍宝,业务要求对数据有整个的掌握控制力,建议使用TCC这类遍及式事务模型,或基于音信队列的柔性事务框架,那三种方案都在业务层实现,业务开辟者具备丰裕掌握控制力,能够结合SOA框架来架构,包蕴Dubbo、Spring Cloud等。

    本文由68399皇家赌场发布于集群主机,转载请注明出处:C#中跨库事务处驾驭决方案,

    关键词: 68399皇家赌场 网易企业邮箱 企业

上一篇:thinkphp达成1陆三、QQ邮箱收发邮件的法子

下一篇:没有了