如何避免误用分布式事务(System.Transactions.TransactionScope)
以下内容来源与:http://www.cyqdata.com/cyq1162/article-detail-54453
1:本地事务DbTransaction和分布式事务TransactionScope的区别:
1.1:System.Data.Common.DbTransaction:
本地事务:这个没什么好说了,就是单个事务,每种数据库都有自己的实现,事务的深度内涵可以搜索查看相关的文章,不是本文介绍的重点。
1.2:System.Transactions.TransactionScope:
分布式事务,需要添加引用System.Transactions,同时启用MSDTC分布式事务服务:通常使用方式为:
using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
{
//代码块A
//代码块B
ts.Complete();//提交事务
}
分布式事务本质上是引入了第三方裁判,来想办法对多个本地事务监控同时成功或同时失败,这里分享几个知识点:
A:如果代码块里,若存在两个或以上数据库链接DbConnection,则需要启动微软的MSDTC分布式事务服务。
用命令行启动或停止服务:
B:如果代码块里,只有一个数据库链接DbConnection,那么实际上只是本地事务在处理,就算MSDTC分布式事务服务没启动,也不会报错。
C:对于TransactionScope包含的代码块,本质是监控了代码块里数据库链接DbConnection的个数,如果有多个不同的对象,则引入MSDTC当裁判,而实际执行的事务的还是各个本地事务。
D:MSDTC总是不够稳定,我在测试时两个简单的事务一起时,按住F5不停刷新,竟然能把MSSQL服务也给挂了,而用本地事务就算跨库也不会有问题。
所以,不是必须的情况,尽量不要引入分布式事务,应该避免使用TransactionScope来包含事务块的冲动。
2:可以用本地事务解决,避免使用分布式事务场景:
2.1:项目只有一个数据库,这个是最应该避免,多个表间的事务, 完全是本地事务可处理的范围:
问题:一个代码块里N个实体类杂交操作,每个实体类带有各种的数据库链接,从而引发了MSDTC。
可以:共用一个DbConnection对象,来避免启用MSDTC。
2.2:项目多个数据库,如果数据库间使用了相同的访问账号和密码,这种情况也可以避免:
每种数据库有自己的解决方式:像MSSQL,跨库处理只要加前缀(dbname..tablename)就可以,因此也使的只使用本地事务就可以处理了。
3:回顾下我以前的项目场景:
3.1:从下图是我08年在中域的项目:有19个数据库,对于数据库链接而言,唯一的不同只有数据库的名称:
进化:能不能只保留一条,其它的通过动态切换数据库名称来改链接字符串?
3.2:那时候,我的架构还是很新手,通过CodeSmith生成了大量的代码文件:
实体类项目,工厂项目,接口项目,数据操作,还有大量的增删改查存储过程,只是为了基础的增删改查而且只针对MSSQL。
随便展开一个项目都会看到大量的文件夹,里面有大量的文件,而这些东东,都是代码生成器的杰作:
19个数据库啊,NN个表,光生成这些基本的增删改查,整个项目就好像高端大气上档次了。
进化:能不能消灭这些大量的文件,简单是我们不断追求的目标。
3.3:这么多数据库,如何跨数据库事务?
对于生成的大量的实体,每个表的操作都是一个新的链接,单库间的事务都必须MSDTC了,更别说19个库间的跨库事务了。
进化:能不能本地事务搞定这些,这是每个ORM可以思考的方向。
4:CYQ.Data 提供的解决方案:
为了消灭上述的那些大量的生成文件,我在后续新的公司写了传统的ORM框架:XQData(这个框架一直没露过面,也只是支持MSSQL,用反射消灭了好多层,只留下实体层)。
对于框架的演进,多数都来源于项目中遇到的问题,或复杂的场景,需要解决或者简化,才有了不断升级的可能,并不是无中生有,因此,一个框架,如果不能不断在在项目中实战,那么很多问题和细节等可能都无法发现,更新也会遥遥无期。
而CYQ.Data的不断升级,说明我一直在奋战在一线的编码生涯中和网友各大项目中的实战反馈中。
下面针对最近的优化调整,演示下CYQ.Data是怎么解决上面提到的几个问题:
4.1:多个数据库的数据库链接切换:
A:先用配置工具生成针对多数据库的枚举文件,和成demo和test两个数据库:
两个数据库就生成两次了。
B:配置一个默认的链接字符串,到Demo数据库:
<add name="Conn" connectionString="server=.;database=demo;uid=sa;pwd=123456"/>
C:打印操作Test数据库表的链接字符串:
using (MAction action = new MAction(TestEnum.Users))
{
Console.WriteLine(action.ConnectionString);
}
输出:
这里自动切换了数据为名称为新的链接,而我动手脚的地方就是在枚举的名称了。
4.2:本地多数据库跨事务,示例:
AppDebug.OpenDebugInfo = true;
AppDebug.Start();
using (MAction action = new MAction(DemoEnum.Users))
{
action.BeginTransation();//开启事务
action.Fill(12);
Console.WriteLine(action.ConnectionString);//打印数据库链接
action.ResetTable(TestEnum.Users);//切换数据库
Console.WriteLine(action.ConnectionString);//打印数据库链接
action.Fill(12);
action.EndTransation();
}
Console.WriteLine(AppDebug.Info);//输出所有执行的SQL语句。
AppDebug.Stop();
输出的结果:
说明:在事务中,当检测到事务开启时,为了使用本地事务,并没有切换数据库,而是采用了前缀来执行操作。
如果注释掉代码中的事务,则是直接切换数据库链接,输出会如下图:
说明:如果没有开启事务,则直接切换了数据库链接,并消消灭前缀语法。
总结:
对于.NET领域,微软除了提供这个不太稳定的MSDTC,似乎没有发现其它分布式事务的解决方案,好在一般的项目,我们在本地事务就可以处理。
希望微软可以在一些重点分布式上多做点研究、普及和推广,提供大型项目的解决方案,别整天操碎心在那些简单的增删改查上。
如何避免误用分布式事务(System.Transactions.TransactionScope)的更多相关文章
- 事务使用中如何避免误用分布式事务(System.Transactions.TransactionScope)
1:本地事务DbTransaction和分布式事务TransactionScope的区别: 1.1:System.Data.Common.DbTransaction: 本地事务:这个没什么好说了,就是 ...
- 谈谈分布式事务之三: System.Transactions事务详解[上篇]
在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务..NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集 ...
- 关于分布式事务的一个误解:使用了TransactionScope就一定会开启分布式事务吗?
背景: 事务是数据库管理系统的一个基本概念,事务具有四个基本特点,即ACID:原子性(Atomicity).一致性(Consistency).隔离性(Isolation)和持久性(Durability ...
- .NET分布式事务--TransactionScop
一.开启DTC服务 方式一 计算机—管理—服务—Distributed Transaction Coordinator—属性—开启 方式二 CMD命令子界面输入:net start msdtc 二.设 ...
- 【WCF--初入江湖】07 分布式事务
07 分布式事务 一.前言 [1]理解事务特性 [2]掌握TransactionFlow 特性 [3]掌握WCF中的事务属性 TransactionAutoCompleteOnSessionClose ...
- ASP.NET中分布式事务的使用
之前发表了一篇事务的存储过程,最近在做项目的时候遇到分布式事务,所有总结一下,跟大家分享和交流一下经验.首先说明为什么要分布式事务呢?先说说我在项目的哪里遇到分布式事务吧,我是在做网站后台开发的时候, ...
- WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程
今天我们继续学习WCF分布式开发步步为赢系列的12节:WCF事务机制(Transaction)和分布式事务编程.众所周知,应用系统开发过程中,事务是一个重要的概念.它是保证数据与服务可靠性的重要机制. ...
- EF 事务(非分布式事务)
在EF 中怎么使用事务? 这个问题纠结了我好久,直到有人跟我一起讨论,我和同事一起讨论查资料. 查的好多资料都是使用 TransactionScope,用 TransactionScope 可处理分布 ...
- 谈谈分布式事务之三: System.Transactions事务详解[下篇]
在前面一篇给出的Transaction的定义中,信息的读者应该看到了一个叫做DepedentClone的方法.该方法对用于创建基于现有Transaction对 象的“依赖事务(DependentTra ...
随机推荐
- C#关于HttpClient的应用(二):融云IM集成
public class RcHttpClient:BaseHttpClient { private String appKey; private String appSecret; public R ...
- java web.xml listener servlet 和filter加载顺序
在该项目中总会遇到一些关于加载的优先问题.最近遇到了同样的类别似的,所以,如果你发现信息汇总下,以下是转载其他一些人,毕竟,人们写的不错.它不重复创建的轮.只是略作修改自己的观点. 首先能够肯定的是, ...
- 开发现代ASP.NET应用程序
新思想.新技术.新架构——更好更快的开发现代ASP.NET应用程序(续1) 今天在@张善友和@田园里的蟋蟀的博客看到微软“.Net社区虚拟大会”dotnetConf2015的信息,感谢他们的真诚付 ...
- BS导出csv文件的通用方法(.net)
最近把以前项目里用的导出文件的功能提取成了dll,通过读取Attribute来得到要导出的表头(没有支持多语言),使用时只要组织好要导出的数据,调用方法就好了,希望对大家有用. 使用时只需引用下载包里 ...
- 剖析Jetty实现原理
之前写一个简单易用Jetty文章.Jetty对于做JAVA Web发展的方面来说并不陌生,他是一个servlet集装箱,只有相对Tomcat这是比较简单的设计,并且也相对简单,使用灵活,我是学习和使用 ...
- BestCoder Round #11 (Div. 2) 题解
HDOJ5054 Alice and Bob Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- MVC4新功能...压缩和合并js文件和样式文件
1.在App_Start文件夹中BundleConfig.cs类中添加相应的文件 1.1bundles.Add(new ScriptBundle("~/bundles/adminJs&quo ...
- Java实现缓存(类似于Redis)
Java实现缓存,类似于Redis的实现,可以缓存对象到内存中,提高访问效率.代码如下: import java.util.ArrayList; import java.util.HashMap; i ...
- SQL点滴1—SET QUOTED_IDENTIFIER OFF语句的作用
原文:SQL点滴1-SET QUOTED_IDENTIFIER OFF语句的作用 先看下面几个sql语句 代码 SELECT * FROM [USER] WHERE a= 'netasp' ...
- 从PHP官网被攻击,到熟悉SSL(安全链路层)
近日,php官网php.net网站受到恶意攻击,攻击者至少破坏了2个服务器.PHP工作组不得不重置用户密码. PHP工作组在随后的调查发现,攻击者成功的对网站注入了恶意的JavaScript代码,这个 ...