Topics

Suggestion for a 2PC optimisation


Michael Musgrove
 

We had a suggestion on our Narayana forum (https://developer.jboss.org/thread/277738) regarding an enhancement that avoids the prepare phase if only one resource actually made any changes. The problem is that during prepare processing - while we may know that in a given specific case only one resource will return XA_OK from prepare (the rest returning XA_RDONLY), it's only a matter of chance as to whether that particular resource will end up last in the list (and thus be eligible for 1PC optimization). 
 
The suggestion is to indicate, ahead of time, that the transaction branch did not do any work.
 
The end call would have been an ideal opportunity to report this information. I would like to ask if, during the writing of the XA spec, why XA_RDONLY was not considered to be a valid return value from the xa_end() call.


 

I worked on the original XA prototype and wrote the draft XA specification that was submitted to X/Open.

The goal of xa_start/xa_end is to associate a thread with a transaction/resource.  There can be many such associations for a global transaction/resource on different threads within a process, on different processes, and different machines.  It's not just a simple start/end, we are done, and we have the answer based on a single return value.

We extended that goal only for the rollback case, where a rollback from any association on the transaction indcates that the entire transaction will be rolled back.   We don't need to worry about the return values from other associations with the transaction.  This optimization allows for the TM to short-cut even starting subsequent associations for the same transaction, propagating communications associated with the transaction, etc.

Extending the goal to provide read-only information is not so straight forward.  The fact that one association returns read-only does not imply that we can take any action other than keeping track of that piece of information because there could be many other such associations for the transaction/resource that are not read-only.  So the read-only information would need to be tracked, ignored if any related association returns OK, combined across all associations everywhere, and can only be acted on in the first phase of commit when we know there will be no further associations allowed. If all associations for the transaction/reesource are read-only, then 1PC can be used.  I don't believe that we considered returning read-only from xa_end.

Adding this feature now would be complicated because it impacts both the RM and the TM.  Most if not all changes to the JTA specification impact only the TM.   Changing the RM can cause a behavior in the unupdated TM that is not expected.  I can see the code that was written 30 years ago with a switch on the return value from xa_end and it doesn't handle XA_RDONLY (unknown return values are treated as an error that causes the transaction to fail).


 

On Fri, Apr 27, 2018 at 1:25 PM, Stephen Felts <stephen.felts@oracle.com> wrote:
I worked on the original XA prototype and wrote the draft XA specification
that was submitted to X/Open.

The goal of xa_start/xa_end is to associate a thread with a
transaction/resource. There can be many such associations for a global
transaction/resource on different threads within a process, on different
processes, and different machines. It's not just a simple start/end, we are
done, and we have the answer based on a single return value.
Understood.

We extended that goal only for the rollback case, where a rollback from any
association on the transaction indcates that the entire transaction will be
rolled back. We don't need to worry about the return values from other
associations with the transaction. This optimization allows for the TM to
short-cut even starting subsequent associations for the same transaction,
propagating communications associated with the transaction, etc.

Extending the goal to provide read-only information is not so straight
forward. The fact that one association returns read-only does not imply
that we can take any action other than keeping track of that piece of
information because there could be many other such associations for the
transaction/resource that are not read-only. So the read-only information
would need to be tracked, ignored if any related association returns OK,
combined across all associations everywhere, and can only be acted on in the
first phase of commit when we know there will be no further associations
allowed. If all associations for the transaction/reesource are read-only,
then 1PC can be used. I don't believe that we considered returning
read-only from xa_end.

Adding this feature now would be complicated because it impacts both the RM
and the TM. Most if not all changes to the JTA specification impact only
the TM. Changing the RM can cause a behavior in the unupdated TM that is
not expected. I can see the code that was written 30 years ago with a
switch on the return value from xa_end and it doesn't handle XA_RDONLY
(unknown return values are treated as an error that causes the transaction
to fail).
Since breaking compatibility is a non-starter, what I had proposed was
an enhancement to XAResource to add a new default method:

/**
* Ends the work performed [...rest of existing spec language...].
* The return value of this method is only a hint; the transaction
manager is free to ignore it.
* [...]
* @return XA_RDONLY if the resource instance did no work during its
association; XA_OK if work was done or it cannot be determined.
*/
default int endWithResult(Xid xid, int flags) {
end(xid, flags);
return XA_OK;
}

The possible return values are XA_RDONLY and XA_OK. If the TM does
not support this method, it does not call it (as it is only a hint).
If the RM does not support it, it does not override it. Compatibility
(forward and backward) is in this way guaranteed, since the method
does not mandate new behavior on either part.

You are correct that a TM supporting this enhancement would have to
record the value returned for each XAResource instance, and it can
only consider the RM to be optimizable if all of its XAResource
instances returned XA_RDONLY. But as the TM would not be required to
do so, I don't think that it constitutes undue complication to the
specification, even without consideration for the benefit of this
enhancement. Once all pre-commit synchronizations are complete, the
transaction can be prepared as normal, with the only change of
ordering XA_RDONLY resources before XA_OK resources. This way, no new
error states are created, since even an inconsistent return between
the endWithResult call(s) and the prepare call would not cause
incorrect operation (the return is only a hint after all).

--
- DML

On Fri, Apr 27, 2018 at 1:25 PM, Stephen Felts <stephen.felts@oracle.com> wrote:
I worked on the original XA prototype and wrote the draft XA specification
that was submitted to X/Open.

The goal of xa_start/xa_end is to associate a thread with a
transaction/resource. There can be many such associations for a global
transaction/resource on different threads within a process, on different
processes, and different machines. It's not just a simple start/end, we are
done, and we have the answer based on a single return value.

We extended that goal only for the rollback case, where a rollback from any
association on the transaction indcates that the entire transaction will be
rolled back. We don't need to worry about the return values from other
associations with the transaction. This optimization allows for the TM to
short-cut even starting subsequent associations for the same transaction,
propagating communications associated with the transaction, etc.

Extending the goal to provide read-only information is not so straight
forward. The fact that one association returns read-only does not imply
that we can take any action other than keeping track of that piece of
information because there could be many other such associations for the
transaction/resource that are not read-only. So the read-only information
would need to be tracked, ignored if any related association returns OK,
combined across all associations everywhere, and can only be acted on in the
first phase of commit when we know there will be no further associations
allowed. If all associations for the transaction/reesource are read-only,
then 1PC can be used. I don't believe that we considered returning
read-only from xa_end.

Adding this feature now would be complicated because it impacts both the RM
and the TM. Most if not all changes to the JTA specification impact only
the TM. Changing the RM can cause a behavior in the unupdated TM that is
not expected. I can see the code that was written 30 years ago with a
switch on the return value from xa_end and it doesn't handle XA_RDONLY
(unknown return values are treated as an error that causes the transaction
to fail).



--
- DML