Handling Commit Operations
There are two types of commit operations: single-phase commit and multi-phase commit. A single-phase commit operation consists of a single notification that resource managers must respond to, while a multi-phase commit operation includes additional notifications for preparation steps.
A single-phase commit operation is simpler to implement. It is appropriate for transaction processing systems (TPSs) that have one of the following characteristics:
A single resource manager.
Multiple resource managers, all but one of which are read-only and do not participate in the commit operation.
A multi-phase commit operation is necessary if multiple resource managers participate in the commit operation.
Single-Phase Commit Operations
If you want your TPS to support single-phase commit operations, one (and only one) resource manager must register to receive TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT notifications for its enlistments. All other resource managers must be read-only.
A TPS that includes a superior transaction manager cannot use single-phase commit.
If a resource manager has registered to receive TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT notifications, KTM sends this kind of notification when a transactional client calls ZwCommitTransaction.
When the resource manager receives a TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT notification for a transaction, it can either commit the transaction or reject single-phase commit.
To commit the transaction, the resource manager must do the following:
Flush any data that it is holding in a non-permanent cache (in-memory storage), such as the CLFS marshalling area for a CLFS log stream.
The resource manager must move the data from the cache to a durable storage medium. For example, a resource manager that is using CLFS can call ClfsFlushBuffers.
Make all data changes permanent and public (that is, visible outside the resource manager's scope).
Call ZwCommitComplete.
After calling ZwCommitComplete, the resource manager should call ZwClose to close the enlistment handle.
To reject a single-phase commit operation for the transaction, the resource manager can call ZwSinglePhaseReject. If the resource manager calls ZwSinglePhaseReject, KTM immediately changes the commit operation from single-phase to multi-phase.
If other resource managers enlist in the same transaction, they must be read-only. However, they must register to receive the TRANSACTION_NOTIFY_RM_DISCONNECTED notification, which they receive if the resource manager that is handling the single-phase commit operation closes the enlistment handle without indicating that it has committed or rolled back the transaction.
Multi-Phase Commit Operations
A multi-phase commit operation begins when one of the following events happens:
A transactional client calls ZwCommitTransaction, and no resource managers have registered to receive TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT notifications.
A resource manager calls ZwSinglePhaseReject after it has received a TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT notification.
A superior transaction manager calls ZwPrePrepareEnlistment.
Multi-phase commit operations consist of three sequential phases: pre-prepare, prepare, and commit.
Pre-Prepare Phase
The pre-prepare phase (also known as phase zero) of the commit operation begins when KTM sends a TRANSACTION_NOTIFY_PREPREPARE notification to all resource managers. KTM sends this notification if no resource managers support a single-phase commit operation for the transaction, or if a superior transaction manager calls ZwPrePrepareEnlistment.
When each resource manager receives the TRANSACTION_NOTIFY_PREPREPARE notification, it must do the following:
Flush any data that it is holding in a non-permanent cache (in-memory storage), such as the CLFS marshalling area for a CLFS log stream.
The resource manager must move the data from the cache to a durable storage medium. For example, a resource manager that is using CLFS can call ClfsFlushBuffers.
Call ZwPrePrepareComplete.
After a resource manager has called ZwPreprepareComplete, it can continue to receive and service client requests. But the resource manager must treat all data modifications as cache pass-through operations that are immediately written to a durable storage medium.
If a resource manager encounters an error while it is processing a TRANSACTION_NOTIFY_PREPREPARE notification, it should call ZwRollbackEnlistment to roll back the transaction.
Prepare Phase
The prepare phase (also known as phase one) of the commit operation begins when KTM sends a TRANSACTION_NOTIFY_PREPARE notification to all resource managers. KTM sends this notification after TRANSACTION_NOTIFY_PREPREPARE if no resource managers support single-phase commit or if a superior transaction manager calls ZwPrepareEnlistment.
When each resource manager receives the TRANSACTION_NOTIFY_PREPARE notification, it must do the following:
Stop servicing client requests and report any client subsequent requests as client errors.
Make sure that all data has been moved to durable storage.
Call ZwPrepareComplete.
If a resource manager encounters an error while it is processing a TRANSACTION_NOTIFY_PREPARE notification, it should call ZwRollbackEnlistment to roll back the transaction. However, the resource manager cannot roll back the transaction after it has called ZwPrepareComplete.
Commit Phase
The commit phase (also known as phase two) of the commit operation begins when KTM sends a TRANSACTION_NOTIFY_COMMIT notification to all resource managers. KTM sends this notification after TRANSACTION_NOTIFY_PREPARE if no resource managers support single-phase commit or if a superior transaction manager calls ZwCommitEnlistment.
When each resource manager receives the TRANSACTION_NOTIFY_COMMIT notification, it must do the following:
Make all data changes permanent and public (that is, visible to other transactions).
Typically, a resource manager makes changes permanent and public by copying the transaction's saved data from the log stream to the database's public, permanent storage. For more information about how to use log streams, see Using Log Streams with KTM.
Call ZwCommitComplete.
After the resource manager calls ZwCommitComplete, it should call ZwClose to close the enlistment handle.
If a resource manager encounters an error while it is processing a TRANSACTION_NOTIFY_COMMIT notification, it should shut itself down. The next time that the operating system reloads the resource manager, the resource manager's recovery process should restore the transaction to a state that was known to be good before the error occurred.