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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事务管理最佳实践全面解析相关的知识,希望对你有一定的参考价值。

 

事务管理

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

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

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

  如果我们把一个AB帐户的操作放在一个事务单元中,那么如果遇到上述异常情况,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提供的助手类,得到ConnectionSession等进行数据库操  作。或者使用Spring助手类的execute()方法调用数据库操作代码。

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

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

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

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

 

以上是关于事务管理最佳实践全面解析的主要内容,如果未能解决你的问题,请参考以下文章

民生银行数据库智能运维的探索与实践——DBPaaS数据库统一管理平台 | 最佳实践

业务技术协同线上化的硬盘式研发管理实践

Zookeeper详细使用解析!分布式架构中的协调服务框架最佳选型实践

Android应用开发:核心技术解析与最佳实践pdf

每周一书《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》分享!

Spring事务使用最佳实践