3 Replies Latest reply on Jan 22, 2018 4:59 AM by tomjenkinson

    Transient error during commit results in HeuristicMixedException

    alon3392

      Hello,

       

      I tried a simple test (on narayana-jta 5.7.1) with XAResource returning XAER_RMFAIL on commit(), signaling a transient error.

       

      If there is more than one enlisted instance of such XAResource, TransactionManager.commit() would finish without exception, it just logs warning message for each resource that returned XAER_RMFAIL, and at some latter time recovery manager will try to commit again.

       

      All as expected.

       

      However, if there is only one XAResource, TransactionManager.commit() fails with:

       

      17:40:48.061 [main] WARN com.arjuna.ats.jta - ARJUNA016039: onePhaseCommit on < formatId=131077, gtrid_length=31, bqual_length=36, tx_uid=0:ffff0a01011f:d796:5a61bd20:2, node_name=me1, branch_uid=0:ffff0a01011f:d796:5a61bd20:3, subordinatenodename=null, eis_name=0 > (p1.XaRes1@6c629d6e) failed with exception XAException.XAER_RMFAIL

      javax.transaction.xa.XAException: null

      at p1.XaRes1.commit(XaRes1.java:32)

      at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:702)

      at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2386)

      at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1497)

      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:96)

      at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)

      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1289)

      at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)

      at p1.Test1.main(Test1.java:48)

      17:40:48.061 [main] WARN com.arjuna.ats.arjuna - ARJUNA012084: One-phase commit of action 0:ffff0a01011f:d796:5a61bd20:2 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD

      Exception in thread "main" javax.transaction.HeuristicMixedException

      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1297)

      at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)

      at p1.Test1.main(Test1.java:48)

      Suppressed: javax.transaction.xa.XAException

      at p1.XaRes1.commit(XaRes1.java:32)

      at com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:702)

      at com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2386)

      at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1497)

      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:96)

      at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)

      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1289)

       

      This doesn't seem right. Not only that it fails with exception, but it fails with HeuristicMixedException. Such exception also causes heuristic participant entry being written in transaction log (that entry can only be removed manually)

       

      Thanks.

        • 1. Re: Transient error during commit results in HeuristicMixedException
          tomjenkinson

          There is a difference here between RMFAIL on a 2PC resource and RMFAIL from a 1PC resource.

           

          With 2PC we can use that knowledge specified in XA that as the resource successfully prepared it should successfully commit at some point in the future. As the XAResource should be fulfilling it's contract it should not have a perpetual difficulty in transitioning that branch and thus eventually the recovery manager should be able to safely transition it.

           

          However, for a TMONEPHASE we are not able to make that assumption because the resource was not asked to prepare. In this case the best situation is to alert the user to the issue immediately. We are then limited by the exception types that JTA supports.

          • 2. Re: Transient error during commit results in HeuristicMixedException
            alon3392

            Yeah, it makes sense, if one phase commit fails with error code that guarantees that commit didn't happen (such as XAER_RMERR or XA_RETRY) then javax.transaction.RollbackException is thrown, otherwise the only choice is javax.transaction.HeuristicMixedException.

            What is strange however is that for some error codes (XAER_OUTSIDE, XAER_DUPID, XAER_ASYNC, XA_NOMIGRATE, XA_RDONLY) TransactionManager.commit() doesn't throw any exception and writes an entry to transaction log, which of course will never be able to be completed by recovery manager:

             

            09:21:23.891 [main] WARN com.arjuna.ats.jta - ARJUNA016037: Could not find new XAResource to use for recovering non-serializable XAResource XAResourceRecord < resource:null, txid:< formatId=131077, gtrid_length=31, bqual_length=36, tx_uid=0:ffff0a010116:dea9:5a63eb02:2, node_name=me1, branch_uid=0:ffff0a010116:dea9:5a63eb02:3, subordinatenodename=null, eis_name=0 >, heuristic: TwoPhaseOutcome.FINISH_OK com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord@22a71081 >

            09:21:23.891 [main] DEBUG com.arjuna.ats.arjuna - RecoverAtomicAction.replayPhase2 recovering 0:ffff0a010116:dea9:5a63eb02:2 ActionStatus is ActionStatus.COMMITTED

            • 3. Re: Transient error during commit results in HeuristicMixedException
              tomjenkinson

              XAER_OUTSIDE, XAER_DUPID, XA_NOMIGRATE, XA_RDONLY are not valid for xa_commit so I think we should not worry about non-compliant XAResource that return those from XAResource::commit()

               

              Regarding XAER_ASYNC I don't think in Java there is a way to pass in TMASYNC so again it is not too problematic we don't handle that case. However if you would like to raise a JBTM issue we can make the change to throw the exception in case an XAResource provides a configurable way to set that flag instead of via XAResource interface.