`

事务划分规则

阅读更多

进来,出去

事务划分的第一条规则是“尽量短小”。事务提供并发控制;这通常意味着资源管理器将代表您获得您在事务期间访问的数据项的锁,并且它必须一直持有这些锁,直到事务结束。(请回忆一下本系列第 1 部分所讨论的 ACID 特 性,其中“ACID”的“I”代表“隔离”(Isolation)。也就是说,一个事务的结果影响不到与该事务并发执行的其它事务。)当您拥有锁时,任何 需要访问您锁定的数据项的其它事务将不得不一直等待,直到您释放锁。如果您的事务很长,那些其它的所有事务都将被锁定,您的应用程序吞吐量将大幅度下降。

 

规则 1:使事务尽可能短小。

 

通过使事务尽量短小,您可以把阻碍其它事务的时间缩到最短,从而提高应用程序的可伸缩性。保持事务尽可能短小的最好方法当然是不在事务中间做任何不必要耗费时间的事,特别是不要在事务中间等待用户输入。

开 始一个事务,从数据库检索一些数据,显示数据,然后在仍处于事务中时请用户做出一个选择可能比较诱人。千万别这么做!即使用户注意力集中,也要花费数秒来 响应 ― 而在数据库中拥有锁数秒的时间已经是很长的了。如果用户决定离开计算机,或许是去吃午餐或者甚至回家一天,会发生什么情况?应用程序将只好无奈停机。在事 务期间执行 I/O 是导致灾难的秘诀。

 

规则 2:在事务期间不要等待用户输入。

 

将相关的操作归在一起

由于每个事务都有不小的开销,您可能认为最好是在单个事务中执行尽可能多的操作以使每个操作的开销达到最小。但规则 1 告诉我们长事务对可伸缩性不利。那么如何实现最小化每个操作的开销和可伸缩性之间的平衡呢?

我 们把规则 1 设置为逻辑上的极端 ― 每个事务一个操作 ― 这样不仅会导致额外开销,还会危及应用程序状态的一致性。假定事务性资源管理器维护应用程序状态的一致性(请回忆一下第 1 部分,其中“ACID”的“C”代表“一致性”(Consistency)),但它们依赖应用程序来定义一致性的意思。实际上,我们在描述事务时使用的一 致性的定义有点圆滑:应用程序说一致性是什么意思它就是什么意思。应用程序把几组应用程序状态的变化组织到几个事务中,结果应用程序的状态就成了 定义上的(by definition) 一致。然后资源管理器确保如果它必须从故障恢复的话,就把应用程序状态恢复到最近的一致状态。

在第 1 部分中,我们给出了一个在银行应用程序中将资金从一个帐户转移到另一个帐户的示例。清单 1 展示了这个示例可能的 SQL 实现,它包含 5 个 SQL 操作(一个选择,两个更新和两个插入操作):


清单 1. 资金转移的样本 SQL 代码

SELECT accountBalance INTO aBalance 
    FROM Accounts WHERE accountId=aId;
IF (aBalance >= transferAmount) THEN 
    UPDATE Accounts 
        SET accountBalance = accountBalance - transferAmount
        WHERE accountId = aId;
    UPDATE Accounts 
        SET accountBalance = accountBalance + transferAmount
        WHERE accountId = bId;
    INSERT INTO AccountJournal (accountId, amount)
        VALUES (aId, -transferAmount);
    INSERT INTO AccountJournal (accountId, amount)
        VALUES (bId, transferAmount);
ELSE
    FAIL "Insufficient funds in account";
END IF


如果我们把这个操作作为五个单独的事务来执行会发生 什么情况?这样不仅会使执行速度变慢(由于事务开销),还会失去一致性。例如,如果一个人从帐户 A 取了钱,作为执行第一次 SELECT(检查余额)和随后的记入借方 UPDATE 之间的一个单独事务的一部分,会发生什么情况?这样会违反我们认为这段代码会强制遵守的业务规则 ― 帐户余额应该是非负的。如果在第一次 UPDATE 和第二次 UPDATE 之间系统失败会发生什么情况?现在,当系统恢复时,钱已经离开了帐户 A 但还没有记入帐户 B 的贷方,并且也无记录说明原因。这样,哪个帐户的所有者都不会开心。

清单 1 中的五个 SQL 操作是单个相关操作 ― 将资金从一个帐户转移到另一个帐户 ― 的一部分。因此,我们希望要么全部执行它们,要么一个也不执行,建议在单个事务中全部执行它们。

 

规则 3:将相关操作归到单个事务中。

 

理想化的平衡

规则 1 说事务应尽可能短小。清单 1 中的示例表明有时候我们必须把一些操作归到一个事务中来维护一致性。当然,它要依赖应用程序来确定“相关操作”是由什么组成的。我们可以把规则 1 和 3 结合在一起,提供一个描述事务范围的一般指导,我们规定它为规则 4:

 

规则 4:把相关操作归到单个事务中,但把不相关的操作放到单独的事务中。






容器管理的事务

 

在使用容器管理的事务时,不是显式声明事务的起点和终点,而是为每个 EJB 方法定义事务性需求。bean 的 assembly-descriptorcontainer-transaction 部分的 trans-attribute 元素中定义了事务模式。(清单 2 中显示了一个 assembly-descriptor 示例。)方法的事务模式以及状态 ― 调用方法是否早已在事务中被征用 ― 决定了当 EJB 方法被调用时容器应该进行下面几个操作中的哪一个:

  • 征用现有事务中的方法。
  • 创建一个新事务,并征用该事务中的方法。
  • 不征用任何事务中的方法。
  • 抛出一个异常。


清单 2. 样本 EJB 装配描述符

<assembly-descriptor>
  ...
  <container-transaction>
    <method>
      <ejb-name>MyBean</ejb-name>
      <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
  </container-transaction>
  <container-transaction>
    <method>
      <ejb-name>MyBean</ejb-name>
      <method-name>logError</method-name>
    </method>
    <trans-attribute>RequiresNew</trans-attribute>
  </container-transaction>
  ...
</assembly-descriptor>


J2EE 规范定义了六种事务模式: RequiredRequiresNewMandatorySupportsNotSupportedNever 。表 1 概述了每种模式的行为 ― 在现有事务中被调用和不在事务内调用时的行为 ― 并描述了每种模式受哪些类型的 EJB 组件支持。(一些容器可能允许您在选择事务模式时有更多的灵活性,但这种使用要依赖特定于容器的功能,因此不适合跨容器的情况)。

 

表 1. 事务模式

 

事务模式 Bean 类型 在事务 T 内被调用时的行为 在事务外被调用时的行为
Required 会话、实体、消息驱动 在 T 中征用 新建事务
RequiresNew 会话、实体 新建事务 新建事务
Supports 会话、消息驱动 在 T 中征用 不带事务运行
Mandatory 会话、实体 在 T 中征用 出错
NotSupported 会话、消息驱动 不带事务运行 不带事务运行
Never 会话、消息驱动 出错 不带事务运行

 

在只使用容器管理的事务的应用程序中,只有组件调用事务模式为 RequiredRequiresNew 的 EJB 方法时才启动事务。如果容器创建一个事务作为调用事务性方法的结果,当该方法完成时将关闭该事务。如果方法正常返回,容器将提交事务(除非应用程序已经要 求回滚事务)。如果方法通过抛出一个异常退出,容器将回滚事务并传播该异常。如果在现有事务 T 中调用了一个方法,并且事务模式指定应该不带事务运行该方法或者在新事务中运行该方法,那么事务 T 将被暂挂,一直到方法完成,然后先前的事务 T 被恢复。

选择一种事务模式

 

那么我们应该为自己的 bean 方法选择哪种模式呢?对于会话 bean 和消息驱动 bean,您通常想使用 Required 来确保每个调用都被作为事务的一部分执行,但仍将允许方法作为一个更大的事务的组件。请小心使用 RequiresNew ;只有在确定自己的方法的行为应该与调用您的方法的行为分开提交时,才应该使用这种模式。 RequiresNew 一般情况下只和与系统中其它对象关系很少或没什么关系的对象(比如日志对象)一起使用。(把 RequiresNew 与日志对象一起使用比较有意义,因为您可能希望在不管外围事务是否提交的情况下提交日志消息。)

 

RequiresNew 使用不当会导致与上面的描述相似的情况,其中,清单 1 中的代码在五个分开的事务而不是一个事务中执行,这样会使应用程序处于不一致状态。

 

对于 CMP(容器管理的持久性,container-managed persistence)实体 bean,通常是希望使用 RequiredMandatory 也是一个合理的选项,特别是在最初开发时;这将会警告您实体 bean 方法在事务外被调用这种情况,这时可能会指出一个部署错误。您几乎从不希望把 RequiresNew 和 CMP 实体 bean 一起使用。 NotSupportedNever 旨在用于非事务性资源,比如 Java 事务 API(Java Transaction API,JTA)事务中无法征用的外部非事务性系统或事务性系统的适配器。

 

如 果 EJB 应用程序设计得当,应用上面的事务模式指导往往会自然地产生规则 4 建议的事务划分。原因是 J2EE 体系架构鼓励把应用程序分解为最小的方便处理的块,并且每个块都作为一个单独的请求被处理( 不管是以 HTTP 请求的形式还是作为在 JMS 队列中排队的消息的结果)。






重温隔离

 

在第 1 部分中,我们定义了 隔离(isolation) 的 意思是:一个事务的影响对与该事务并发执行的其它事务是不可见的;从事务的角度来看,好象事务是连续执行而非并行执行。尽管事务性资源管理器经常可以同时 处理许多事务并提供隔离的假象,但有时隔离限制实际上要求把新事务延迟到现有事务完成后才开始。由于完成一个事务至少包括一个同步磁盘 I/O(写到事务日志),这就会把每秒的事务数限制到接近每秒的写磁盘次数,这对可伸缩性不利。

 

实际上,通常是充分放松隔离需求以允许更多的事务并发执行并使系统响应能够得到改善,使可伸缩性变得更 强。几乎所有的数据库都支持标准隔离级别:读未提交的(Read Uncommitted)、读已提交的(Read Committed)、可重复的读(Repeatable Read) 和可串行化的(Serializable)。

 

不幸 的是,为容器管理的事务管理隔离目前是在 J2EE 规范的范围之外。但是,许多 J2EE 容器,比如 IBM WebSphere 和 BEA WebLogic,将提供特定于容器的扩展,这些扩展允许您以每方法(per-method)为基础设置事务隔离级别,设置方法与在装配描述符中设置事务 模式的方法相同。对于 bean 管理的事务,您可以通过 JDBC 或者其它资源管理器连接设置隔离级别。

 

为阐明隔离级别之间的差异,我们首先把几个并发危险分类 ― 这几种危险是当没有适当地隔离时一个事务可能会干涉另一个事务的情况。下列的所有这些危险都与这种情况( 第二个事务已经启动后第一个事务变得对第二个事务 可见 )的结果有关:

  • 脏读(Dirty Read) :当一个事务的中间(未提交的)结果对另一个事务可见时就会发生这种情况。
  • 不可重复的读(Unrepeatable Read) :当一个事务读取一个数据项,然后重新读取这个数据项并看到不同的值时就是发生了这种情况。
  • 虚读(Phantom Read) :当一个事务执行返回多个行的查询,稍后再次执行同一个查询并看到第一次执行该查询没出现的额外行时就是发生了这种情况。

四个标准隔离级别与这三个隔离危险相关,如表 2 所示。最低的隔离级别“读未提交的”并不能保护事务不被其它事务更改,但它的速度最快,因为它不需要争夺读锁。最高的隔离级别“可串行化的”与上面给出的隔离的定义相当;每个事务好象都与其它事务的影响完全隔离。

 

表 2. 事务隔离级别

 

隔离级别 脏读 不可重复的读 虚读
读未提交的
读已提交的
可重复的读
可串行化的

 

对 于大多数数据库,缺省的隔离级别为“读已提交的”,这是个很好的缺省选择,因为它阻止事务在事务中的任何给定的点看到应用程序数据的不一致视图。“读已提 交的”是一个很不错的隔离级别,用于大多数典型的短事务,比如获取报表数据或获取要显示给用户的数据的时候(多半是作为 Web 请求的结果),也用于将新数据插入到数据库的情况。

 

当您需要所有事务间有较高级别的一致性时,使用较高的隔离级别“可重复 的读”和“可串行化的”比较合适,比如在清单 1 示例中,您希望从检查余额以确保有足够的资金到您实际取钱期间账户余额一直保持不变;这就要求至少要用“可重复的读”隔离级别。在数据一致性绝对重要的情 况下,比如审核记帐数据库以确保一个帐户的所有借方金额和贷方金额的总数等于它目前的余额时,可能还需要防止创建新行。这种情况下就需要使用“可串行化 的”隔离级别。

 

最低的隔离级别“读未提交的”很少使用。它适用于您只需要获得近似值,否则查询将导致您不希望的性能开销这种情况。当您想要估计一个变化很快的数量,如定单数或者今天所下定单的总金额(以美元为单位)时一般使用““读未提交的”。

 

因 为隔离和可伸缩性之间实际是一种此消彼长的关系,所以您在为事务选择隔离级别时应该小心行事。选择太低的级别对数据比较危险。选择太高的级别可能对性能不 利,尽管负载比较轻时可能不会这样。一般来说,数据一致性问题比性能问题更严重。如果拿不准,应该以小心为主,选择一个较高的隔离级别。这就引出了规则 5:

 

规则 5:使用保证数据安全的最低隔离级别,但如果拿不准,请使用“可串行化的”。

 

即 使您打算刚开始时以小心为主并希望结果性能可以接受 ―(被称为“拒绝和祈祷(denial and prayer)”的性能管理技术 ― 很可能是最常用的性能策略,尽管大多数开发者都不承认这一点),在开发组件时考虑隔离需求也是有利的。您应该努力编写能够容忍级别较低但实用的隔离级别的 事务,这样,当稍后性能成为问题时,自己就不会陷入困境。因为您需要知道方法正在做什么以及这个方法中隐藏了什么一致性假设来正确设置隔离级别,那么在开 发期间仔细说明并发需求和假设,以便在装配应用程序时帮助作出正确的决定也不失为一个好主意。

 

 

转自http://www.ibm.com/developerworks/cn/java/j-jtp0514/

 

分享到:
评论

相关推荐

    超市事务数据库挖掘关联规则的设计

    ### 超市事务数据库挖掘...综上所述,《超市事务数据库挖掘关联规则的设计》不仅深入探讨了关联规则挖掘技术的基本原理与实现方法,还提出了一种更为高效的基于划分的数据挖掘算法,为零售业提供了有力的数据支持工具。

    超市事务数据库挖掘关联规则的设计.doc

    【超市事务数据库挖掘关联规则的设计】文档探讨了在信息爆炸时代如何运用数据挖掘技术,特别是关联规则,来分析超市事务数据库。关联规则是数据挖掘领域的重要研究内容,它旨在发现不同商品之间的关联关系,帮助商家...

    本文通过对Apriori算法分析,应用散列、事务压缩、划分、抽样等方法,最大可能的减少数据库扫描的次数,快速发现频繁项集,提高Apriori算法的效率。

    本文旨在探讨如何通过散列、事务压缩、划分和抽样等方法来提高Apriori算法的效率。 #### 二、Apriori算法概述 Apriori算法由Rakesh Agrawal等人于1993年首次提出,它基于频繁项集的先验性质,采用逐层搜索的方式...

    超市事务数据库挖掘关联规则的设计(1).doc

    在当今信息爆炸的时代,数据挖掘技术成为处理大量数据的关键手段,尤其在超市事务数据库中,通过对关联规则的挖掘,商家能够洞察消费者的购物行为,优化商品布局,提高销售额。关联规则挖掘起源于1993年IBM Almaden ...

    浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架 .docx

    事务日志的物理结构主要由虚拟日志文件(Virtual Log Files, VLFs)组成,这些文件是日志文件的逻辑划分,有助于更有效地管理和利用存储空间。在创建数据库时,SQL Server会根据日志文件的大小自动确定VLF的数量和...

    spring框架的学习--事务

    了解了Spring事务的基本概念后,我们可以看到压缩包中的文件名如SpringStudy_tx3、SpringStudy_tx4等,这些很可能是按照章节进行划分的源码示例,涵盖了不同阶段的事务管理学习。通过学习这些源码,你可以更直观地...

    提高Apriori算法的效率之一事物压缩划分

    通过事物压缩划分,我们可以将多个小事务合并为一个大事务,以此减少事务数量,进而降低内存需求和I/O操作。 具体来说,该方法首先对事务进行分组,使得每个组内的事务具有较高的项集重叠度。然后,使用压缩编码...

    PCIE规范第二章_事务层规范

    总的来说,PCIe规范的事务层规范详细定义了数据传输的各个方面,包括但不限于事务类型、包结构、协议规则和错误处理机制,这些是PCIe总线高效、可靠运行的基础。理解和掌握这些知识对于设计、开发和优化PCIe系统至关...

    关联规则挖掘理论和算法PPT课件.pptx

    * 关联规则挖掘问题可以划分成两个子问题:1. 发现频繁项目集;2. 生成关联规则。 四、项目集格空间理论 * Agrawal等人建立了用于事务数据库挖掘的项目集格空间理论(1993, Apriori属性)。 * 该理论的核心原理是...

    事务处理技术PPT学习教案.pptx

    而隐式事务则是由数据库管理系统自动进行,当用户没有明确定义事务时,DBMS会按照默认规则划分事务。 COMMIT和ROLLBACK是事务处理中的关键命令。COMMIT表示事务正常结束,所有在事务中的操作(包括读取和更新)都将...

    分布式工程数据库系统中事务管理机制相关技术的研究

    扩充分层封锁模型是在2PL基础上的创新,它将数据库对象按照一定规则划分为不同的层次,每一层的封锁策略和解锁时机有所不同。这种机制能够在保证事务一致性的同时,最大化并发操作的机会,尤其适用于处理大型分布式...

    一种高效的多层和概化关联规则挖掘方法

    这种方法通过构建项相关性模型(D.ICM,Domain Knowledge-based Item Correlation Model),结合领域知识对分类数据进行层次聚类,从而对事务数据库进行有效约简和划分。随后,通过将这些约简后的数据库映射到一种...

    律师事务所保密制度守则.pdf

    《律师事务所保密制度守则》是法律服务机构内部管理的核心规则之一,旨在保护律师事务所的商业秘密和其他敏感信息,确保业务的正常运作和客户权益的安全。本文将深入解析该守则的关键内容。 首先,保密制度强调了...

    Java理论与实践:理解JTS―平衡安全性和性能

    事务划分的原则是“尽量短小”,这是因为事务期间锁定的数据会阻止其他并发事务的进行,长时间的事务会导致资源竞争,降低应用程序的吞吐量。因此,应避免在事务中进行耗时操作,尤其是等待用户输入。这样做不仅会...

    物业公司法律事务管理条例.docx

    《物业公司法律事务管理条例》是针对物业管理行业中法律事务的管理和实施制定的一套详细规则。条例的主要目的是强化公司的法律事务管理,构建完整的法律事务管理体系,确保在物业管理业务中防范法律风险,解决可能...

    税务师事务所待遇如何税务师事务所年检工作报告书.pdf

    江西省某县银河税务师事务所提交的年检报告,反映了其在规定时间内遵守行业规则的情况。 3. **执业规范**: - 事务所通过脱钩改制,成为以注册税务师为主体的独立社会中介机构,建立了以质量控制为核心的内部管理...

Global site tag (gtag.js) - Google Analytics