posts - 42,comments - 83,trackbacks - 0
                  這幾天做welogic xa debug的時候,反復(fù)碰到TransactionTimeoutException。我可是把transaction的timeout設(shè)到了100000秒的,一天多,怎么可能10幾分鐘就timeout掉啊?而且我還把事務(wù)分支的timeout調(diào)到了一天,即enable "Set XA Transaction Timeout ", "XA Transaction Timeout"=86400秒。注意:XA Transaction Timeout是Weblogic作為transction manager時,要求對應(yīng)XA resource的resource manager給transaction branch設(shè)定的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的話,那么這個事務(wù)就不應(yīng)該在短短的10多分鐘內(nèi)被rollback.調(diào)查后發(fā)現(xiàn),除了這幾個上面的兩個timeout,weblogic內(nèi)部還有幾個跟事務(wù)狀態(tài)有關(guān)的timeout,不過這幾個timeout都是internal的,最終用戶是無法對其進(jìn)行配置的。

                  對于一個能正常結(jié)束的transaction,weblogic中,它會經(jīng)歷如下幾個狀態(tài),New, PrePrepared , Logging(if logging is necessary) ,Prepared,  Committed or Rollbacked. 這幾個狀態(tài)切換前,weblogic完成工作如下:
                  
                  New---->PrePrepared: 完成synchronization list的beforeCompletion(), 這個工作是以鏈?zhǔn)椒绞酵瓿傻模尤雐nvolve到某個global transaction中的xa resources分別駐留于server_1, server_2, server_3, server_4上,加入 server_1 充當(dāng)?shù)氖莄oordinator, 其余三個充當(dāng)?shù)氖莝ubcoordinator。那么server_1首先會完成本地synchronization 的beforeCompletion,然后它會發(fā)起一個RMI請求到server_2,server_2完成本地的beforeCompletion后,繼續(xù)要求
           server_3, server_3完成后要求server_4,如此這般,鏈?zhǔn)酵瓿蓚€server的工作,直到最后一個server(即sserver_4) ,server_4發(fā)現(xiàn)自己是最后一個,它會負(fù)責(zé)將PrePrepare OK的Ack返回給 coordinator,即server_1。
                 
                   PrePrepared---->Logging: 這個階段coordinator會以并行的方式要求每個subcoordinator完成prepare的工作,當(dāng)所以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的狀態(tài)將被切換到Logging,否則到Prepared。關(guān)于emulate_2PC和LLR的區(qū)別,這里不做過多討論,但值得注意的是,LLR在weblogic9中引入,相對于emulate_2PC,LLR的事務(wù)可靠性更高。emulate_2PC以文件方式記錄tlog,而LLR則使用數(shù)據(jù)庫表方式記錄。如果傳統(tǒng)的emulate_2PC在non-xa-resource提交成功后和global transaction記入tlog前發(fā)生系統(tǒng)crash,那么這個事務(wù)就會產(chǎn)生不一致性。non-xa-resource已經(jīng)提交,而其余xa-resource則處于preprared狀態(tài),最終可能會被會滾掉。而LLR采用數(shù)據(jù)庫表方式,把non-xa-resource的操作、tlog記入放在一個transaction branch中,則不會發(fā)生上述情況。
                 
                  Logging---->Prepared:將global transaction記入tlog,以備recover.
                  
                  Prepared---->Committed :工作內(nèi)容、順序基本同于Prepare,不過有點區(qū)別是:這里要求subcoordinator完成的是commit, 操作順序上也稍有點區(qū)別,首先是non-xa-resource的commit,然后是subcoordinator的commit,最后才是coordinator的local xa resource commit.

                  狀態(tài)切換過程中,事務(wù)超時并不尊從global transaction timeout,而是依照weblogic內(nèi)部狀態(tài)切換超時規(guī)定,所謂狀態(tài)切換超時是指transaction 從這一狀態(tài)切換到下一狀態(tài)的時間限制,在這限制時間內(nèi),必須完成狀態(tài)切換所需要完成的工作。比如,從PrePrepared---->Logging,必須完成所有xa_resource, non_xa_resource的prepare.這些超時在weblogic內(nèi)部使用的都是常量,是不可配置的。
                  PrePrepared---->Logging:60secs
                  Logging---->Prepared:30secs
                  Prepared---->Committed :120secs        

                 那么weblogic是怎么實現(xiàn)上述狀態(tài)切換超時控制的呢?當(dāng)從狀態(tài)A切換到B的時候,如果到B所需要的所有工作都已經(jīng)完成,那么weblogic事務(wù)狀態(tài)設(shè)定成B,并重置wakeUpAfterSeconds(從B到下一狀態(tài)的時間限制),這個wakeUpAfterSeconds對于狀態(tài)切換,都是些常量,即多少秒后,這個事務(wù)會被觸發(fā)超時。比如從PrePrepared---->Logging,我們完成preprepare的工作后,會切換事務(wù)狀態(tài)到preprepare,并將狀態(tài)切換超時設(shè)定到PrePrepared---->Logging的時間限制,如下:

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

            也就是說,雖然我們將global transaction timeout設(shè)定的很長,但如果某一狀態(tài)切換過程耗費時間過長,事務(wù)同樣會被超時掉。

            加入如下的debug options,可以debug 出詳細(xì)信息,
                  -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 走走停停又三年 閱讀(3986) 評論(2)  編輯  收藏 所屬分類: Weblogic

          FeedBack:
          # re: Weblogic中幾個internal的XA timeout(狀態(tài)切換相關(guān)的超時)
          2009-10-27 23:38 | Mingfu
          請問,如果TLOG的SIZE和Logging---->Prepared 的時間有關(guān)嗎?
          ====
          Logging---->Prepared:將global transaction記入tlog,以備recover.
            回復(fù)  更多評論
            
          # re: Weblogic中幾個internal的XA timeout(狀態(tài)切換相關(guān)的超時)
          2009-10-28 17:34 | fjin
          tlog中的log record是臨時性的,事務(wù)成功提交后,對應(yīng)的log record會被刪除,所以一個正常的系統(tǒng),tlog不會不停的增長,除非可疑事務(wù)太多。  回復(fù)  更多評論
            
          主站蜘蛛池模板: 宜州市| 阿拉善盟| 公主岭市| 洞头县| 呼伦贝尔市| 江城| 巴中市| 肃北| 新蔡县| 南阳市| 东方市| 专栏| 馆陶县| 北京市| 宁城县| 石河子市| 马公市| 威信县| 新田县| 锦州市| 盐山县| 新疆| 昭苏县| 文昌市| 滦平县| 中方县| 安吉县| 固原市| 兰溪市| 西华县| 德昌县| 台湾省| 凤城市| 滁州市| 增城市| 洛宁县| 松溪县| 芦溪县| 安达市| 盐山县| 张掖市|