谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx

上传人:b****2 文档编号:1507443 上传时间:2023-04-30 格式:DOCX 页数:8 大小:19.79KB
下载 相关 举报
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第1页
第1页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第2页
第2页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第3页
第3页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第4页
第4页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第5页
第5页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第6页
第6页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第7页
第7页 / 共8页
谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx_第8页
第8页 / 共8页
亲,该文档总共8页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx

《谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx》由会员分享,可在线阅读,更多相关《谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx(8页珍藏版)》请在冰点文库上搜索。

谈谈分布式事务之三 SystemTransactions事务详解下篇文档格式.docx

DependentTransaction通过Transaction的DependentClone方法创建,该方法具有一个DependentCloneOption枚举类型的参数,体现了被依赖的事务再上尚未接受到依赖事务的通知(调用Complete或者Rollback方法)得情况下,提交或者完成所采取的事务控制行为。

DependentCloneOption提供了两个选项,BlockCommitUntilComplete表示被依赖事务会一直等待接收到依赖事务的通知或者超过事务设定的超时时限;

而RollbackIfNotComplete则会直接将被依赖的事务回滚,并抛出TransactionAbortedException异常。

publicclassTransaction:

IDisposable,ISerializable3:

//其他成员5:

publicDependentTransactionDependentClone(DependentCloneOptioncloneOption);

6:

}7:

publicenumDependentCloneOption8:

{9:

BlockCommitUntilComplete,10:

RollbackIfNotComplete11:

下面的代码演示了如果通过依赖事务,采用异步的方式进行银行转账操作。

借助于组件ThreadPool,将主线程环境事务的依赖事务传递给异步操作代理,开始异步操作的时候将此依赖事务作为当前的环境事务,那么之后的操作将自动在当前事务下进行。

privatestaticvoidTransfer(stringaccountFrom,stringaccountTo,doubleamount)2:

{3:

TransactionoriginalTransaction=Transaction.Current;

4:

CommittableTransactiontransaction=newCommittableTransaction();

try6:

{7:

Transaction.Current=transaction;

8:

ThreadPool.QueueUserWorkItem(state=&

gt;

9:

{10:

Transaction.Current=stateasDependentTransaction;

11:

try12:

{13:

Withdraw(accountFrom,amount);

14:

Deposite(accountTo,amount);

15:

(stateasDependentTransaction).Complete();

16:

}17:

catch(Exceptionex)18:

{19:

Transaction.Current.Rollback(ex);

20:

}21:

finally22:

{23:

(stateasIDisposable).Dispose();

24:

Transaction.Current=null;

25:

}26:

},Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete));

27:

//其他操作28:

transaction.Commit();

29:

}30:

catch(TransactionAbortedExceptionex)31:

{32:

transaction.Rollback(ex);

33:

Console.WriteLine("

转帐失败,错误信息:

{0}"

ex.InnerException.Message);

34:

}35:

catch(Exceptionex)36:

{37:

38:

throw;

39:

}40:

finally41:

{42:

Transaction.Current=originalTransaction;

43:

transaction.Dispose();

44:

}45:

由于在调用DependentClone方法创建依赖事务时指定的参数为DependentCloneOption.BlockCommitUntilComplete,所以主线程在调用Commit方法提交事务的时候,由于依赖事务尚未结束(调用Complete或者Rollback方法),在这里会一直等待。

如果依赖事务的Complete或者Rollback一直没有调用,那么被依赖的事务会一直等到超出事务设置的超时时限。

所以,对于基于BlockCommitUntilComplete选项创建的依赖事务来说,应该及时地调用Complete或者Rollback方法。

2、通过DependentTransaction实现事务型方法

这里所说的事务型方法是指方法的执行总是在事务中执行。

具体来讲,有两种不同的事务应用场景:

如果当前不存在环境事务,那么方法的执行将在一个独立的事务中执行;

反之,如果存在环境事务,在方法执行会自动加入到环境事务之中。

比如说,存储(Deposit)和提取(Withdraw)就是典型的事务型操作。

对于单纯的存取款的场景,应该创建一个新的事务来控制存储和提取操作的执行,以确保单一帐户款项的数据一致性。

如果在转账的场景中,应在在转账开始之前就创建一个新的事务,让提取和存储的操作自动加入到这个事务之中。

我们现在就结合可提交事务和依赖事务将Deposit和Withdraw两个方法定义成事务型方法,为了相同代码的重复,在这里把事务控制部分定义在如下一个InvokeInTransaction静态方法中:

staticvoidInvokeInTransaction(Actionaction)2:

CommittableTransactioncommittableTransaction=null;

DependentTransactiondependentTransaction=null;

if(null==Transaction.Current)7:

{8:

committableTransaction=newCommittableTransaction();

Transaction.Current=committableTransaction;

10:

}11:

else12:

dependentTransaction=Transaction.Current.DependentClone(DependentCloneOption.RollbackIfNotComplete);

Transaction.Current=dependentTransaction;

}16:

17:

try18:

action();

if(null!

=committableTransaction)21:

{22:

committableTransaction.Commit();

23:

}24:

=dependentTransaction)26:

{27:

dependentTransaction.Complete();

28:

}29:

catch(Exceptionex)31:

finally36:

Transactiontransaction=Transaction.Current;

40:

}41:

InvokeInTransaction方法的参数是一个Action类型的代理(Delegate),表示具体的业务操作。

在开始的时候记录下当前的环境事务,当整个操作结束之后应该环境事务恢复成该值。

如果存在环境事务,则创建环境事务的依赖事务,反之直接创建可提交事务。

并将新创建的依赖事务或者可提交事务作为当前的环境事务。

将目标操作的执行(action)放在try/catch中,当目标操作顺利执行后,调用依赖事务的Complete方法或者可提交事务的Commit方法。

如果抛出异常,则调用环境事务的Rollback进行回滚。

在finally块中将环境事务恢复到之前的状态,并调用Dispose方法对创建的事务进行回收。

借助于InvokeInTransaction这个辅助方法,我们以事务型方法的形式定义了如下的两个方法:

Withdraw和Deposit,分别实现提取和存储的操作。

staticvoidWithdraw(stringaccountId,doubleamount)2:

Dictionary&

lt;

string,object&

parameters=newDictionary&

();

parameters.Add("

id"

accountId);

amount"

amount);

InvokeInTransaction(()=&

DbAccessUtil.ExecuteNonQuery("

P_WITHDRAW"

parameters));

7:

}8:

staticvoidDeposit(stringaccountId,doubleamount)10:

{11:

12:

13:

P_DEPOSIT"

二、TransactionScope

在上面一节,我结合可提交事务和依赖事务,以及环境事务的机制提供了对事务型操作的实现。

实际上,如果借助TransactionScope,相应的代码将会变得非常简单。

下面的代码中,通过TransactionScope对InvokeInTransaction进行了改写,从执行效果来看这和原来的代码完全一致。

using(TransactionScopetransactionScope=newTransactionScope())4:

{5:

transactionScope.Complete();

通过InvokeInTransaction方法前后代码的对比,我们可以明显看到TransactionScope确实能够使我们的事务控制变得非常的简单。

实际上,在利用System.Transactions事务进行编程的时候,我们一般不会使用到可提交事务,对于依赖事务也只有在异步调用的时候会使用到,基于TransactionScope的事务编程方式才是我们推荐的。

正如其名称所表现的一样,TransactionScope就是为一组事务型操作创建一个执行范围,而这个范围始于TransactionScope创建之时,结束于TransactionScope被回收(调用Dispose方法)。

在对TransactionScope进行深入介绍之前,照例先来看看它的定义:

publicsealedclassTransactionScope:

IDisposable2:

publicTransactionScope();

publicTransactionScope(TransactiontransactionToUse);

publicTransactionScope(TransactionScopeOptionscopeOption);

publicTransactionScope(TransactiontransactionToUse,TimeSpanscopeTimeout);

publicTransactionScope(TransactionScopeOptionscopeOption,TimeSpanscopeTimeout);

publicTransactionScope(TransactionScopeOptionscopeOption,TransactionOptionstransactionOptions);

publicTransactionScope(TransactiontransactionToUse,TimeSpanscopeTimeout,EnterpriseServicesInteropOptioninteropOption);

publicTransactionScope(TransactionScopeOptionscopeOption,TransactionOptionstransactionOptions,EnterpriseServicesInteropOptioninteropOption);

publicvoidDispose();

我们可以看到TransactionScope实现了IDisposable接口,除了Dispose方法之外,仅仅具有一个唯一的方法:

但是TransactionScope却有一组丰富的构造函数。

我们先来看看这些构造函数相应的参数如何影响TransactionScope对事务控制的行为。

1、TransactionScopeOption

实际上前面一节中提供的InvokeInTransaction方法基本上体现了TransactionScope的内部实现。

也就是说,TransactionScope也是通过创建可提交事务或者依赖事务,并将其作为事务范围内的环境事务,从而将范围的所有操作纳入到一个事务之中。

通过在构造函数中指定TransactionScopeOption类型的scopeOption参数,控制TransactionScope当环境事务存在的时候应该采取怎样的方式执行事务范围内的操作。

具有来讲,具有三种不同的方式:

如果已经存在环境事务,则使用该环境事务。

否则,在进入范围之前创建新的事务;

总是为该范围创建新事务;

环境事务上下文在创建范围时被取消。

范围中的所有操作都在无环境事务上下文的情况下完成。

TransactionScopeOption是一个枚举,三个枚举值Required、RequiresNew和Suppress依次对应上面的三种行为。

publicenumTransactionScopeOption2:

Required,4:

RequiresNew,5:

Suppress6:

对于Required选项,如果当前存在环境事务TransactionScope会创建环境事务的依赖事务,负责创建可提交事务,然后将创建的环境事务或者可提交事务作为事务范围的环境事务。

如对于RequiresNew选项,TransactionScope总是会创建可提交事务并将其作为事务范围的环境事务,意味着控制事务范围内操作的事务也当前的环境事务已经没有任何关系。

如果Suppress选项,TransactionScope会将事务范围内的环境事务设为空,意味着事务范围内的操作并不受事务的控制。

Required是默认选项,意味着事务范围内的事务将会作为当前环境事务的一部分。

如果你不希望某个操作被纳入当前的环境事务,但是相应的操作也需要事务的控制以确保所操作数据的一致性。

比如,当业务逻辑失败导致异常抛出,需要对相应的错误信息进行日志记录。

对于日记的操作就可以放入基于RequiresNew选项创建TransactionScope中。

对于一些不重要的操作(操作的错误可被忽略),并且不需要通过事务来控制的操作,比如发送一些不太重要的通知,就可以采用Suppress选项。

2、TransactionOptions和EnterpriseServicesInteropOption

TransactionOptions在前面已经提及,用于控制事务的超时时限和隔离级别。

对于超时时限,你也可以选择TransactionScope相应能够的构造函数以TimeSpan的形式指定。

而对于事务的隔离级别,需要着重强调一点:

当选择TransactionScopeOption.Required选项时,TransactionScope指定的隔离级别必须与环境事务(如果有)相匹配。

比如下面的例子中,我定义两个嵌套的TransactionScope,外部的TransactionScope采用默认的隔离级别,内部在采用ReadCommitted隔离级别,当执行这段代码的时候,会抛出如图1所示的ArgumentException异常。

using(TransactionScopeouterScope=newTransactionScope())2:

TransactionOptionstransactionOptions=newTransactionOptions(){IsolationLevel=IsolationLevel.ReadCommitted};

using(TransactionScopeinnerScope=newTransactionScope(TransactionScopeOption.Required,transactionOptions))5:

{6:

//事务型操作7:

innerScope.Complete();

}9:

//事务型操作10:

outerScope.Complete();

}图1隔离级别不一致导致的异常

实际上在System.Transactions事务机制被引入之前,像EnterpriseService主要依赖于基于COM+的分布式事务。

TransactionScope通过EnterpriseServicesInteropOption控制System.Transactions事务如何与COM+的分布式事务进行互操作。

具有来讲具有如下三种互操作选项,分别和EnterpriseServicesInteropOption三个枚举值相对应:

None:

Transaction和Current之间不同步;

Automatic:

搜索现有的COM+上下文并与之同步(如该上下文存在);

Full:

System.EnterpriseServices上下文(可通过调用ContextUtil类的静态方法Transaction来检索)和System.Transactions环境事务(可通过调用Transaction类的静态方法Current来检索)始终保持同步。

这将引入性能损失,因为可能需要创建新的System.EnterpriseServices上下文。

publicenumEnterpriseServicesInteropOption2:

None,4:

Automatic,5:

Full6:

3、事务提交和回滚

对于事务范围中的事务,无论是事务的提交(对于可提交事务)、完成(依赖事务)和回滚都是在Dispose方法中执行的。

TransactionScope中定一个个私有的布尔类型字段(complete)表示事务是否正常结束。

该成员的默认值为False,当调用TransactionScope的Complete方法的时候会将此字段设置成True。

当Dispose执行的时候,如果该字段的值为False,会调用事务的Rollback方法对该事务实施回滚;

否则会调用Commit方法(对于可提交事务)对事务进行提交或者调用Complete方法(依赖事务)通知被依赖的事务本地事务已经正常完成。

除了执行事务的提交、完成或者回滚之外,TransactionScope的Dispose方法还负责将环境事务回复到事务范围开始之前的

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 历史学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2