posts - 42,comments - 83,trackbacks - 0
        这几天做welogic xa debug的时候,反复碰到TransactionTimeoutException。我可是把transaction的timeout设到了100000秒的,一天多,怎么可能10几分钟就timeout掉啊?而且我还把事务分支的timeout调到了一天,即enable "Set XA Transaction Timeout ", "XA Transaction Timeout"=86400秒。注意:XA Transaction Timeout是Weblogic作为transction manager时,要求对应XA resource的resource manager给transaction branch设定的timeout.如果Set XA Transaction Timeout没有enable的话,那么resource manager会使用自己的Timeout去控制transaction branch。

 1     public void xaTest()
 2     {
 3             try{
 4                     UserTransaction tx = getUserTransaction();
 5                     System.out.println("tx: " + tx.toString());
 6                     tx.setTransactionTimeout(100000);
 7                     tx.begin();
 8                     Connection conn1 = getConnection("t3://localhost:7011", XA_DS);
 9                     Connection conn2 = getConnection("t3://localhost:7021", REMOTE_XA_DS);
10                     this.executeInsertInPSMT(conn1, null);
11                     this.executeAnoInsertInPSMT(conn2, null);
12                     conn1.close();
13                     conn2.close();
14                     tx.commit();
15             }catch(Exception e){
16                     e.printStackTrace();
17             }
18     }


        异常堆栈如下:
weblogic.transaction.RollbackException: Timed out tx=BEA1-0000DB7D6CD6F87E5FE6 after 100000 seconds
        at weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:215)
        at weblogic.rmi.internal.BasicRemoteRef.invoke(BasicRemoteRef.java:224)
        at weblogic.transaction.internal.CoordinatorImpl_923_WLStub.commit(Unknown Source)
        at weblogic.transaction.internal.TransactionImpl.commit(TransactionImpl.java:324)
        at weblogic.transaction.internal.TransactionManagerImpl.commit(TransactionManagerImpl.java:283)
        at weblogic.transaction.internal.TransactionManagerImpl.commit(TransactionManagerImpl.java:277)
        at com.bea.cs.test.jdbc.DriverTest.xaTest(DriverTest.java:293)
        at com.bea.cs.test.jdbc.DriverTest.main(DriverTest.java:49)
Caused by: weblogic.transaction.RollbackException: Timed out tx=BEA1-0000DB7D6CD6F87E5FE6 after 100000 seconds
        at weblogic.transaction.internal.TransactionImpl.throwRollbackException(TransactionImpl.java:1809)
        at weblogic.transaction.internal.ServerTransactionImpl.internalCommit(ServerTransactionImpl.java:331)
        at weblogic.transaction.internal.ServerTransactionImpl.commit(ServerTransactionImpl.java:227)
        at weblogic.transaction.internal.CoordinatorImpl.commit(CoordinatorImpl.java:101)
        at weblogic.transaction.internal.CoordinatorImpl_WLSkel.invoke(Unknown Source)
        at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:553)
        at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:443)
        at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363)
        at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:147)
        at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:439)
        at weblogic.rmi.internal.BasicServerRef.access$300(BasicServerRef.java:61)
        at weblogic.rmi.internal.BasicServerRef$BasicExecuteRequest.run(BasicServerRef.java:983)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
        
        如果只有这几个timeout的话,那么这个事务就不应该在短短的10多分钟内被rollback.调查后发现,除了这几个上面的两个timeout,weblogic内部还有几个跟事务状态有关的timeout,不过这几个timeout都是internal的,最终用户是无法对其进行配置的。

        对于一个能正常结束的transaction,weblogic中,它会经历如下几个状态,New, PrePrepared , Logging(if logging is necessary) ,Prepared,  Committed or Rollbacked. 这几个状态切换前,weblogic完成工作如下:
        
        New---->PrePrepared: 完成synchronization list的beforeCompletion(), 这个工作是以链式方式完成的,加入involve到某个global transaction中的xa resources分别驻留于server_1, server_2, server_3, server_4上,加入 server_1 充当的是coordinator, 其余三个充当的是subcoordinator。那么server_1首先会完成本地synchronization 的beforeCompletion,然后它会发起一个RMI请求到server_2,server_2完成本地的beforeCompletion后,继续要求
 server_3, server_3完成后要求server_4,如此这般,链式完成个server的工作,直到最后一个server(即sserver_4) ,server_4发现自己是最后一个,它会负责将PrePrepare OK的Ack返回给 coordinator,即server_1。
       
         PrePrepared---->Logging: 这个阶段coordinator会以并行的方式要求每个subcoordinator完成prepare的工作,当所以subcoordinator的prepare Ack都收到后,它会开始做它本地resource的prepare。所以XA resources都Prepare OK后,coordinator开始要求non-xa-resource(最多只有一个,emulate_2PC或LLR)去做commit.non-xa-resource完成commit后,coordinator将判断是否需要将这个global transaction记入tlog,如果需要,transaction的状态将被切换到Logging,否则到Prepared。关于emulate_2PC和LLR的区别,这里不做过多讨论,但值得注意的是,LLR在weblogic9中引入,相对于emulate_2PC,LLR的事务可靠性更高。emulate_2PC以文件方式记录tlog,而LLR则使用数据库表方式记录。如果传统的emulate_2PC在non-xa-resource提交成功后和global transaction记入tlog前发生系统crash,那么这个事务就会产生不一致性。non-xa-resource已经提交,而其余xa-resource则处于preprared状态,最终可能会被会滚掉。而LLR采用数据库表方式,把non-xa-resource的操作、tlog记入放在一个transaction branch中,则不会发生上述情况。
       
        Logging---->Prepared:将global transaction记入tlog,以备recover.
        
        Prepared---->Committed :工作内容、顺序基本同于Prepare,不过有点区别是:这里要求subcoordinator完成的是commit, 操作顺序上也稍有点区别,首先是non-xa-resource的commit,然后是subcoordinator的commit,最后才是coordinator的local xa resource commit.

        状态切换过程中,事务超时并不尊从global transaction timeout,而是依照weblogic内部状态切换超时规定,所谓状态切换超时是指transaction 从这一状态切换到下一状态的时间限制,在这限制时间内,必须完成状态切换所需要完成的工作。比如,从PrePrepared---->Logging,必须完成所有xa_resource, non_xa_resource的prepare.这些超时在weblogic内部使用的都是常量,是不可配置的。
        PrePrepared---->Logging:60secs
        Logging---->Prepared:30secs
        Prepared---->Committed :120secs        

       那么weblogic是怎么实现上述状态切换超时控制的呢?当从状态A切换到B的时候,如果到B所需要的所有工作都已经完成,那么weblogic事务状态设定成B,并重置wakeUpAfterSeconds(从B到下一状态的时间限制),这个wakeUpAfterSeconds对于状态切换,都是些常量,即多少秒后,这个事务会被触发超时。比如从PrePrepared---->Logging,我们完成preprepare的工作后,会切换事务状态到preprepare,并将状态切换超时设定到PrePrepared---->Logging的时间限制,如下:

1   private final void setPrePreparedUnsync() {
2         setState(STATE_PRE_PREPARED);
3             ..
4       wakeUpAfterSeconds(Constants.PRE_PREPARED_WAIT_SECONDS);
5   }

  也就是说,虽然我们将global transaction timeout设定的很长,但如果某一状态切换过程耗费时间过长,事务同样会被超时掉。

  加入如下的debug options,可以debug 出详细信息,
        -Dweblogic.debug.DebugJTA2PC=true, -Dweblogic.debug.DebugJTA2PCStackTrace=true

        下面是一段debug输出,注意其中的wakeUpAfterSeconds为120secs 

        ####<Feb 23, 2009 1:05:09 PM CST> <Debug> <JTA2PC> <fjin> <server_1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <BEA1-02A2E9A37F31> <> <1235365509343> <000000> <java.lang.Exception: DEBUG: Name=JDBC Internal,Xid=BEA1-02A2E9A37F31(19522730),Status=Prepared,numRepliesOwedMe=0,numRepliesOwedOthers=0,seconds since begin=0,seconds left=3000,activeThread=Thread[[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads],SCInfo[driver_test_domain+server_1]=(state=pre-prepared),properties=({weblogic.transaction.name=JDBC Internal}),OwnerTransactionManager=ServerTM[ServerCoordinatorDescriptor=(CoordinatorURL=server_1+192.168.0.51:7011+driver_test_domain+t3+, XAResources={OracleXADS},NonXAResources={})]) wakeUpAfterSeconds(120)
 at weblogic.transaction.internal.TxDebug.debugStack(TxDebug.java:60)
 at weblogic.transaction.internal.TransactionImpl.wakeUpAfterSeconds(TransactionImpl.java:1940)
 at weblogic.transaction.internal.ServerTransactionImpl.setPreparedUnsync(ServerTransactionImpl.java:3095)
 at weblogic.transaction.internal.ServerTransactionImpl.globalPrepare(ServerTransactionImpl.java:2179)
 at weblogic.transaction.internal.ServerTransactionImpl.internalCommit(ServerTransactionImpl.java:266)
 at weblogic.transaction.internal.ServerTransactionImpl.commit(ServerTransactionImpl.java:227)
 at weblogic.transaction.internal.TransactionManagerImpl.commit(TransactionManagerImpl.java:283)
 at weblogic.jdbc.common.internal.ConnectionEnv.test(ConnectionEnv.java:684)
 at weblogic.jdbc.common.internal.ConnectionEnv.test(ConnectionEnv.java:460)
 at weblogic.common.resourcepool.ResourcePoolImpl.checkResource(ResourcePoolImpl.java:1504)
 at weblogic.common.resourcepool.ResourcePoolImpl.checkAndReturnResource(ResourcePoolImpl.java:1413)
 at weblogic.common.resourcepool.ResourcePoolImpl.checkAndReturnResource(ResourcePoolImpl.java:1401)
 at weblogic.common.resourcepool.ResourcePoolImpl.testUnusedResources(ResourcePoolImpl.java:1834)
 at weblogic.common.resourcepool.ResourcePoolImpl.access$700(ResourcePoolImpl.java:37)
 at weblogic.common.resourcepool.ResourcePoolImpl$ResourcePoolMaintanenceTask.timerExpired(ResourcePoolImpl.java:2002)
 at weblogic.timers.internal.TimerImpl.run(TimerImpl.java:265)
 at weblogic.work.ServerWorkManagerImpl$WorkAdapterImpl.run(ServerWorkManagerImpl.java:518)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
>


  

posted on 2009-02-24 10:54 走走停停又三年 阅读(3940) 评论(2)  编辑  收藏 所属分类: Weblogic

FeedBack:
# re: Weblogic中几个internal的XA timeout(状态切换相关的超时)
2009-10-27 23:38 | Mingfu
请问,如果TLOG的SIZE和Logging---->Prepared 的时间有关吗?
====
Logging---->Prepared:将global transaction记入tlog,以备recover.
  回复  更多评论
  
# re: Weblogic中几个internal的XA timeout(状态切换相关的超时)
2009-10-28 17:34 | fjin
tlog中的log record是临时性的,事务成功提交后,对应的log record会被删除,所以一个正常的系统,tlog不会不停的增长,除非可疑事务太多。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: