1 2 Previous Next 19 Replies Latest reply on Mar 25, 2012 9:10 AM by redfoxlee

    When transaction timeout, rollback didn't work as expected.

    redfoxlee

      Hi, i got some problem with transaction timeout, hope somebody can help me to figure it out.

       

      here is what i'm trying to do :

       

      // consider this method as one transaction

      method() {

          1.insert table1

          2.insert table2

          3.insert table3

          ....

      }

      Sometimes this operation could take a very long while until transaction timeout exception occured. and i got something like below:

       

      ErrorLogType1

      WARN - Abort of action id -3f57cb74:c9a4:499eb149:a92 invoked while multiple threads active within it.

      WARN - CheckedAction::check - atomic action -3f57cb74:c9a4:499eb149:a92 aborting with 1 threads active!

       

      ErrorLogType2

        The transaction is not active!

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

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

        at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)

       

      as it was mentioned before : https://community.jboss.org/wiki/TxMultipleThreads

       

      ErrorLogType1 happened between 2 and 3, and ErrorLogType2 happend after 3. Rollback only effected part 1,2 , after that didn't get rolled back.

       

      I know maybe i have to increase default transaction-timeout value larger to fit requirement. But in case of it could happen again, i would like to know if there are some solutions for this situation.

       

      So, my question is:

       

      1. Is this partly rollback a right behavior?

      2. If not how can i do to correct this wrong behavior? or how to get completly rollback for this situation?

       

      ps:hope my bad english will not get you confused. I will be appreciate for any help. Thank you very much

        • 1. Re: When transaction timeout, rollback didn't work as expected.
          tomjenkinson

          As I understand what you are saying is:

           

          begin();

          update1();

          update2();

          update3(); <-- WARNS APPEAR DURING THE UPDATE FROM THE TRANSACTION REAPER THREAD

          commit(); <-- INACTIVE EXCEPTION RAISED

           

           

          i.e. Sometimes during update3 you see the rollback happening because the transaction timed out:

          WARN When transaction timeout, rollback didn't work as expected. When transaction timeout, rollback didn't work as expected. - Abort of action id -3f57cb74:c9a4:499eb149:a92 invoked while multiple threads active within it.

          WARN When transaction timeout, rollback didn't work as expected. When transaction timeout, rollback didn't work as expected. - CheckedAction::check - atomic action -3f57cb74:c9a4:499eb149:a92 aborting with 1 threads active!

           

          When you see that message, commit fails with the stack you pasted:

          com.arjuna.ats.internal.jta.transaction.arjunacore.inactive

            com.arjuna.ats.internal.jta.transaction.arjunacore.inactive The transaction is not active!

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

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

            at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)

           

          This all seems normal to me for a transaction that has timed out. Based on what you are saying, I would say that update1, update2 and update3 should all be rolled back, is that what you are seeing? If so, the only correction is to increase the timeout, this would be the same with any transaction manager.

           

          Hope that clarifies,

          Tom

          • 2. Re: When transaction timeout, rollback didn't work as expected.
            redfoxlee

            Hi, tom. Thank you for you reply, first.

            Based on what you are saying, I would say that update1, update2 and update3 should all be rolled back, is that what you are seeing?

            Yes, this is what i believed. Only just i didn't see the completely rollback for all 3 processes as i expected .

             

            I'm sorry. Again, 3 processes should all be rolled back, right? Did i take it wrong about your answer ? But why they weren't ? Only 2 of them get rolled back, 3rd couldn't.

             

            Based on your reply, i will consider to increase timeout longer than default. In another way, maybe i also should check out why that update query took so long. I mean usually it dosen't take that long (just 1 min for long). Maybe it will take much longer next time, and i have to increase and increase again. it won't end, right?

             

            BTW:we are running this operation on JBoss AS 4.2.2 GA, MySql 5.1 in a VM. OS is REHL 5, Memory 1844MB, Java Heap Memory 1024 MB. any surggestions about this?

             

            Any way thank you again!!

            • 3. Re: When transaction timeout, rollback didn't work as expected.
              tomjenkinson

              My guess is update3() took place in a different context to the other two activities as the transaction rolled back before update3() really did any work then it either:

              1. update3() was done in a local transaction as the resource manager responsible for update3 could not find transactional info

              2. update3() was done a new JTA transaction as there was no transaction active by the time it was started and therefore automatically committed as it was successful

              • 4. Re: When transaction timeout, rollback didn't work as expected.
                redfoxlee

                Actually i never used transaction explicity but only call the java method as we usual do.So what i am doing is just like below

                 

                private void insertMethod1() {

                     execute insert statement;

                }

                 

                private void insertMethod2() {

                     execute insert statement;

                }

                 

                private void insertMethod3() {

                     execute insert statement;

                }

                 

                public void totalMethod() {

                     insertMehthod1();

                     insertMehthod2();

                     insertMehthod3();

                }

                 

                // no annotations

                // no UserTransactions

                 

                If i didn't get wrong with this, totalMethod should be treated as one transaction. As i know when there is an RuntimeException was thrown, EJB Container will do the rollback for me.

                 

                And the error log like this :

                insertMethod1() excuted

                insertMethod2() excuted

                WARN When transaction timeout, rollback didn't work as expected. When transaction timeout, rollback didn't work as expected. - Abort of action id -3f57cb74:c9a4:499eb149:a92 invoked while multiple threads active within it.

                WARN When transaction timeout, rollback didn't work as expected. When transaction timeout, rollback didn't work as expected. - CheckedAction::check - atomic action -3f57cb74:c9a4:499eb149:a92 aborting with 1 threads active!

                insertMehtod3() excuted

                com.arjuna.ats.internal.jta.transaction.arjunacore.inactive

                  com.arjuna.ats.internal.jta.transaction.arjunacore.inactive The transaction is not active!

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

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

                  at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)

                After that i checked data, and i found

                • insertMethod1() was rolled back
                • insertMethod2() was rolled back
                • insertMethod3() was not rolled back

                 

                I just don't understand why there are only 2 of them get rolled back but the 3rd one. They were in one transaction, isn't it?

                In fact i'm also not familiar with JTA, if there was misunderstanding, please correct me :-)

                • 5. Re: When transaction timeout, rollback didn't work as expected.
                  tomjenkinson

                  As the transaction is already rolled back by the time insertMethod3 is called:

                   

                  private void insertMethod3() {

                       execute insert statement;

                  }

                   

                  As the transaction is rolledback by this point, this call is made in a separate (JDBC local) transaction, hence why it commits, i.e. the transaction manager isn't involved in that part of the code execution.

                   

                  If you were to check, the insertMethod1 and insertMethod2 would have rolled back before insertMethod3 was even called, I would say you should follow the guidance on https://community.jboss.org/wiki/TxMultipleThreads regarding transaction timeout

                   

                  When you say, no annotations, I assume you have at least some annotation (or XML) to mark this as an EJB?

                  • 6. Re: When transaction timeout, rollback didn't work as expected.
                    mmusgrov

                    Yes I think Tom has identified what's going. To summarize:

                     

                    The private EJB methods do not have any default transaction type associated but public void totalMethod() does.

                     

                    So on entry to totalMethod the container starts a transaction. In insertMethod2() the transaction times out. Therefore when insertMethod3 is called there is no transction and the inserts are done inside a local transaction (ie independant from the one that the container started). Hence, the inserts done in the context of the container managed transaction are rolled back because of the timeout, but the inserts done in the local transaction (in the third method) are committed ok.

                     

                    I would advise that you set the transaction type on all three methods, then when insertMethod2 returns, an exception should be thrown (because of the timeout) and therefore insertMethod3 will never get called (and you won't end up with partial inserts).

                    • 7. Re: When transaction timeout, rollback didn't work as expected.
                      tomjenkinson

                      Thanks Mike, I was considering suggesting that (i.e. to mark as transaction mandatory on each of the three update methods) but I am not 100% that that would be enough?

                       

                      Lets say the transaction is still active imediately prior to calling update3 and update3 is marked as mandatory for a transactions, the EJB is happy therefore to allow the call to proceed.

                       

                      Lets then say that imediately after entry into update3() the timeout happens but before any SQL is executed. My question is, would the SQL of update3 be ran in its own transaction as, by the time it does the SQL insert, the original transaction is now timed out?

                       

                      Here is a timeline assuming updateX is marked as mandatory:

                       

                      begin

                       

                      call update1

                      update1 marked as mandatory so check if transaction exists

                      inside update1

                      sql insert1

                      leaving update1

                       

                      call update2

                      update2 marked as mandatory so check if transaction exists

                      inside update2

                      sql insert2

                      leaving update2

                       

                      call update3

                      update3 marked as mandatory so check if transaction exists

                      inside update3

                      <TIMEOUT NOW, this rolls back the transaction>

                      sql insert3

                       

                      Question is, is insert3 done in a local transaction or can the container detect the issue and therefore insert3 fails?

                       

                      Tom

                      • 8. Re: When transaction timeout, rollback didn't work as expected.
                        redfoxlee

                        When you say, no annotations, I assume you have at least some annotation (or XML) to mark this as an EJB?

                        Sorry, my fault. I mean i'm not using any annotations explicity to mark method transactional. (i.e. @TransactionaAttribute)

                        • 9. Re: When transaction timeout, rollback didn't work as expected.
                          redfoxlee

                          Hi, mike.

                          So on entry to totalMethod the container starts a transaction. In insertMethod2() the transaction times out. Therefore when insertMethod3 is called there is no transction and the inserts are done inside a local transaction (ie independant from the one that the container started). Hence, the inserts done in the context of the container managed transaction are rolled back because of the timeout, but the inserts done in the local transaction (in the third method) are committed ok.

                          With your summary, all about this are making sense to me now.  Thank you and tom, both of you!

                           

                          I would advise that you set the transaction type on all three methods, then when insertMethod2 returns, an exception should be thrown (because of the timeout) and therefore insertMethod3 will never get called (and you won't end up with partial inserts).

                          You mean annotate them by @TransactionAttribute?

                          • 10. Re: When transaction timeout, rollback didn't work as expected.
                            tomjenkinson

                            redfoxlee wrote:

                             

                            When you say, no annotations, I assume you have at least some annotation (or XML) to mark this as an EJB?

                            Sorry, my fault. I mean i'm not using any annotations explicity to mark method transactional. (i.e. @TransactionaAttribute)

                             

                            I assumed as much, that means each method will get the default transactional attribute: REQUIRED.

                             

                            Making each one MANDATORY will significantly reduce the likelihood of this error happening.

                             

                            You probably still want to know what happens if the transaction is active as it enters the method, but times out immediately after entering the method.

                             

                            Also, it definitely sounds like you need to increase the timeout if this is expected to happen a lot!

                            • 11. Re: When transaction timeout, rollback didn't work as expected.
                              redfoxlee

                              You mean like this ?

                              @TransactionAttribute(TransactionAttributeType.MANDATOY)
                              insertMethod1();


                              @TransactionAttribute(TransactionAttributeType.MANDATOY)
                              insertMethod2();

                              @TransactionAttribute(TransactionAttributeType.MANDATOY)
                              insertMethod3();

                              // This one just as usuall way 
                              totalMethod() {
                                    insertMethod1();
                                    insertMethod2();
                                    insertMethod3();
                              }

                              so that insertMethods() become part of totalMethod, one fails others will not even get called? And we don't have to worry about after timeout rest part of them will be performed, right? With no extra exception handling?

                              • 12. Re: When transaction timeout, rollback didn't work as expected.
                                tomjenkinson

                                Hi redfoxlee,

                                 

                                Two points:

                                 

                                1. I am not certain but those methods might have to be public for that to work

                                2. Please note my caveat about being unsure what happens in the following scenario:

                                 

                                call update3

                                update3 marked as mandatory so check if transaction exists

                                inside update3

                                <TIMEOUT NOW, this rolls back the transaction>

                                sql insert3

                                 

                                I am still not 100% sure what context the sql insert3 would be done in or whether it would fail. Admittedly this is a very small window of opportunity compared to the current scenario but it is still worth considering.

                                 

                                It sounds like you should be making that change anyway to be fair as that describes clearer what you are attempting to do with these updates.

                                 

                                Tom

                                • 13. Re: When transaction timeout, rollback didn't work as expected.
                                  tomjenkinson

                                  Ivo pointed me to this:

                                   

                                  http://www.javahelp.info/2009/11/01/using-transactionattribute-in-submethods-on-same-ejb3-beans/

                                   

                                  The salient point being:

                                   

                                  The reason is that the @TransactionAttribute-annotations will only be honored, if you call the method via a business interface. So the first solutions is to inject the bean itself and call the submethod via the injected bean.

                                   

                                  I have to re-iterate, this will only minimize the potential case of the transaction not being active

                                  • 14. Re: When transaction timeout, rollback didn't work as expected.
                                    mmusgrov

                                    Would it be possible for you to include the AS log for this problem.

                                     

                                    Also is it feasible for you to test whether you get the same behaviour on one of the more recent versions of the app server.

                                    1 2 Previous Next