masterEjb 2读书笔记——Transaction部分(2)

类别:Java 点击:0 评论:0 推荐:

Transaction Isolation(事务隔离)

n         Isolation是ACID原则中的I,意思就是将访问同一数据库的不同用户隔离开。你可以通过指定隔离级别来在性能和安全性之间获得平衡。共有四种隔离级别:

l         The read uncommitted:不做任何的隔离并且有最高的性能;

l         The Read Committed:能够解决读脏数据(dirty read)的问题;这种隔离级别是很多数据库缺省的隔离级,如:Oralce和Sql server。

l         The Repeatable Read:解决UnRepeatable read问题;这个问题的特征是:首先,用户A读出数据X;然后,用户B更改了数据X;用户A重新读数据X,结果数据和第一次不一致。

l         The Serializable:解决phantom(幻影)问题,这个问题的特征是:首先,用户A查询数据;然后,用户B添加了数据X;用户A再次查询数据,结果数据和第一次不一致。使用这个隔离级别的时候要非常小心,你可以做个试验:将你的所有操作都设置为这个级别,很快你会看到数据库会越来越慢知道挂起。而且Transaction方面的错误是非常难察觉的。

n         怎样在Ejb中指定隔离级别呢?在Bean-managed transaction中,使用Connection.setTransactionIsolation()方法指定;在容器管理的事务中,不能使用Deployment descriptor来指定,而要通过上述的API或者通过Deploy工具和数据库的工具来指定。为什么不能使用Deployment descriptor来指定呢?据sun公司的人说:“对于系统提供商来说,在组件级实现隔离是非常困难的。”

n         在同一个事物中如果有不同的数据库联接的话,可以指定不同的隔离级别。但是通常情况下为了程序的稳定性,都指定为同一种隔离级别。

 

分布式事务(Distributed Transaction)

n         两段提交(Two phase commit protocol OR 2PC):分布式事务实现的基本原理。

u       第一步:给整个事务中涉及到的所有资源管理器(Resource Manager)发送Before Commit信号,此时是资源管理器放弃提交的最后时机。如果有任何一个资源管理器放弃提交则整个事务会被取消。否则,事务会按部就班地执行直到错误发生为止。所有的更新操作都会记录到事务日志中,以防发生错误。

u       第二步:只在第一步的事务没有被取消之后才会被执行,在这一步,所有的数据库进行真正的数据更新操作。

n         在分布式事务中有很多事务管理器(Transaction Manager),其中一个被称之为协调员(Coordinator),用来在网络上协调其他的事务管理器,其步骤为:

u       协调员发送Prepared Commit信息给每一个事务管理器;

u       每个事务管理器将此消息转发给其对应的资源管理器(Resource Manager);

u       每个事务管理器将资源管理器返回的信息转发给协调员,如果每个事务管理器都同意commit,则协调员纪录日志以备不测;

u       最后,协调员通知每个事务管理器进行提交,事务管理器按顺序通知对应的资源管理器,他将数据持久地写入。如果发生错误,使用刚才协调员记录的日志进行错误恢复。

n         事务通信协议(Transaction Communication Protocol):在以分布式事务中涉及到的事务管理器很有可能使不同厂商的产品,为了相互之间能够通讯,要使用事务通信协议。IIOP就是这样的一种协议。

n         事务上下文(Transaction Context):在事务通信协议中最重要的信息就是事务上下文。他是一个对象,包含了系统当前的事务状态。查看这个上下文,你就可以得知:你是否在事务中,事务当前状态和其他有用信息。对于处于一个事务当中的组件的线程来说,它必须要有一个事务上下文。

n         J2EE规范建议但不是必须要求服务器厂商实现上述事务上下文交互机制,所以不同厂家的App服务器之间不能保证协同工作实现分布式两段提交。

 

设计EJB中的事务会话

n         App服务器帮我们做了很多事务控制方面的事情,但是这只是一半,在程序中还是要做一些处理。当事务被取消,你有多种选择,可以终止逻辑处理并且抛出异常给客户端;也可以多次重试事务,但是多次重试失败后总之要结束程序逻辑。对于无状态Session Bean来说事情很简单,只要将异常抛出给客户端即可;但是对于有状态Session Bean来说,在内存中还有与客户交流的状态值不能随意丢弃,这时App服务器就不能自动的替你保存这些状态值了,但是它会给你一个机会去让你自己保存这些值,只要你的Bean实现SessionSynchronization接口即可。在这个接口中你要实现的方法有:

u       afterBegin():事务开始之前被容器调用;这时事务刚刚开始,你可以从数据库中读出你想缓存的一些数据;

u       beforeCompletion():事务结束之前被容器调用;这时事务马上要结束,你可以将缓存的数据写入数据库;

u       afterCompletion(Boolean):事务结束之后被容器调用。对于回滚操作来说最重要的就是这个方法。容器会在事务结束之后调用这个方法而不管事务是被提交或是被取消。你可以通过这个方法传入的参数知道事务是否被提交。如果是false(即事务被取消)的话,你应该在此方法中处理会话状态值。注意:这里的提到的事务必须是容器控制的,而不能是程序控制的。

本文地址:http://com.8s8s.com/it/it16412.htm