本文共 5855 字,大约阅读时间需要 19 分钟。
Jonathan Sagorin 在 的最后一部分中对 Enterprise Java™Beans(EJB)事务进行了全面的揭示。探索 Apache Geronimo 应用服务器上与容器管理事务和 bean 管理事务都相关的难题和附加实现与配置选项。
在本系列的 和 中,您简单了解了 bean 管理的和容器管理的 EJB 事务以及如何在 Geronimo 应用服务器上实现它们。那么接下来呢?在使用 EJB 事务时,您应考虑哪些其他事务设置是可用的,以及需要考虑的其他事项?
本文首先概述第 1 和第 2 部分中的事务选择:容器管理或 bean 管理的事务。接着将了解并发控制策略和方法,确保事务执行时没有数据损失。您还将了解隔离级别(如何控制事务与其他事务的隔离)并了解如何设置事务超时。 最后,您将了解赞成和反对使用分布式事务的理由。
![]() ![]() |
![]()
|
在实现 EJB 事务时,有两种选择:容器管理或 bean 管理的事务。
使用容器管理的事务时,将在部署描述符中指定事务行为。EJB 容器负责控制事务边界。您为整个 enterprise bean、bean 上的个别方法或两者指定事务属性。事务属性的选择有:
使用 bean 管理的事务时,您编程控制事务边界并决定事务开始、提交和回滚的时机。在 bean 管理的事务中,可以在 Java Transaction API(JTA)或 Java Database Connectivity(JDBC)事务实现之间进行选择。JTA 使用 javax.transaction.UserTransaction 接口控制事务,而 JDBC 事务则直接经 java.sql.Connection 接口执行操作来控制事务行为。
如果使用会话或消息驱动 bean(MDB),那么可以实现 bean 管理或容器管理事务。然而,实体 bean 只可以使用容器管理事务。
按每个 enterprise bean 实现的事务类型总结了这些选择。
事务类型 | 会话 bean | 实体 bean | 消息驱动 bean |
---|---|---|---|
bean 管理 | x | x | |
事务管理 | x | x | x |
如果不确定您的 bean 使用哪种事务类型,Sun Microsystems 建议对 enterprise bean 使用具有 required 属性的容器管理的事务。
对于开发人员,使用容器管理的事务会比较简单并且需更比较少的工作量。在 bean 方法中不要求事务逻辑。在 enterprise bean 的方法级别上划分事务边界。bean 方法必须运行在事务上下文中或不在其中运行。
如果要求对事务边界进行更严格的控制,那么使用 bean 管理的事务。如果期望在 enterprise bean 中拥有长期过程,那么使用 bean 管理的事务。对于本文的目的,希望事务运行尽可能短的时间。如果使用容器管理事务,划分边界的粒度不够细,它们处于 bean 方法级别。
通过使用 bean 管理的事务,可以限制事务的持续时间为短暂的。可以在事务中隔离数据库操作并允许长期过程在事务作用域之外运行。这将确保不会阻塞访问同一数据的其他任何事务。
![]() ![]() |
![]()
|
使用 EJB 实现并发控制有两种策略:可以遵循消极(pessimistic)或积极(optimistic)锁定策略。
使用消极锁定 时,在修改数据所需的事务持续时间内获取锁,从而阻塞其他任何人修改同一数据。如果系统中有其他人可能试图修改正在处理的数据,那么这是使用该策略的好机会。该策略提供对数据的可靠访问,但是不适用于较小规模的系统,因为当要求系统规模和更多锁时,性能将会降低。
积极锁定 不会在事务期间持有锁。您采取积极的态度并假设在您使用数据时数据不会被其他事务修改。当发生数据冲突时,您可以处理异常情况,但假设这是很少发生的。当 要求更新数据时,实现策略来检查数据在最近被读取之后和在被修改之前这段时间里没有发生改变。如果数据没有改变,就执行更新。该策略适用于大规模系统。缺 点是您必须实现检测和处理数据冲突的代码。
下一节将讨论改变事务的隔离级别。这是消极锁定的一个例子,其中通过改变事务的隔离级别来控制消极锁定的程度和效力。
![]() ![]() |
![]()
|
事务的 ACID 属性之一是隔离性。隔离允许事务行为(无论是读还是写数据)独立或隔离于其他并发运行的事务。通过控制隔离,每个事务在其行动时间里都像是修改数据库的惟一事务。一个事务与其他事务隔离的程度称为隔离级别。
锁机制和同步用来控制隔离级别。随着隔离级别增加,需要更多的锁和同步。由于锁控制数据资源,其他尝试执行任何数据操作的事务必须等待,直到锁被释放。因此,增加隔离级别将以性能为代价。相反,随者隔离级别降低,因事务耗费较少的时间来等待锁被释放,将提高性能。
对事务设置隔离级别来处理下列数据一致性问题:
当从数据库读取未经提交的数据时,发生脏数据读。读取的数据没有与数据库里的真实数据同步。
考虑下面的场景,其中两个事务在读取和更新数据库的 String 字段 X。String X 的初始值是 foo:
这里的问题是一个事务可以改变值,而另一个事务可能在初始修改被提交前读取其值。数据是脏的,并不能表示数据的真实状态。
如果应用程序从数据库读取数据,然后又重读已经被修改的数据(可能以后在同一事务中),那么会发生不可重复读。考虑下面的场景,其中两个应用程序在读取和更新同一数据:
因此在读取之间,数据的值已改变并变得不一致。
影像读 与不可重复读类似。但是,影像读会将新数据插入到数据库中。应用程序从数据库中读取数据集,然后确定在其重读同一数据集时,附加的数据已经被添加。考虑下面的场景,其中两个应用程序在读取和更新数据库的同一数据:
同样,在读取之间数据变得不一致。
隔离的四个级别列在下面,按最低(最弱)隔离级别到最高(最强)级别的顺序排列。记住当提高隔离级别时,应用程序的性能将降低。
概述隔离级别选择并显示每个级别如何解决 列出的三个数据问题。
数据解决方案 | Read uncommitted | Read committed | Repeatable read | Serializable |
---|---|---|---|---|
解决脏数据读 | x | x | x | |
解决不可重复读 | x | x | ||
解决影像读 | x |
通过底层的数据库资源管理器指定隔离级别。使用 bean 管理的事务时,可以编程访问底层连接。由于可以访问 java.sql.Connection 接口,可以使用方法 setTransactionIsolation(int level) 改变连接的隔离级别。
使用下面这些常量来设置恰当的隔离级别:
其他让人感兴趣的方法是:
(参考 部分中的 Sun JavaDoc API 来获得有关这些方法的更多信息。)
注意:通过修改隔离级别,要求数据库资源管理器改变该资源的隔离性。这不是数据库供应商必须提供的必要特性。实际上,很多数据库供应商不会允许这么做。在改变隔离级别时一定要小心。查看您的数据库资源管理器文档来查明支持的隔离级别。
另外,应该在开始事务之前设置事务隔离级别。决不能在事务的过程中切换隔离级别。大多数资源管理器还要求对事务中的所有参与者使用同一隔离级别。
在使用容器事务时,没有办法在部署描述符中指定隔离级别。默认情况下,Geronimo 对 EJB 容器使用 Read Committed 隔离级别。如果需要对隔离级别更细的控制,那么考虑在 bean 管理的事务中使用 JDBC 事务。
![]() ![]() |
![]()
|
在 bean 管理的事务中使用 JTA 事务时,可以使用 javax.transaction.UserTransaction 接口的 setTransactionTimeout 方法。这将设置在事务中止之前将运行的最大时间(秒)。
![]() ![]() |
![]()
|
在单个事务中的多个参与者物理分布于网络中时,事务称为分布式事务。分布式事务允许不同类型的资源参与到事务中。分布式事务的例子是:
几个事务管理器必须共同工作来执行分布式事务。通常指定一个单独的事务管理器(称为事务协调器或分布式事务管理器)来协调其他事务管理器。
事务管理器进而与资源管理器进行协调来对资源(可能是数据库或消息服务器)执行必需的提交或回滚。大多数数据库的事务管理器和资源管理器紧密地耦合在一起。
通过使用某种协议进行通信来完成分布式事务,被称为两段式提交。从名字上看,您可能已经知道有两个阶段:
分布式事务的最大挑战是对事务管理器之间的共用通信协议取得一致。用于两段式提交的标准化协议称为 XA 协议,但是并非所有的供应商都支持该标准。XA 协议定义了事务管理器和资源管理器之间的接口。
Geronimo 的事务管理器是 Java Open Transaction Manager(JOTM),一个开放源码的事务管理器。它实现 XA 协议并编译成 JTA。记住,JTA 是本系列文章中用来与事务管理器进行通信的接口。可以在 bean 管理的事务中使用其来指定何时启动、提交或回滚事务。
只要所有的事务参与者都对通信协议取得一致,它们就可以参与同一分布式事务。
注意,使用分布式事务比使用本地事务要慢。所有事务参与者都需要更多的系统资源。事务协调器和所有事务参与者之间的网络交流都将影响系统响应时间。分布式事务由于涉及的事务管理器和资源管理器的数量,还将花费更多时间。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130292/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-130292/