Atomikos Forum

All feedback will be investigated, but priority support, confidential support, and product priority updates are reserved for customers. Interested in becoming a customer? Subscribe here...

Only registered users can post (registration is free). Problems registering? Send an email to support@atomikos.com to get help.


Local heuristic termination of coordinator with state COMMITTING

If there were no any transactional operations in a transaction, then after restart of the transaction manager a lot of messages appears:

0    [main] WARN  atomikos  - Local heuristic termination of coordinator atomikos-empty-tx0000100005 with state COMMITTING
0    [main] WARN  atomikos  - Local heuristic termination of coordinator atomikos-empty-tx0000100005 with state COMMITTING
0    [main] WARN  atomikos  - Local heuristic termination of coordinator atomikos-empty-tx0000200005 with state COMMITTING
0    [main] WARN  atomikos  - Local heuristic termination of coordinator atomikos-empty-tx0000200005 with state COMMITTING
...

Is it possible not to keep information about empty transactions? Our application is expected to work for months and several transactional methods are expected to have no action because of internal checks.
We know that we could move these checks out of the transaction method, but it breaks information hiding principle.

Here is an example application, which demonstrates our problem:

https://docs.google.com/open?id=0B5bRA7IIC9RgNzUxZDFiODYtZTVhYi00YTdiLTkxYzUtMTEwNTM5MmRkOWM5

On the second call of setUp() method Atomikos prints messages like above.

Is it possible to setup Atomikos not to save information about empty transactions?

Is it a bug of transaction manager to try to recover what shouldn't be recovered at all?

Thanks in advance.
DmitriiAfanasyev Send private email
Tuesday, January 17, 2012
 
 
Hi,

This is because you have destroy-method="shutdownForce" in your Spring config. This blows essentially ignores any pending transactions and may lead to log/recovery issues like these.

The easiest thing would be to change this in your config to:

destroy-method="shutdownWait"

Let me also check if we can avoid this warning for empty transactions upon recovery - that will be for a future release.

HTH
Guy Pardon Send private email
Thursday, January 19, 2012
 
 
Hi,

I am involved in porting some web applications from WebLogic to Tomcat. As part of this exercise, we are evaluating TransactionEssentials 3.7.0. We are seeing the same warnings as Dmitrii, the original poster. These transactions are NOT pending transactions (and we are using shutdownWait rather than shutdownForce). They are transactions which terminated successfully and do not need restoring.

I have debugged this and found that all the transactions reported in this way during recovery at startup had previously commited and terminated successfully. In our case, a servlet filter requests a new transaction at the start of any request to a Struts action and commits the transaction at the end of the request. Quite often, the transaction will not be required to do anything. This may be less than optimal but we are not looking to address this issue at the moment. What the transactions have in common is that they either had zero participants (I suspect that this is also what Dmitrii was seeing) or a single read-only participant.

Each transaction results in a pair of warnings during recovery. The warnings are output while the SystemLogImage instances from the log file are deserialized. The first of each pair was written at the start of commit when the CoordinatorImpl had an ActiveStateHandler and a state of COMMITTING. The second SystemLogImage of each pair was flushed to the log when the transaction was terminated. The serialized Coordinator impl is a copy of the first (ActiveStateHandler/COMMITTING) but with a forgettable flag equal to true. This indicates that the transaction terminated.

After the SystemLogImages have all been deserialized they are added to a hashtable in sequence. When a forgettable image is found, the entry is removed from the hashtable because this is not a transaction which needs to be recovered. In our application, after this stage, we have an empty hashtable meaning that there are no transactions to recover. This is correct. However, we already have a bunch of worrying warnings in the log. As far as I can tell so far, the only problems this causes are the undermining of confidence due to the warnings (not to be underestimated!) and also possibly the inefficiency of writing unneccessary information to the transaction log and causing checkpoints to happen more frequently than is needed.

Is this possibly a defect? Should any state ever be written to the logs for transactions with zero participants or a single read-only participant? I think the significant method here is CoordinatorImpl's terminate() method. It looks like this:

    protected void terminate ( boolean commit ) throws HeurRollbackException,
            HeurMixedException, SysException, java.lang.SecurityException,
            HeurCommitException, HeurHazardException, RollbackException,
            IllegalStateException

    {
        // FOLLOWING IN COMMENTS: REMOVED FOR COMPENSATION!
        // if ( coordinator_ != null )
        // throw new java.lang.SecurityException ("Not root");

            synchronized ( fsm_ ) {
                        if ( commit ) {
                                    if ( participants_.size () <= 1 ) {
                                                // System.err.println ( "CoordinatorImp: only one participant!"
                                                // );
                                                commit ( true );
                                    } else {
                                                int prepareResult = prepare ();
                                                // make sure to only do commit if NOT read only
                                                if ( prepareResult != Participant.READ_ONLY )
                                                            commit ( false );

                                                // FOLLOWING WAS REPLACED BECAUSE IT CAUSES READ-ONLY
                                                // TRANSACTIONS TO ROLLBACK!
                                                // prepare();
                                                // commit ( false );
                                    }
                        } else {
                                    rollback ();
                        }

            }
    }
           
The logs are written when commit(true) is called. I notice that commit is never called for transactions with multiple read-only participants. Should the same be true when there is a lone read-only participant (or no participants at all)? This is certainly what prompts the entries to be written to the transaction log.

I experimented with changes to the code. I changed the second if statement to only call commit(true) if there is exactly one participant which is not read-only. This had the desired effect of not writing anything to the transaaction log. But when I shutdown tomcat, atomikos told me it was waiting for pending transaction to complete. Because the transactions hadn't terminated, their coordinators were still hanging around.

So I looked for a way to terminate the transactions without calling commit or rollback. I may be way off the mark but prepare() had the desired effect. But maybe it also does extras which make it inefficient and there's a better way to terminate. This modified code seems to be doing the trick for me. It may of course be horrendously wrong! Could you please take a look at this and consider whether Dmitrii and I have run into a bug and offer advice.

                        synchronized ( fsm_ ) {
                        if ( commit ) {
                                    int prepareResult = prepare ();
                                    if (participants_.size() > 0 && prepareResult != Participant.READ_ONLY) {
                                                // make sure to only do commit if NOT read only
                                                            boolean onePhase = participants_.size() == 1;
                                                            commit ( onePhase );
                                    }
                        } else {
                                    rollback ();
                        }

            }
                       
Regards,
Alkesh Rathod Send private email
Thursday, February 09, 2012
 
 
Hi,

Thanks for the detailed feedback!

Your suggestion forces full two-phase commit in all cases, so it is not yet optimal IMHO.

This does seem like some bug in our core, but before we touch that we want to analyze the details a bit more. For now you could try your code changes, but I would like to come up with something better...

Thanks!
Guy Pardon Send private email
Thursday, February 09, 2012
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz