首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

细说事宜

2012-12-24 
细说事务一、事务的定义所谓事务,它是一个操作集合,这些操作要么都执行,要么都不执行,它是一个不可分割的工

细说事务

一、事务的定义

所谓事务,它是一个操作集合,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。典型的例子就像从网上银行系统的帐户A转帐到帐户B,它经过两个阶段:1.从帐户A取出款项。2.把款项放入帐户B中。这两个过程要么同时成功,要么同时失败,这一系列的操作就被称为事务性(Transactional)操作。

在一个事务性操作的环境下,操作有着以下的4种特性,被称为ACID特性

原子性(Atomicity)当事务结束,它对所有资源状态的改变都被视为一个操作,这些操作要不同时成功,要不同时失败  一致性(Consistency)操作完成后,所有数据必须符合业务规则,否则事务必须中止隔离性(Isolation)事务以相互隔离的方式执行,事务以外的实体无法知道事务过程中的中间状态持久性(Durable)事务提交后,数据必须以一种持久性方式存储起来

?

?

?

?

?

?

?

回到目录


二、事务管理器

在软件系统当中可以看到无论在数据库、Web服务、WCF、文件系统都存在着数据参与到事务运作当中,我们把管理这些数据的工具称为资源管理器RM(Resources Manager)。而事务管理器TM(Transaction Manager)就是协调多个资源管理器的工作,保证数据完整性的工具。

?

细说事宜

?

由上图可以看到事务的管理流程,系统通知事务管理器TM来启动事务,事务管理器TM控制向多个资源管理器RM并协调RM之间的事务操作。图中存在两个持久化RM,分别管理数据库和文件系统,这些事务操作要不同时成功,要不同时失败。

?

事务管理器一般分为三类:轻量级事务管理器(LTM)、核心事务管理器(KTM)、分布式事务协调器(DTC)

?

1. 轻量级事务管理器 (LTM)

它是包括在System.Transactions 命名空间内的一个事务管理框架,它只能管理单个应用程序域内的事务。LTM 可以管理多个易变的RM,但只能管理一个持久化RM。若事务试图加入第二个持久化RM,那轻量级事务管理器LTM将提升级别。LTM是性能最高的事务管理器,在可选择的情况下应该尽可能地使用 LTM 事务管理器。

这里易变RM是指它参与会引发 “未确定状态” 的2PC事务时候,不需要恢复服务,更多时候,易变RM的数据只存储在内存当中。

而持久化RM是指它参与会引发 “未确定状态” 的2PC事务时候,它需要恢复服务,持久化RM管理的数据是在于硬盘当中。所以,参与2PC事务的的持久RM必须有新旧两个版本,如果事务引发 “未确定状态” 的时候,那么它就会联系持久化RM,恢复到其中一个版本。

2PC说明 (http://blogs.msdn.com/b/diegumzone/archive/2006/08/14/699219.aspx)

2PC 是2 Phase Commit的缩写,代表事务的2阶段提交验证算法:在数据提交时,第一阶段:应用程序记录每个数据源并执行更新请求,TM通知每个RM来执行分布式事 务,然后每个RM都对数据执行本地的事务,在事务将提交前,TM会与各个RM进行信息交换,以获知更新是否成功。第二阶段,如果其中任何一个RM表示更新 失败,TM就会通知所有的RM事务操作失败,实现数据回滚。如果所有RM的操作都成功,那么整个TM事务就宣告成功。


2. 核心事务管理器 (KTM)

KTM是用于Windows Vista和Windows Server 2008 系统中的轻量级事务管理器,与LTM相像,它可以管理多个易变的RM,但只能管理一个持久化RM。

?

3. 分布式事务协调器(DTC)

分布式事务协调器DTC(Distributed Transaction Coordinator)能管理多个持久化RM中的事务,事务可以跨越应用程序域、进程、硬件、域等所有的边界。在Windows Server 2008当中,DTC支持OleDB、XA、WS-AtomicTransaction、WSCoordination、WS-BusinessActivity等多个协议。由于分布式事务需要在多个参与方之间实现多次通讯,所以是一种巨大的开销,因此,在可以使用LTM和KTM的时候,应该尽量避免使用DTC。在上面图片中的事务同时启动了两个RM分别处理数据库数据与文件数据,当中启动的就是DTC分布式事务。

?

4.事务类 System.Transactioins.Transaction

Transaction是由Framework 2.0 就开始引入,用于显示管理事务的一个类。通过Transaction可以直接管理事务的中止、释放,也可以获取、克隆当前的环境事务类。

Transaction的公用属性

其中Transaction.Current 比较常用,它可以指向一个当前运行环境中的事务,如果环境事务不存在,系统将返回一个null

Transaction transaction=Transaction.Current;

属性说明Current获取或设置环境事务。IsolationLevel获取事务的隔离级别。TransactionInformation检索有关某个事务的附加信息。

?

?

?

?

?

Transaction的常用公用方法

其中Rollback、Dispose方法可以控制事务中止、释放,而Clone、DependentClone方法在多线程操作中经常用到,在 “异步事务” 一节中将详细说明

方法说明Rollback中止事务、回滚。Dispose释放事务对象。Clone    创建事务克隆DependentClone创建事务的依赖克隆。

?

?

?

?

?

?

Transaction的事件

在事务完成后,会触发TransactionCompleted事件,开发人员可以在此事件的过程监测其状态

事件说明TransactionCompleted在事务完成后执行

?

?

?

?

?

5. 事务状态 TransactionInformation

上面讲解过事务分为本地事务与分布式事务,而Transaction类的TransactionInformation是事务状态的记录,它可以跟踪事务动作,分辨事务现处的状态,记录本地事务与分布式事务的Guid。

TransactionInformation有两个重要成员

?

2.开发实例

在传统的ADO.NET中使用事务,方法如下:

http://msdn.microsoft.com/zh-cn/library/system.transactions.transactionscopeoption.aspx

成员名称说明RequiredRequiresNewSuppress

?


3.2使用分布式事务协调多个服务端的操作

在分布式系统当中,单个客户端可能引用多个服务,分布式事务能协调多方的操作。多个系统中的操作要不同时成功,要不同时失败。下面的例子中,客户端同时引用了ExampleService服务和ExtensionService服务,并启动了分布式事务。而在客户端与两个服务端的事务都是通过DistributedIndentifier 作为事务的标识的。

服务端:

contract="Example.IExampleService" 62 bindingConfiguration="defaultWSHttpBinding" > 63 <identity> 64 <dns value="localhost" /> 65 </identity> 66 </endpoint> 67 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 68 <host> 69 <baseAddresses> 70 <add baseAddress="http://localhost:7200/Example/ExampleService/" /> 71 </baseAddresses> 72 </host> 73 </service> 74 </services> 75 </system.serviceModel> 76 </configuration> 77 78 //*************************************Extension**************************************************************// 79 namespace Extension 80 { 81 [ServiceContract] 82 public interface IExtensionService 83 { 84 [OperationContract] 85 void DoWork(); 86 } 87 88 public class ExtensionService : IExtensionService 89 { 90 [OperationBehavior(TransactionAutoComplete=true,TransactionScopeRequired=true)] 91 [TransactionFlow(TransactionFlowOption.Allowed)] 92 public void DoWork() 93 { 94 Transaction transaction = Transaction.Current; 95 string info = string.Format(" DistributedIndentifier:{0} \n LocalIndentifier:{1}", 96 transaction.TransactionInformation.DistributedIdentifier, 97 transaction.TransactionInformation.LocalIdentifier); 98 Console.WriteLine("DoWork: \n" + info); 99 }100 101 static void Main(string[] args)102 {103 Console.WriteLine("extension service start");104 ServiceHost host = new ServiceHost(typeof(ExtensionService));105 host.Open();106 Console.ReadKey();107 host.Close();108 }109 }110 }111 <configuration>112 <!--略-->113 ................... 114 </configuration>

值得注意的一点,事务必须由客户端提交,当客户端调用无事务状态时,两个服务端的事务则无法进行辨认,即其中一方出错,事务出现回滚,另一方也无法感知,这样容易引起逻辑性错误。试着把客户端代码改为 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)){...},再运作一下,可以看到以下结果。事务都是由两个服务端分别管理,系统并无启动分布式事务。

细说事宜

?

应该注意:分布式事务会耗费较大的资源,在没必要的情况下,应该尽量使用LTM级量级事务管理器,而避免使用DTC分布式事务管理。

?

4.事务的的隔离性

事务的隔离性是通过TransactionIsolationLevel来定义的,它存在以下几个级别:

Unspecified  ?ReadUncommitted在读取数据时保持共享锁以避免读取已修改的数据,但在事务结束前这些数据可能已更改,因此会导致不可重复的读取和虚假数据。ReadCommitted发出共享锁定并允许非独占方式的锁定。 RepeatableRead在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。这防止了不可重复的读取,但仍有可能产生虚假行。 Serializable默认级别,也是最高级别。表示事务完成前禁止外界更新数据Chaos不使用隔离  Snapshot?

?

?

?

?

?

?

?


?

?

需要注意服务端与客户端必须使用同一级别的隔离模式,否则系统将会抛出FaultException异常。

服务类必须在至少一个方法开启了事务后才可以设置隔离模式

?

结束语

事务是在多个层次都会使用到的,但很多项目当中往往会忽略了这一点而只在数据层使用,在大型的系统当中这样可能会影响到系统的一致性。特别是在分布式系统当中,操作往往同时存在于多个不同的系统当中,事务的处理更显示出其重要性。

希望这篇文章能对大家的工作有帮助,对.NET开发有兴趣的朋友请加入博客园讨论小组“.NET高级编程” 一起探讨!

热点排行