【转】TransactionScope事务简介

2024-01-01 22:58

本文主要是介绍【转】TransactionScope事务简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在.NET 1.0/1.1 版本我们使用SqlTransaction.处理事务

 
  1. string connString = ConfigurationManager.ConnectionStrings["db"].ConnectionString;

  2. using (var conn = new SqlConnection(connString))

  3. {

  4. conn.Open();

  5. using (IDbTransaction tran = conn.BeginTransaction())

  6. {

  7. try

  8. {

  9. // transactional code...

  10. using (SqlCommand cmd = conn.CreateCommand())

  11. {

  12. cmd.CommandText = "INSERT INTO Data(Code) VALUES('A-100');";

  13. cmd.Transaction = tran as SqlTransaction;

  14. cmd.ExecuteNonQuery();

  15. }

  16. tran.Commit();

  17. }

  18. catch(Exception ex)

  19. {

  20. tran.Rollback();

  21. throw;

  22. }

  23. }

  24. }

到了.NET2.0微软提供了TransactionScope

 
  1. using (var scope = new TransactionScope())

  2. {

  3. //transctional code…

  4. scope.Complete();

  5. }

TransactionScope使用起来简单,只需要把代码写在大括号里,最后加上scope.Complete();就可以了

 

接下来主要介绍TransactionScope的简单使用

TransactionScope有三个属性:IsolationLevel,Timeout,TransactionScopeOption

Property

Default Value

Available Options

IsolationLevel(隔离等级)

Serializable

Serializable, Read Committed, Read Un Committed, Repeatable Read

Timeout(超时)

1 Minute

Maximum 10 Minutes

TransactionScopeOption

(选项)

Required

Required, Required New, Suppress

用以下代码可以看到他们属性的值

 
  1. using (var scope = new System.Transactions.TransactionScope())

  2. {

  3. System.Transactions.IsolationLevel isolationLevel = Transaction.Current.IsolationLevel;

  4. TimeSpan defaultTimeout = TransactionManager.DefaultTimeout;

  5. TimeSpan maximumTimeout = TransactionManager.MaximumTimeout;

  6. }

由图可以看到,TransactionScope默认情况下的隔离等级为Serializable,超时时间为1分钟

 

Dirty Read(脏读):脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

Non Repeatable Read(不可重复读):是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)

Phantom Read(幻读):是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象

发生了幻觉一样。

隔离等级的四种选择:

Serializable(序列化):它在读/写操作时锁定数据。由于这个原因,很多时候它会创建一个死锁,因此你可能会得到一个超时异常。可以将此隔离级别用于高度安全的事务性应用程序(如金融应用程序)。缺点是性能低

Repeatable Read(可重复读):同为Serializable,除了允许幻读。可以使用在金融中的应用或严重事务性应用,但需要知道幻读创造的场景是不存在的。

Read Committed(读提交):大多数应用程序都可以使用它。SQLServer默认隔离级别是这个。不会有脏读

Read Un-Committed(读不提交):这些应用程序不需要支持并发事务。

 

TransactionScope使用:

对CommonTest_ExamInfo_ExamStudents表中的一个学生进行修改操作,隔离等级为Read Committed

 
  1. var option = new TransactionOptions();

  2. option.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

  3. option.Timeout = TimeSpan.FromMinutes(1);

  4. using (var scope = new TransactionScope(TransactionScopeOption.Required, option))

  5. {

  6. String sql = @"UPDATE Students SET sStuName = @sStuName WHERE sID = @sID AND sIdentityID = @sIdentityID ";

  7. SqlParameter[] args = new SqlParameter[3];

  8. args[0] = new SqlParameter("@sStuName", "张三");

  9. args[1] = new SqlParameter("@sTID", "2017120608575");

  10. args[2] = new SqlParameter("@sIdentityID", "36281763861231231");

  11. if (testDB.Database.ExecuteSqlCommand(sql, args) > 0)

  12. {

  13. scope.Complete();

  14. return true;

  15. }

  16. else

  17. {

  18. return false;

  19. }

  20. }

当执行完代码红色那行后,可以看到,SQLserver启动了隔离等级为Read Committed的事务,然后执行修改操作。 此时,如果执行

SELECT TOP 1000  * FROM [dbo].[Students]  SQL语句,如正在修改的数据也包括在内,则不能被查出来,修改操作也是如此。

直到跳出using括号后,查询语句才能被真正执行。

但是,此时数据库可以执行与事务修改操作无关的数据,如执行

SELECT * FROM Students

WHERE sTID = '2017120608575'  AND sIdentityID = '36281763861231231'    SQL语句,可以顺利查询到数据

此外,还有一点需要说明,当连续执行两次相同的修改操作,即第二次其实是没有真正修改数据库数据的,此时可以对操作的数据行查询

场次安排不使用事务和使用TransactionScope的Read Committed进行对比

 

不使用事务如下:

 
  1. using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))

  2. {

  3. testDB.Database.ExecuteSqlCommand("delete from dbo.ChildTestList where sTID=@sTid;delete from dbo.ExamStudents where sTID=@sTid;", new SqlParameter("@sTid", sTID));

  4. if (testDB.Database.Connection.State != ConnectionState.Open)

  5. {

  6. testDB.Database.Connection.Open(); //打开Connection连接

  7. }

  8. if(!DbHelper.BulkInsert<ExamStudents>((SqlConnection)testDB.Database.Connection, "ExamStudents", lstExamStudents))

  9. {

  10. if (testDB.Database.Connection.State != ConnectionState.Closed)

  11. {

  12. testDB.Database.Connection.Close(); //关闭Connection连接

  13. }

  14. return false;

  15. }

  16. if (!DbHelper.BulkInsert<ChildTestList>((SqlConnection)testDB.Database.Connection, "ChildTestList", lstCldTestTB))

  17. {

  18. if (testDB.Database.Connection.State != ConnectionState.Closed)

  19. {

  20. testDB.Database.Connection.Close(); //关闭Connection连接

  21. }

  22. return false;

  23. }

  24.  
  25. if (testDB.Database.Connection.State != ConnectionState.Closed)

  26. {

  27. testDB.Database.Connection.Close(); //关闭Connection连接

  28. }

  29. var testInfo = testDB.TestList.Where(p => p.sTID == sTID).FirstOrDefault();

  30. if (nSaveType == 1)

  31. {

  32. testInfo.nTestState = 14;

  33. }

  34. else

  35. {

  36. testInfo.nTestState = 13;

  37. }

  38. testDB.SaveChanges();

  39. scope.Complete();

  40. return true;

  41. }

添加TransactionScope事务:

以上两图显示他们性能上并无明显区别。

 

总结:可以使用TransactionScopeRead Committed隔离等级进行一系列事务操作,性能没有太大影响。一般不使用TransactionScope默认的Serializable隔离等级,因为它需要开很多锁,性能会因此而下降。使用TransactionScope应注意尽量让using大括号里面的代码都短一些,这样它出错的几率更小,事务回滚的几率也会减少。所以出于数据的一致性考虑,一系列对数据库的操作可添加TransactionScopeRead Committed隔离等级的事务。

 

引用一下别人的导读:在实际开发工作中,执行一个事件,然后调用另一接口插入数据,如果处理逻辑出现异常,那么之前插入的数据将成为垃圾数据,我们所希望的是能够在整个这个方法定义为一个事务,TransactionScope 类提供一个简单方法,通过这一方法,您不必与事务本身交互,即可将代码块标记为参与某个事务。TransactionScope对象创建了一个事务,同时将该事务设置给Transaction类的Current属性。

一、TransactionScope的优点
1、使用起来比较方便.TransactionScope可以实现隐式的事务,使你可以在写数据访问层代码的时候不用考虑到事务,而在业务层的控制事务.
2、可以实现分布式事务,比如跨库或MSMQ.
 
二、TransactionScope缺点
1、性价比不高.比如,你只是在"Scope"里控制一个库的事务.用"TransactionScope"就有点浪费了.
2、一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139端口.这个端口不可以更改
 
三、如果你不得不用分布式事务,那也得琢磨琢磨
1.这步操作一定得在事务当中吗?这步操作如果没完成或者失败了,值得回滚整个事务吗?难道没有优雅的补偿措施或者容错措施?
2.分布式事务涉及到的点,必须的这么多?必须得实时的操作这一大串?不能通过通知类操作去精简掉某些点?
3.在发起分布式事务之后,你是不是做了事务无关的操作,尽管这些操作跟事务无关?(如,读取数据、计算、等用户返回消息、等其他模块的调用返回等等)要知道事务应该尽快结束。
4.你没有把一些读操作也算在事务里面了吧?这是很容易犯的错误,你在事务中Enlist了一个select 操作。
5.你的操作,某些步骤可以等全部操作完成之后再执行.这类操作具有明显的通知类特点。通知类操作是说,我给你一个通知,并且我保证通知到了你;你必须吃下这个通知,并且保证处理成功,但是你不必我一通知你你就处理。这样的操作很明显可以用另外一个任务去搞。
 
四、使用分布式事务注意如下几点
1:确保参与事务的machine开启了分布式事务支持;
2:如果machine开启了防火墙,需要设置msdtc进程为例外;
3:参与事务的machine不能跨域(如果跨域,目前微软还没有确切的解决方案);
4:多数据库时才使用分布式事务,如果是同一个数据库,最好使用SqlTransaction.

这篇关于【转】TransactionScope事务简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/560731

相关文章

MYSQL事务死锁问题排查及解决方案

《MYSQL事务死锁问题排查及解决方案》:本文主要介绍Java服务报错日志的情况,并通过一系列排查和优化措施,最终发现并解决了服务假死的问题,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录问题现象推测 1 - 客户端无错误重试配置推测 2 - 客户端超时时间过短推测 3 - mysql 版本问

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

SpringBoot嵌套事务详解及失效解决方案

《SpringBoot嵌套事务详解及失效解决方案》在复杂的业务场景中,嵌套事务可以帮助我们更加精细地控制数据的一致性,然而,在SpringBoot中,如果嵌套事务的配置不当,可能会导致事务不生效的问题... 目录什么是嵌套事务?嵌套事务失效的原因核心问题:嵌套事务的解决方案方案一:将嵌套事务方法提取到独立类

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

业务协同平台--简介

一、使用场景         1.多个系统统一在业务协同平台定义协同策略,由业务协同平台代替人工完成一系列的单据录入         2.同时业务协同平台将执行任务推送给pda、pad等执行终端,通知各人员、设备进行作业执行         3.作业过程中,可设置完成时间预警、作业节点通知,时刻了解作业进程         4.做完再给你做过程分析,给出优化建议         就问你这一套下

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么? K8s的架构原理  控制平面(Control plane)         kube-apiserver         etcd         kube-scheduler         kube-controller-manager         cloud-controlle

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

【Tools】AutoML简介

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 AutoML(自动机器学习)是一种使用机器学习技术来自动化机器学习任务的方法。在大模型中的AutoML是指在大型数据集上使用自动化机器学习技术进行模型训练和优化。