权衡 Apache Geronimo EJB 事务选项,第 3 部分: 综合所有事务

Jonathan Sagorin 在 由三部分组成的系列文章 的最后一部分中对 Enterprise Java™Beans(EJB)事务进行了全面的揭示。探索 Apache Geronimo 应用服务器上与容器管理事务和 bean 管理事务都相关的难题和附加实现与配置选项。

简介

在本系列的 第 1 部分 和 第 2 部分 中,您简单了解了 bean 管理的和容器管理的 EJB 事务以及如何在 Geronimo 应用服务器上实现它们。那么接下来呢?在使用 EJB 事务时,您应考虑哪些其他事务设置是可用的,以及需要考虑的其他事项?

本文首先概述第 1 和第 2 部分中的事务选择:容器管理或 bean 管理的事务。接着将了解并发控制策略和方法,确保事务执行时没有数据损失。您还将了解隔离级别(如何控制事务与其他事务的隔离)并了解如何设置事务超时。 最后,您将了解赞成和反对使用分布式事务的理由。


回页首

EJB 事务:我的选择是什么?

在实现 EJB 事务时,有两种选择:容器管理或 bean 管理的事务。

使用容器管理的事务时,将在部署描述符中指定事务行为。EJB 容器负责控制事务边界。您为整个 enterprise bean、bean 上的个别方法或两者指定事务属性。事务属性的选择有:

  • Required
  • RequiresNew
  • Supports
  • Mandatory
  • NotSupported
  • Never

使用 bean 管理的事务时,您编程控制事务边界并决定事务开始、提交和回滚的时机。在 bean 管理的事务中,可以在 Java Transaction API(JTA)或 Java Database Connectivity(JDBC)事务实现之间进行选择。JTA 使用 javax.transaction.UserTransaction 接口控制事务,而 JDBC 事务则直接经 java.sql.Connection 接口执行操作来控制事务行为。

如果使用会话或消息驱动 bean(MDB),那么可以实现 bean 管理或容器管理事务。然而,实体 bean 只可以使用容器管理事务。

表 1 按每个 enterprise bean 实现的事务类型总结了这些选择。

表 1. enteprise 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 属性之一是隔离性。隔离允许事务行为(无论是读还是写数据)独立或隔离于其他并发运行的事务。通过控制隔离,每个事务在其行动时间里都像是修改数据库的惟一事务。一个事务与其他事务隔离的程度称为隔离级别

锁机制和同步用来控制隔离级别。随着隔离级别增加,需要更多的锁和同步。由于锁控制数据资源,其他尝试执行任何数据操作的事务必须等待,直到锁被释放。因此,增加隔离级别将以性能为代价。相反,随者隔离级别降低,因事务耗费较少的时间来等待锁被释放,将提高性能。

数据一致性

对事务设置隔离级别来处理下列数据一致性问题:

  • 脏数据读(Dirty read)
  • 不可重复读(Unrepeatable read)
  • 影像读(Phantom read)

脏数据读

当从数据库读取未经提交的数据时,发生脏数据读。读取的数据没有与数据库里的真实数据同步。

考虑下面的场景,其中两个事务在读取和更新数据库的 String 字段 X。String X 的初始值是 foo:

  1. 事务 1 读取 String X 的值 foo。
  2. 事务 1 将 String X 的当前值与 bar 连接并将其保存到数据库中。
  3. X 的新值是 foobar。事务 1 还没有发出提交语句。
  4. 事务 2 读取 String X 的值,即 foobar。
  5. 事务 1 中止。
  6. 事务 2 将 String X 与 bar 连接并将其保存至数据库。
  7. X 的新值是 foobarbar,这时其正确的值应该是 foobar。
  8. 事务 2 对 String X 的值执行了脏数据读。

这里的问题是一个事务可以改变值,而另一个事务可能在初始修改被提交前读取其值。数据是脏的,并不能表示数据的真实状态。

不可重复读

如果应用程序从数据库读取数据,然后又重读已经被修改的数据(可能以后在同一事务中),那么会发生不可重复读。考虑下面的场景,其中两个应用程序在读取和更新同一数据:

  1. 应用程序 1 读取 String X 的值 foo。
  2. 应用程序 2 更新 String X 的值为 foobar。
  3. 应用程序 1 重读 String 的值并发现其已改为 foobar。

因此在读取之间,数据的值已改变并变得不一致。

影像读

影像读 与不可重复读类似。但是,影像读会将新数据插入到数据库中。应用程序从数据库中读取数据集,然后确定在其重读同一数据集时,附加的数据已经被添加。考虑下面的场景,其中两个应用程序在读取和更新数据库的同一数据:

  1. 应用程序 1 搜索符合某个条件的数据并返回五行的数据集。
  2. 应用程序 2 将五个满足应用程序 1 的搜索条件的附加行添加到数据库。
  3. 在应用程序 1 基于其初始条件重读数据库(且期望得到五行)时,将返回 10 行。

同样,在读取之间数据变得不一致。

选择隔离级别

隔离的四个级别列在下面,按最低(最弱)隔离级别到最高(最强)级别的顺序排列。记住当提高隔离级别时,应用程序的性能将降低。

  • Read uncommitted - 该选项仅适用于具有非共享数据的非任务关键型系统(这在应用程序中是很少见的情况)。性能处于最佳状态,但是将牺牲并发控制。如果确定没有其他并发事务,请使用该选项。使用该选项,以上所列的数据问题都无法解决。
  • Read committed - 这是大多数数据库的默认隔离级别,也是 Apache Geronimo 默认的。只能读取提交的数据,因此该选项解决了脏数据读问题。由于要求对数据库使用附加锁,因此性能将会慢一些。
  • Repeatable read - 通过使用该隔离级别,解决脏数据读和未提交读问题。可以保证读取的任何行可以在以后被重读而其值将不会改变。
  • Serializable - 这是最严格的隔离级别,解决了所有三个数据问题。在希望事务以真正隔离的方式运行并完全与其他事务独立时,请使用该级别。这将保证数据一致性。对任务关键型系统使用它来保证真正地隔离事务行为。但是注意,该隔离级别是以性能为代价。

表 2 概述隔离级别选择并显示每个级别如何解决 早先 列出的三个数据问题。

表 2. 使用隔离级别解决数据问题

数据解决方案 Read uncommitted Read committed Repeatable read Serializable
解决脏数据读 x x x
解决不可重复读 x x
解决影像读 x

在 bean 管理的事务中的隔离级别

通过底层的数据库资源管理器指定隔离级别。使用 bean 管理的事务时,可以编程访问底层连接。由于可以访问 java.sql.Connection 接口,可以使用方法 setTransactionIsolation(int level) 改变连接的隔离级别。

使用下面这些常量来设置恰当的隔离级别:

  • Connection.TRANSACTION_READ_UNCOMMITTED
  • Connection.TRANSACTION_READ_COMMITTED
  • Connection.TRANSACTION_REPEATABLE_READ
  • Connection.TRANSACTION_SERIALIZABLE

其他让人感兴趣的方法是:

  • Connection.getTransactionIsolation()
  • DatabaseMetaData.supportsTransactionIsolationLevel(int)

(参考 参考资料 部分中的 Sun JavaDoc API 来获得有关这些方法的更多信息。)

注意:通过修改隔离级别,要求数据库资源管理器改变该资源的隔离性。这不是数据库供应商必须提供的必要特性。实际上,很多数据库供应商不会允许这么做。在改变隔离级别时一定要小心。查看您的数据库资源管理器文档来查明支持的隔离级别。

另外,应该在开始事务之前设置事务隔离级别。决不能在事务的过程中切换隔离级别。大多数资源管理器还要求对事务中的所有参与者使用同一隔离级别。

在容器管理的事务中的隔离级别

在使用容器事务时,没有办法在部署描述符中指定隔离级别。默认情况下,Geronimo 对 EJB 容器使用 Read Committed 隔离级别。如果需要对隔离级别更细的控制,那么考虑在 bean 管理的事务中使用 JDBC 事务。


回页首

事务超时

在 bean 管理的事务中使用 JTA 事务时,可以使用 javax.transaction.UserTransaction 接口的 setTransactionTimeout 方法。这将设置在事务中止之前将运行的最大时间(秒)。


回页首

分布式事务

在单个事务中的多个参与者物理分布于网络中时,事务称为分布式事务。分布式事务允许不同类型的资源参与到事务中。分布式事务的例子是:

  • 单个会话 bean 开始事务并更新数据库 A。调用运行在同一个应用服务器上的另一个会话 bean 来更新数据库 B。第一个会话 bean 提交事务。两个数据库更新发生在同一个事务中。
  • 单个会话 bean 开始事务并更新数据库 A。调用运行在不同的 应用服务器上的另一个会话 bean 来更新数据库 B。每个应用服务器的事务管理器将确保两个数据库在同一事务中更新。
  • 单个会话 bean 开始事务并更新数据库 A,接着是 Java Message Service(JMS)操作。两个工作单元都是同一事务的一部分。如果 JMS 操作失败,事务将不会更新数据库。

几个事务管理器必须共同工作来执行分布式事务。通常指定一个单独的事务管理器(称为事务协调器分布式事务管理器)来协调其他事务管理器。

事务管理器进而与资源管理器进行协调来对资源(可能是数据库或消息服务器)执行必需的提交或回滚。大多数数据库的事务管理器和资源管理器紧密地耦合在一起。

两段式提交

通过使用某种协议进行通信来完成分布式事务,被称为两段式提交。从名字上看,您可能已经知道有两个阶段:

  • 第一个阶段,即预提交

    • 事务协调器给每个事务管理器发送准备操作的信号。
    • 事务管理器将操作(通常是数据更新)步骤(或细节)写入事务日志。如果失败,事务管理器使用这些步骤重复操作。
    • 事务管理器本地创建事务并通知资源管理器对资源(例如,数据库或消息服务器)执行操作。
    • 资源管理器执行操作并向事务管理器报告成功(准备提交信号)或失败(准备回滚)。
    • 资源管理器等待事务管理器进一步的指令。
    • 事务管理器向事务协调器报告成功或失败。
  • 第二阶段,即提交阶段:在第二阶段中,第一阶段的结果将传送给所有事务管理器。如果任何事务管理器报告失败,所有的事务参与者都必须回滚。
    • 事务协调器让所有事务管理器提交(或回滚)。
    • 所有事务管理器将提交或回滚信息传递给其资源管理器。
    • 资源管理器将成功或失败提示返回给事务管理器。
    • 事务管理器向事务协调器报告成功或失败。

我们可以交谈吗?

分布式事务的最大挑战是对事务管理器之间的共用通信协议取得一致。用于两段式提交的标准化协议称为 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/

[转载]权衡 Apache Geronimo EJB 事务选项,第 3 部分: 综合所有事务相关推荐

  1. [转载]使用 XMLBeans 在 Apache Geronimo 中部署 SOA 应用程序

    使用 XMLBeans 在 Apache Geronimo 中部署 SOA 应用程序 对 XMLBeans 好奇吗?这种高级易用的 XML-Java 绑定技术允许您像访问任何 Java™ 对象或 Ja ...

  2. Apache Geronimo Remote Code Execute Vulnerability

    简介: Apache Geronimo 是 Apache 软件基金会的开放源码J2EE服务器,它集成了众多先进技术和设计理念. 这些技术和理念大多源自独立的项目,配置和部署模型也各不相同. Geron ...

  3. [转载]用消息队列和消息应用状态表来消除分布式事务

    由于数据量的巨大,大部分Web应用都需要部署很多个数据库实例.这样,有些用户操作就可能需要去修改多个数据库实例中的数据.传统的解决方法是使用分布式事务保证数据的全局一致性,经典的方法是使用两阶段提交协 ...

  4. java.lang.NoClassDefFoundError: org/apache/geronimo/mail/util/Base64Encod——解决方案

    最近在弄通过javaMail发送信息到邮箱,老是会报这样的错误:Exception in thread "main" java.lang.NoClassDefFoundError: ...

  5. Apache Geronimo 介绍

    Apache Geronimo 介绍 1. Apache Geronimo 是 Apache 软件基金会的开放源码J2EE服务器,它集成了众多先进技术和设计理念.

  6. Apache Geronimo 2.2发布

    Apache Geronimo 是一个由 Apache Software Foundation 开发的开源 J2EE 应用服务器项目,其发行许可证是 Apache License, Version 2 ...

  7. WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程

    今天我们继续学习WCF分布式开发步步为赢系列的12节:WCF事务机制(Transaction)和分布式事务编程.众所周知,应用系统开发过程中,事务是一个重要的概念.它是保证数据与服务可靠性的重要机制. ...

  8. oracle 开始一个事务,oracle的启动与关闭原理-事务commit或者rollback

    oracle的启动与关闭原理-事务commit或者rollback 4.事务 4.1事务的概念 从第一个DML语句开始执行,以rollback或者commit为结束标记,之前所有的DML操作(inse ...

  9. 阐述一下Mysql事务的四个特性_数据库事务的四个基本性质?

    本文转载:http://www.sqlstudy.com/sql_article.php?id=2008080302 数据库事务概念 什么是数据库事务? 事务(transaction)是由一系列操作序 ...

最新文章

  1. java interface class_Java中常量定义在interface和class的区别(转)
  2. linux卸载数据库后还在吗,oracle停止数据库后linux完全卸载oracle的详细步骤
  3. Counting power sets
  4. php读取部分文章显示不出来了,织梦使用PHP5.3环境时遇到部分文章出现”读取附加信息出错“的解决办法jz1...
  5. MySQL数据库阶段学习目录
  6. 使用Free Spire.Presentation生成PowerPoint文件
  7. 微信小程序中rpx与rem单位使用
  8. vs2003不能调试4/8
  9. 方正电脑如何关闭网络启动计算机,方正电脑怎么进安全模式
  10. 指示灯亮着,但是右边的数字小键盘不可用
  11. html从谷歌浏览器跳转到IE,谷歌浏览器chrome
  12. python如何进行数据挖掘_如何使用python实现文本数据挖掘?
  13. python模拟太阳系_模拟太阳系8大行星运行图:matplotlib实现
  14. 有哪些资本运作的经典案例?
  15. cocoa和cocoa Touch的区别
  16. flyaway mysql_mysql 常用命令
  17. 求大佬指教一下,小白不懂为什么子网IP和子网掩码相对应但却不匹配呢
  18. GMS认证环境搭建-终极篇
  19. 洛谷—— AT_pakencamp_2021_day2_a Participants 2
  20. php显示cpu温度,cpu温度过高怎么办

热门文章

  1. 人最重要的是选择--近一年来申博、读博及参加工作有感!
  2. 数电/数字电子技术期末考前突击复习(小白稳过,看这一篇就够了)
  3. 学习python,需要多少学费,Python前景怎么样?
  4. Java对接某地联通API接口01---选号服务
  5. 84.网络安全渗透测试—[SQL注入篇23]—[高级注入技巧-dnslog无回显注入]
  6. 【达内课程】ContentProvider
  7. 民安智库开展珠海连锁快餐门店暗访调查
  8. ios:Layer 异步绘制
  9. 【对讲机的那点事】了解这四点,就知道如何合法合理的使用对讲机
  10. 如何做学生喜欢的老师