对嵌套事务的理解

原文地址:http://dev2dev.bea.com.cn/blog/davidturing/200803/transaction_04_923.html

目前,似乎很少有支持嵌套事务的中间件,但嵌套事务确实存在。
假定有Method A, Method B, Method C
A 调用 B,C

ServiceHost {    
        
    
/**    
     * 事务属性配置为 PROPAGATION_REQUIRED   
     
*/    
    
void  invoke() {    
      try{
           ServiceA.invoke()
      } 
catch (Bussiness.A.Exception) { 
           abort()
      }

        
try  {    
            ServiceB.invoke();    
        } 
catch  (Bussiness.B.Exception) {    
            ServiceC.invoke();
        } 
catch  (Bussiness.C.Exception) {    
            ServiceD.invoke();
        } catch (Bussiness.D.Exception) { 
           abort()
      }

  
        
try {
           ServiceE.invoke()
        } 
catch  (Bussiness.E.Exception) { 
           ServiceF.invoke()
        }catch (Bussiness.F.Exception) { 
           abort()
      }


    }    
   

 

ServiceA {    
        
    
/**    
     * 事务属性配置为 PROPAGATION_NESTED, 
     × 即该事务需要被嵌套   
     
*/      
    
void  methodA() {    
    }    
        
}

 

ServiceA, ServiceB, ServiceC, ServiceD, ServiceE, ServiceF 都配置为 PROPAGATION_NESTED
通过这样的嵌套规约,我们可以满足业务完整性的需求,一个 ServiceParent  业务,只允许出现 A-B-E , A-B-F, A-C-E, A-C-F, A-D-E A-D-F 的组合,其他组合,如 A-B-C, A-E, B-F 都是不允许的。
 
术语上, ServiceA, B, C, D, E, F 的事务均是 ServiceParent 事务的子事务,现在,是 ServiceParent 嵌套 ServiceA-F ,且嵌套事务的几个特性如下:
1,  假定子事务 (ServiceA-F) 处于活动状态 (active) ,则 parent 事务 (ServiceParent) 不能执行任何其他操作,父事务只能 commit 事务, abort 事务以及创建更多其它子事务。
2,  若子事务 (ServiceA) 被提交了,此时父事务则能够看到子事务做出的任何修改,这些修改,对其他子事务来说是隐藏的,直到父事务提交为止。
3,  同样地,如果被嵌套的事务 ServiceA 被回滚了,则它也不会对父事务有任何影响,且父事务 servieParent 也不会看到 ServiceA 曾经修改过的数据。
4,  最终父事务提交、回滚才会决定到子事务的提交、回滚。表达的形象点,若 ServiceA “提交”后, ServiceParent 却因为 Service B/C/D 都无法成功执行, ServiceA 会回滚。这种做法依赖于 JDBC 3.0 SavePoint 技术。
5,  嵌套子事务提交后,它对 DB 的锁其实并没有释放,这些锁的控制权被转交给父事务,直到父事务提交(或回滚)后,锁才会真正释放
6,  目前,嵌套的深度不收控制,也就是,我们可对 method 进行以深度嵌套。
 
 
           
      现在,我们略略了解一下 JDBC SavePoint 技术,它给予了我们这样的能力,在一个事务里面,我们能够将已经提交的事务状态,恢复到一个事务 commit 以前的任意定点 ( 这个点就是 SavePoint)
            举个例子,假设我们面临这样一种情况, methodA 是运算代价非常大的事务操作, methodB, methodC 都是轻量级的事务,我们需要执行这样一个事务 Tx={methodA->methodB->methodC}
           没有 SavePoint 之前,如果 methodA 执行成功,但是恰恰 methodB 失败了,那么 methodA 所有成果必须回滚, methodC 也别想执行了,因为 methodA methodB methodC 都在同一个 Tx 事务中; JDBC3.0 SavePoint 技术为我们提供了一个无需回滚 MethodA 的折衷办法,可以让我们在保留 methodA 的成果的同时,仅仅回滚 methodB ,然后继续执行 methodC
      回滚到SavePoint的代码类似于:

 

Statement stmt  =  conn.createStatement();
int  rows  =  stmt.executeUpdate( " INSERT INTO TAB1 (COL1) VALUES  "  +
" (’FIRST’) " );
//  set savepoint
Savepoint svpt1  =  conn.setSavepoint( " SAVEPOINT_1 " );
rows 
=  stmt.executeUpdate( " INSERT INTO TAB1 (COL1)  "  +
" VALUES (’SECOND’) " );

conn.rollback(svpt1);

conn.commit();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值