Introduction
AllegroGraph now supports two-phase commits when managed by an external transaction coordinator such as the Atomikos Transaction Essentials Transaction Manager (see https://www.atomikos.com/Main/TransactionsEssentials).
Two-phase commit concepts
Wikipedia defines the two-phase commit protocol as
In transaction processing, databases, and computer networking, the
two-phase commit protocol (2PC) is a type of atomic commitment
protocol (ACP). It is a distributed algorithm that coordinates all
the processes that participate in a distributed atomic transaction
on whether to commit or abort (roll back) the transaction (it is a
specialized type of consensus protocol).
When used with an external transaction coordinator, AllegroGraph can ensure that commits in specified repositories in AllegroGraph (in one or more running servers) and in external non-AllegroGraph databases will all happen or will all fail (be rolled back).
Transaction managers are supplied by companies other than Franz Inc. (the supplier of AllegroGraph). One such supplier is Atomikos, who supply the Atomikos Transaction Essentials transaction manager. This is the transaction manager with which AllegroGraph's Two-phase Commit utility is certified.
Two-phase committing has a number of well-known disadvantages, perhaps the most important of which is that it is a blocking protocol: once the commit procedure is started, none of the participants can do any further commits until all have either indicated their readiness to commit and the commit order has gone out from the transaction coordinator or the transaction coordinator calls for a roll back and the roll back is finished. If any participant (or, after sending the "ready to commit?" message, the transaction coordinator) fails or becomes unavailable, further commits on the affected AllegroGraph repositories are blocked until the prepared commit is completed or rolled back. (Non-AllegroGraph participant databases are presumably similarly restricted. See their documentation for more information.)
Because of this blocking potential, users need special permission to initiate a 2PC. See the Managing Users document, particularly the section on User Permissions and Access Controls for more information on user permissions and how they are set. Users with superuser privileges can always initiate a 2PC.
Two-phase Commit Example
There is a complete example using two-phase commit and the Atomikos Transaction Essentials transaction manager among the tutorials included with the AllegroGraph Java client download.
The AllegroGraph Java client is not part of the regular AllegroGraph download. Go to the AllegroGraph Java client GitHub page and follow the instructions there.
Once downloaded, you will find the two-phase commit example in the tutorials/2pc/ directory.
To run the tutorial start an AllegroGraph 7.3.1 server and open a shell in tutorials/2pc/.
The example reads the host, port, user, and password from the environment variables AGRAPH_HOST, AGRAPH_PORT, AGRAPH_USER, and AGRAPH_PASS. If any variable is unset, defaults (in order "localhost", "10035", "test" and "xyzzy") are used. Set the appropriate environment variables as necessary. The user must either be a superuser or have 2pc privileges (see the General permissions section of the Managing Users document for details on user permissions and privleges).
Now perform the following steps:
- Compile the example:
- Run the example:
mvn compile
mvn exec:java -Dexec.mainClass="com.franz.tutorials.tpc.TwoPhaseCommitExample"
Notes about the test program:
The test program starts the Apache Derby database product.
The test program creates an AllegroGraph repository and a Derby database.
The AllegroGraph repository is placed in the
java-catalog
catalog and is namedtest-2pc
. Thejava-catalog
must exist in AllegroGraph and so must be defined in the agraph.cfg file prior to running the example (see Server Configuration and Control for information on specifying catalogs). If thetest-2pc
repo exists, it will be overwritten.The Derby database is also named
test-2pc
.Then com.atomikos.icatch.config.Configuration.addResource() is called twice to notify the transaction manager that these resources will be involved in two phase transactions.
An instance of the transaction manager is created by calling UserTransactionManager(). It is initialized by invoking its init() method. Then doSampleTransaction() is called. doSampleTransaction gets a connection to each resource. Then we ask the transaction manager to begin a new distributed transaction.
The participants in the distributed transaction are registered by calling enlistResource() on the transaction object with the result of calling getXAResource() on each of the connections. Then we do normal operations against each of the repository connections (adding one triple to the AllegroGraph repo and a record into the Derby database).
Then we invoke the tm.commit() method of the transaction manager object. The transaction manager performs the two phase commit operation as a result.
We could have also called tm.rollback() to cancel the transaction. This would roll back the work on all participants.