Using the Last Resource Gambit

The Last Resource Gambit is a technique by which a non-XA capable resource may be (relatively) safely included in a two-phase commit transaction containing multiple resources.

Importantly:

  • The transaction must be 2-phase (typically XA)
  • All but one of the resources must be XA capable
  • The Transaction Manager must support the Last Resource Gambit

How does it work?

In a two phase commit/rollback the Transaction Manager prepares all of the resources before calling commit. This means that the resources have the opportunity to do any constraint checking and buffer flushing before committing, so that they know that a commit will succeed. If any of the prepare calls fail then all of the resources (including the ones that were already prepared) may be rolled back to ensure consistency.

If a "local" (i.e. one phase) resource is included in the transaction then this model breaks. It is not possible to prepare a one-phase resource, so typically a transaction manager must "commit and hope" expecting that all other resources will commit successfully.

In the case of the Last Resource Gambit this possiblity can be reduced to near zero by including the local resource as the "last resource". Specifically all of the XA resources are prepared, and if the prepare succeeds then the local resource is committed. If the commit succeeds then all of the XA resources are committed, otherwise the XA resources are rolled back. This model means that the overall transaction is robust to resource failures.

Taking advantage of the Last Resource Gambit

The Aries XA Transaction Control service implements the last resource gambit automatically, so there is nothing that needs to be explicitly done by the client to enable the behaviour, other than to use a local resource alongside XA resources.

For example, if one database in use is HSQLDB, which does not support XA, but two others use H2, which does support XA, then the following configurations would be used:

org.apache.aries.tx.control.jdbc.xa

osgi.jdbc.driver.class=org.h2.Driver
url=jdbc:h2:tcp://192.168.1.31:12345/path/to/db

org.apache.aries.tx.control.jdbc.xa

osgi.jdbc.driver.class=org.h2.Driver
url=jdbc:h2:tcp://192.168.1.63:23456/path/to/another/db

org.apache.aries.tx.control.jpa.local

osgi.jdbc.driver.class=org.hsqldb.jdbc.JDBCDriver
url=jdbc:hsqldb:hsql://192.168.1.127/xdb"
osgi.unit.name=jpa-workspace

If these three resource providers are used in the same transaction then the Last Resource Gambit will ensure that the one-phase resource is committed reliably.