Java 理论和实践: 理解 JTS ― 平衡安全性和性能
在他的关于 JTS 的系列文章的第 1 和第 2 部分,Brian 讲述了一些基础知识,包括什么
是事务以及 J2EE 容器如何使事务服务对 EJB 组件透明。尽管能够以声明的方式而不是编
程的方式指定组件的事务性语义可以大大增强配置企业应用程序时的灵活性,但在装配应
用程序时做出不当的决定会削弱应用程序的性能和稳定性。在这最后一部分,Brian 讨论
了 J2EE 提供的用来管理事务划分和隔离的工具和一些高效率地使用这些工具的指导。请
单击文章顶部或底部的 讨论,在讨论论坛与作者和其他读者分享您对本文的想法。
在本系列的第 1 部分(“ An introduction to transactions”)和第 2 部分(“ The
magic beind the scenes”)中,我们定义了什么是事务,列举了事务的基本特性
(property),并探讨了 Java 事务服务(Java Transaction Service)和 J2EE 容器如
何合作为事务提供对 J2EE 组件的透明支持。在本文中,我们将讨论事务的划分和隔离这
个主题。
为 EJB 组件定义事务划分和隔离属性(attribute)的职责由应用程序装配人员来承担。
如果这些属性设置不当,会对应用程序的性能、可伸缩性或容错能力造成严重的后果。不
幸的是,并没有一种必须遵守的规则用于正确设置这些属性,但有一些指导可以帮助我们
在并发危险和性能危险之间找到一种平衡。
我们在第 1 部分中讨论过,事务主要是一种异常处理机制。事务在程序中的用途与合法合
同在日常业务中的用途相似:如果出了什么问题它们可以帮助恢复。但由于大多数时间内
都没实际
发生
什么错误,我们就希望能够尽量减少它们的开销以及对其余时间的占用。我
们在应用程序中如何使用事务会对应用程序的性能和可伸缩性产生很大的影响。
事务划分
J2EE 容器提供了两种机制用来定义事务的起点和终点:bean 管理的事务和容器管理的事
务。在 bean 管理的事务中,用 UserTransaction.begin() 和
UserTransaction.commit() 在 bean 方法中显式开始和结束一个事务。另一方面,容器
管理的事务提供了更多的灵活性。通过在装配描述符中为每个 EJB 方法定义事务性属性,
您可以指定每个方法的事务性需求并让容器确定何时开始和结束一个事务。无论在哪种情
况下,构建事务的基本指导方针都是一样的。
进来,出去
事务划分的第一条规则是“尽量短小”。事务提供并发控制;这通常意味着资源管理器将代
表您获得您在事务期间访问的数据项的锁,并且它必须一直持有这些锁,直到事务结束。
(请回忆一下本系列第 1 部分所讨论的 ACID 特性,其中“ACID”的“I”代表“隔离”
(Isolation)。也就是说,一个事务的结果影响不到与该事务并发执行的其它事务。)当
您拥有锁时,任何需要访问您锁定的数据项的其它事务将不得不一直等待,直到您释放锁。
如果您的事务很长,那些其它的所有事务都将被锁定,您的应用程序吞吐量将大幅度下降。
规则 1:使事务尽可能短小。
通过使事务尽量短小,您可以把阻碍其它事务的时间缩到最短,从而提高应用程序的可伸
缩性。保持事务尽可能短小的最好方法当然是不在事务中间做任何不必要耗费时间的事,
特别是不要在事务中间等待用户输入。
开始一个事务,从数据库检索一些数据,显示数据,然后在仍处于事务中时请用户做出一
个选择可能比较诱人。千万别这么做!即使用户注意力集中,也要花费数秒来响应 ― 而
评论0
最新资源