JPA和分布式事务简介

1. Transaction 分两种,Local Transaction 和 Global Transaction。 
涉及到一个Connection的Commit,称为Local Transaction。 
涉及到多个Connection的Commit,称为Global Transaction。 
楼主提到的是,Global Transaction. 

2. Global Transaction 须要XA接口(包括在JTA里面)的支持。 

import javax.sql.XAConnection; 
import javax.transaction.xa.Xid; 
import javax.transaction.xa.XAResource; 
import javax.transaction.xa.XAException; 
import javax.transaction.Transaction; 
import javax.transaction.TransactionManager; 

其中的 
javax.sql.XAConnection; 
javax.transaction.xa.Xid; 
javax.transaction.xa.XAResource; 

这些XA接口的实现,须要数据库的JDBC提供。 
数据库自己要支持XA。数据库的JDBC也要提供XA的实现。 

Oracle, Sybase, DB2, SQL Server等大型数据库才支持XA, 支持Global Transaction。 
My SQL 连Local Transaction都支持很差,更别说Global Transation了。 

3. XA须要两阶段提交 -- prepare 和 commit. 
假设有两个Connection, con1, con2, 大致的过程以下, java

con1 = XAResouce1.getConnection...
con2 = XAResouce2.getConnection...

con1 do some thing.
con2 do some thing.
after they finish.

pre1 = XAResouce1.prepare();
pre2 = XAResouce2.prepare();

if( both pre1 and pre2 are OK){
XAResouce1 and 2 commit
}else {
XAResouce1 and 2 rollback
}

前面有人讲了,在XAResouce1 and 2 commit的时候, 
可能XAResouce1 commit() 成功了,XAResouce2 commit()失败了。 
这时候,会抛出一个 “启发式异常”。程序能够处理这个异常。好比,XAResouce.recover()之类。 
但通常状况下,还真没别的办法,须要数据管理员根据数据操做日志 undo全部的操做,或者恢复数据备份。 
有的数据库在进行数据操做的时候,会生成一个“反操做”日志。好比,insert 对 delete, 等。 

4. TransactionManager的实现可以处理多个XAResouce(一个XAResouce list)的状况。 
好比Tyrex。或JBoss等EJB Server的Transaction实现代码git

 

注释:XA:XA协议由Tuxedo首先提出的,并交给X/Open组织,做为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通讯的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。github

如下的函数使事务管理器能够对资源管理器进行的操做:sql

  1)xa_open,xa_close:创建和关闭与资源管理器的链接。数据库

  2)xa_start,xa_end:开始和结束一个本地事务。编程

  3)xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个本地事务。框架

  4)xa_recover:回滚一个已进行预提交的事务。分布式

  5)ax_开头的函数使资源管理器能够动态地在事务管理器中进行注册,并能够对XID(TRANSACTION IDS)进行操做。函数

  6)ax_reg,ax_unreg;容许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。学习

 

 

JTA和JTS

 

JTA

 

JTA定义了一套接口,其中约定了几种主要的角色:TransactionManager、UserTransaction、Transaction、XAResource,并定义了这些 角色之间须要遵照的规范,如Transaction的委托给TransactionManager等。

 

JTS

 

JTS也是一组规范,上面提到JTA中须要角色之间的交互,那应该如何交互?JTS就是约定了交互细节的规范。

 

整体上来讲JTA更多的是从框架的角度来约定程序角色的接口,而JTS则是从具体实现的角度来约定程序角色之间的接口,二者各司其职。

 

由于JTA相对来讲,更高层一些,咱们主要关注JTA。

 

XA

 

XA协议,规定事务管理器和资源管理器接口,采用二阶段提交协议。

JTA事务有效的屏蔽了底层事务资源,可是与本地事务相比,XA协议的系统开销大。

 

 

总结

 

关键接口

 

先介绍一下JTA的规范接口中,主要围绕如下几个接口:

 

  • UserTransaction:编程人员接口
  • TransactionManager:留给厂商实现的与事务管理有关的接口
  • Transaction:留给厂商实现的事务
  • XAResource:留给厂商实现的与持久化资源有关的接口

 

接口类中的接口定义可参见源码,几个接口类关系以下:

下载了JBoss的JTA实现源码,可是发现深刻这个源码有难度,且须要的时间也会较长,故留着之后学习。JBoss的JTA实现是Narayana,SVN地址为https://github.com/jbosstm/narayana,若是有兴趣能够研究一下。

二阶段提交协议

因此在一阶段协议的基础上,有了二阶段协议,二阶段协议的好处是添加了一个管理者角色,以下:

很明显,二阶段协议经过将两层变为三层,增长了中间的管理者角色,从而协调多个数据源之间的关系,二阶段提交协议分为两个阶段。

应用程序调用了事务管理器的提交方法,此后第一阶段分为两个步骤:

  • 事务管理器通知参与该事务的各个资源管理器,通知他们开始准备事务。
  • 资源管理器接收到消息后开始准备阶段,写好事务日志并执行事务,但不提交,而后将是否就绪的消息返回给事务管理器(此时已经将事务的大部分事情作完,之后的内容耗时极小)。

第二阶段也分为两个步骤:    

  • 事务管理器在接受各个消息后,开始分析,若是有任意其一失败,则发送回滚命令,不然发送提交命令。
  • 各个资源管理器接收到命令后,执行(耗时不多),并将提交消息返回给事务管理器。
    事务管理器接受消息后,事务结束,应用程序继续执行。
    为何要分两步执行?一是由于分两步,就有了事务管理器统一管理的机会;二尽量晚地提交事务,让事务在提交前尽量地完成全部能完成的工做,这样,最后的提交阶段将是耗时极短,耗时极短意味着操做失败的可能性也就下降。
    同时,二阶段提交协议为了保证事务的一致性,不论是事务管理器仍是各个资源管理器,每执行一步操做,都会记录日志,为出现故障后的恢复准备依据。
    二阶段提交协议的存在的弊端是阻塞,由于事务管理器要收集各个资源管理器的响应消息,若是其中一个或多个一直不返回消息,则事务管理器一直等待,应用程序也被阻塞,甚至可能永久阻塞。
相关文章
相关标签/搜索