事务管理最佳实践全面解析

事务管理

  事务是一个单元的工作,要么全做,要么全不做。

  事务管理对于维持数据库系统内部保存的数据逻辑上的一致性、完整性,起着至关重要的作用。

  如:一个银行应用软件中,转帐的操作中,需要先在A用户帐户中减去资金,然后再在B用户帐户中增加相应的资金。如果完成A帐户操作后,由于系统故障或者网络故障,没有能够完成接下来的操作,那么A帐户中的资金就白白流失了。显然,客户是无法接受这样的结果的!

  如果我们把一个A和B帐户的操作放在一个事务单元中,那么如果遇到上述异常情况,A帐户减少资金的操作会回滚。A帐户的资金不会减少。

事务管理和数据库连接的关系

  事务管理的工作,需要在数据库连接上进行。如果没有数据库连接,事务管理是无法实施的。

  因此,一个事务单元,应该小于或者等于一个数据库连接的生命周期。

事务管理最佳模式

  数据库连接管理最佳模式

  数据库连接,是一种很宝贵也很昂贵的资源。一个数据库可以提供的数据库连接总数是有限的。而且,获取一次数据库连接也是非常昂贵的操作。需要建立网络连接。因此,我们应当尽可能的重用数据库连接,让数据库连接维持的时间尽可能的长。但是,我们也不能把数据库连接维持的太久。因为,一个数据库可以提供的数据库连接总数是有限的,如果数据库连接的时间很长,那么其他需要数据库连接的工作就无法得到所需的数据库连接。

  因此,最佳的数据库连接模式,是“每次请求,一次数据库连接”这样的使用模式。

  因为,多次请求之间的时间间隔是无法预料的,可能长达几小时、甚至几天。数据库连接显然不能白白的等待在那里。而应该返回给数据库,或者数据库连接缓冲池,让其他程序和组件有机会使用数据库连接。另外,如果一次数据库连接,小于一次用户请求,那么,数据库连接的得到和关闭次数又太频繁了。因为,得到一次数据库连接是非常消耗资源的。一次用户请求,是一个短时、瞬间的操作,完全没有必要使用多个数据库连接。

  事务是依托在数据库连接之上的,多个数据库连接之间,是无法使用同一个事务的。(实际上,JTA分布式事务是可以在一个事务中使用多个数据库连接的)

事务管理最佳模式

  最佳的事务管理模式,“每次请求,一次数据库连接,一次事务”。

  一次用户请求,是用户对软件系统功能的一次独立调用。用户当然不希望他的一次操作,系统只执行一部分这种情况的发生。因此,对一次用户请求的响应,使用一次事务,是非常和正确的。

  对于一次单纯的查询操作,不更改持久化数据库中记录,那么我们不需要使用事务。在数据库操作发生错误时,抛出异常,让用户界面显示出问题即可。而对于更改数据库记录的操作,并且涉及到多次数据库操作的,则必须使用事务,以保证数据库中记录的完整性和真实性。

事务管理的最佳设计模式

  最佳的事务管理模式,是“每次请求,一次数据库连接,一次事务”。那么,根据这个原则,具体我们应该怎样编写程序呢?

  在DAO数据访问层,执行数据库操作的DAO方法,并不需要创建和关闭数据库连接,也不需要处理事务。它们之需要得到数据库连接,然后使用这个连接即可。(数据库连接,可以通过参数从外部得到,也可以从本地线程变量中得到。后 者是目前主流的技术)

  这就是我提出的“事务管理最佳实践”的工作情况。

  在Service业务层和DAO数据访问层中,我们都使用了“接口—实现类”相分离的设计模式。

  一、编程方式的数据库连接和事务管理

  假设,现在我们使用多种数据库访问技术,来进行O-R映射。看看我们这个架构的适应能力。

  我们的系统,分别使用JDBC,iBatis,Hibernate这三种数据库访问技术,使用编程方式手工管理数据库连接和事务,不使用Spring这样的IOC容器进行管理。看看我们需要做什么:

一、JDBC编程方式管理数据库连接和事务  

  (1) 开发一个JDBCUtil类,得到数据库连接,并且把它们放在一个线程变量中,以便一个线程重用一个数据库连接。
  (2) 开发DAO接口的实现类,实现DAO方法。从本地线程变量中得到数据库连接,使用它。不需要关闭这个连接,也不需要管理事务。
  (3) 开发Serivce层的*Dao后缀命名的方法。它们只需要调用DAO接口的方法即可。不需要和数据库连接、事务打交道。
  (4) 开发Service层的*Transaction后缀命名的方法。它们调用JDBCUtil类的方法,创建一个数据库连接,并把它放在JDBCUtil类的本地线程变量中,设置conn.setAutoCommit(false);等待DAO接口的方法去取这个已经设为不自动 提交的数据库连接。
  (5) 在Try块中,调用Dao方法(Service接口或者DAO接口的Dao方法)。调用结束之后,提交事务,并在异常处理模块中,设置回滚。

  最后,在finally块中关闭数据库连接,清除本地线程变量的值。

二、iBatis编程方式管理数据库连接和事务

  iBatis本身就是使用本地线程变量来管理数据库连接的。

  (1) DAO接口的实现方法中,调用iBatis代码,执行数据库操作。

  (2) Service层的Dao方法,不需要任何更改。

  (3) Service层的Transaction方法,需要使用iBatis的事务管理代码。  

    private SqlMapClient sqlMap = XmlSqlMapBuilder.buildSqlMap(reader);

    public void updateActionTransaction (String itemId, String newDescription) throws SQLException {

      try {

        sqlMap.startTransaction ();

        dao方法调用;

        sqlMap.commitTransaction ();

      } finally {

        sqlMap.endTransaction ();

      }

    }

  iBatis处理事务的代码,也处理得数据库连接。并且,事务的回滚也被iBatis搞定了。

  也就是说,换了一种数据库访问技术,只需要改变Service层中*Transaction方法的实现和DAO层的实现。

声明方式的数据库连接和事务管理

  使用Spring时,我们一般使用Spring声明式事务来管理数据库连接和事务。

  Spring管理下的JDBC、iBatis、Hibernate数据库访问方法。我们在DAO接口的实现类中,可以使用Spring提供的助手类的便利方法,进行数据库操作。也可以使用Spring提供的助手类,得到Connection,Session等进行数据库操  作。或者使用Spring助手类的execute()方法调用数据库操作代码。

  对于Service层中的Transaction方法。我们需要去除“得到和关闭数据库连接,管理事务”的代码。然后,在Spring的配置文件中,对其应用声明式事务管理。运行时,Spring会通过SpringAOP技术,自动得到数据库连接,管理事务。

  可见,使用声明式事务管理,我们只需要修改得到数据库连接或者会话的Util助手类,以及Transaction方法即可。

  综上所述,可以看到,我提出的这一套事务管理最佳实践是一套非常灵活、强大、简洁的管理事务的最佳实践。具有极其强大的适应能力。采用这套编程范式,你可以很容易地彻底摆脱事务管理带来的困扰!

  使用它,即使是编程方式管理事务,也是非常简单而可爱的。

时间: 2024-10-10 00:59:42

事务管理最佳实践全面解析的相关文章

《国际项目集管理最佳实践与实战应用》大型复杂项目与项目群管理工作坊

<国际项目集管理最佳实践与实战应用>大型复杂项目与项目群管理工作坊 Program Management Training 主办单位:共创国际-项目管理者联盟 2015年4月10.11.12日 北京 & 课程前言 项目集(PROGRAM)定义为“经过协调管理以获取单独管理它们时无法取得收益与控制的一组关联的项目和项目集活动.”从组织战略的角度来看,项目集管理主要是指组织为实现其战略目标或为其客户提供整体解决方案而在组织高层针对战略性资源进行跨界整合的管理活动. 在全球经济一体化的背景下

《项目集管理标准》:全球项目集管理最佳实践

<项目集管理标准>是全球项目集管理最佳实践           <项目集管理标准>(The Standard for Program Management)是由美国项目管理协会推出的一个重要的国家性的,也是事实上的全球性标准.标准详细描述了项目集管理的内容,促进不同项目小组之间进行有效沟通和资源调配.提供了帮助人们理解如何通过提升相互关联的组件的交付能力从而促进组织战略实现的重要且基本的内容.在大多数情况对大部分项目集而言,被认为是清晰.完整的.相关的和公认的在项目集管理中良好实践

Android 6.0 运行时权限管理最佳实践

Android 6.0 运行时权限管理最佳实践 版权声明:转载必须注明本文转自严振杰的博客: http://blog.yanzhenjie.com 这是一篇迟来的博客,Android M已经发布一年多了(6.0的变化),在Android M中权限系统被重新设计,发生了颠覆性的变化,很多人把握不好这个变化,一是对这个权限策略和套路还没有摸透,二是没有一个很好的实践来支撑,在我的技术开发群里很多人问我关于权限的问题,往往我都没有直接回答,因为这个问题不是一两句说的清楚的,这几点是今天我写这篇博客的原

Spring事务管理—aop:pointcut expression解析

先来看看这个spring的配置文件的配置: <!-- 事务管理器 -->  <bean id="transactionManager"   class="org.springframework.orm.hibernate3.HibernateTransactionManager">   <property name="sessionFactory" ref="sessionFactory" /&g

密码管理最佳实践

为每个在线网站和服务设置不同的密码,对于保证你使用网络时的安全来说是至关重要的.下面由Personal Technology的专栏作家Geoffrey Fowler,向你展示密码管理程序是如何帮助你记录所有这些登录信息的. 我有超过150个不同的登录项和账户.要记住这么多的密码,我必须成为“雨人”才行.于是我开始搜寻能够储存我所有的密码的最好的服务,最终将名单削减为了四个,它们兼顾了可用性和安全性:1Password.Dachlane.LastPass和PasswordBox. LastPass

Azure虚拟机管理最佳实践之用户凭据

还记的之前老猫关于通过Powershell远程管理Azure中虚拟机的博文的脚本中,每个虚拟机访问都需要通过get-credential交互方式取得用于访问的用户凭据,但是这这种方式每次都要进行用户交互,如果反复运行的脚本显然不是个好方式,如何加密保留用户的凭据以便反复使用就是个最佳实践的内容.当然现在国际版Azure中提供的自动化服务功能包含的Asset可以安全保留凭据用于自动化脚本调用,由于目前国内的Azure服务还没有这项功能,因此暂时只能按下不表了,当然如果只能这样本文也就结束了,这里介

Fragment管理最佳实践

现在的app视图中tab+fragment是最常用的一种布局,但是如果使用才是更简洁更有效的呢?下面通过一个demo的分类测试来分析下: add remove replace detach attach hide show这些方法的使用对Fragment生命周期的影响分析: 顺便分析下Fragment所依赖的Activity的生命周期: 测试代码如下: MainActivity的代码如下: package com.testfragmentlifecircle; import android.co

Mesos+Zookeeper+Marathon+Docker分布式集群管理最佳实践

参考赵班长的unixhot以及马亮blog 笔者QQ:572891887 Linux架构交流群:471443208 1.1Mesos简介 Mesos是Apache下的开源分布式资源管理框架,它被称为分布式系统的内核.Mesos最初是由加州大学伯克利分校的AMPLab开发,后在Twitter得到广泛使用. Mesos-Master:主要负责管理各个framework和slave,并将slave上的资源分配给各个framework. Mesos-Slave:负责管理本节点上的各个mesos-task

ECS应用管理最佳实践

前言即使在CloudNative发展如火如荼的当下,ECS应用(直接将应用部署在ECS上,不使用容器)仍然占了相当大的比重,原因主要在于相对容器化应用,ECS应用由于不需要容器的运行时环境和类似K8S的调度层软件,因此存在一些天然优势,比如: 更低的Overhead,可以更充分发挥硬件的处理能力,适合用于工作负载比较高的组件或应用更高的单元可靠性,结合高可用方案,可以实现很好的整体可用性更好的安全性,因为隔离在虚拟化层面更易用的运维界面,对运维的技能要求更低对于既存系统,无改造成本当然,对比于容