public interface ITransactionService extends ITimestampService
An interface for managing transaction life cycles.
The underlying concurrency control mechanism is Multi-Version Concurrency
Control (MVCC). There are no "write locks" per say. Instead, a transaction
reads from a historical commit point identified by its assigned start time
(abs(transactionIdentifier) is a timestamp which identifies the commit point)
and writes on an isolated write set visible only to that transaction. When a
read-write transaction commits, its write set is validated against the then
current committed state of the database. If validation succeeds, the isolated
write set is merged down onto the database. Otherwise the transaction is
aborted and its write set is discarded. (It is possible to register an index
IConflictResolver in order to present the application with an
opportunity to validate write-write conflicts using state-based techniques,
i.e., by looking at the records and timestamps and making an informed
A transaction imposes "read locks" on the resources required for the historical state of the database from which that transaction is reading (both read-only and read-write transactions impose read locks). Those resources will not be released until the transaction is complete or aborted. The transaction manager coordinates the release of resources by advancing the global release time - the earliest commit time from which a transaction may read. Under dire circumstances (disk shortage) the transaction manager MAY choose to abort transactions and advance the release time in order to permit the release of locked resources and the reclamation of their space on local disk.
When deployed as a distributed database there will be a centralized service
implementing this interface and clients will discover and talk with that
service. The centralized service in turn will coordinate the distributed
transactions with the various
IDataServices using their local
implementations of this same interface. The centralized transaction service
SHOULD invoke the corresponding methods on a
IDataService IFF it
knows that the
IDataService is buffering writes for the transaction.
Both read-only and read-write transactions assert global read locks on the resources required for that historical state of the database corresponding to their start time. Those read locks are released when the transaction completes. Periodically the transaction manager will advance the release time, rendering views of earlier states of the database unavailable.
The transaction identifier codes the transaction start time. The transaction start time is chosen from among those distinct timestamps available between the specified commit time and the next commit time on the database. Successive read-write transactions must be assigned transaction identifiers whose absolute value is strictly increasing - this requirement is introduced by the MVCC protocol.
The sign of the transaction identifier indicates whether the transaction is read-only (positive) or read-write (negative). Read-only transaction identifiers may be directly used as commit times when reading on a local store. Read-write transaction identifiers must have their sign bit cleared in order to read from their ground state (the commit point corresponding to their transaction start time) but the unmodified transaction identifier is used to access their mutable view (the view comprised of the write set of the transaction super imposed on the ground state such that writes, overwrites, and deletes are visible in the view).
The symbolic value
ITx.READ_COMMITTED and any
MAY be used to perform a lightweight read-only operations either on a local
data service or on the distributed database without coordination with the
ITransactionService, but resources MAY be released at any time since
no read "locks" have been declared. While a read-write transaction may be
readily identified by the sign associated with the transaction identifier,
you CAN NOT differentiate between a read-only transaction (with read-locks)
and a lightweight read on a given commit time. In practice, it is only the
transaction manager which needs to recognize read-only transactions and then
only to constrain its assignment of distinct transaction identifiers and to
coordinate the advance of the release time as transactions end. There is no
other practical difference between read-only transactions and lightweight
reads from the perspective of either the client or the individual data
services as read-locks are managed solely through the advancement of the
release time by the transaction manager.
|Modifier and Type||Method and Description|
Request abort of the transaction write set.
Request commit of the transaction write set.
Return the last commitTime reported to the
Return the timestamp whose historical data MAY be released.
Create a new transaction.
long newTx(long timestamp) throws IOException
timestamp- The timestamp may be:
lastCommitTimewill produce a read-only transaction that is reading on the
lastCommitTimewith snapshot isolation (new writes will not become visible in the view). This is basically the same behavior as specifying
ITx.READ_COMMITTED. While perhaps counter-intuitive, this behavior is preferred to throwing an exception when a user attempts to read from a commit time GT the most recent commit point.).
ITx.READ_COMMITTEDto obtain a read-historical transaction reading from the most recently committed state of the database. The transaction will be assigned a start time corresponding to the most recent commit point of the database and will be a fully isolated read-only view of the state of the database as of that start time. (This is an atomic shorthand for newTx(getLastCommitTime())).
ITx.UNISOLATEDfor a read-write transaction.
IllegalStateException- if the requested timestamp is for a commit point that is no longer preserved by the database (the resources for that commit point have been released).
IOException- RMI errors.
long commit(long tx) throws ValidationError, IOException
The commit of a transaction with a write set on a single
IDataService does not require either
or other transactions to wait. The latency for such commits is directly
related to the size of the transaction write set.
However, the commit of a transaction with writes on more than one
IDataService requires a distributed commit protocol. The
distributed commit protocol forces ALL tasks writing on those
IDataServices to wait until the transaction is complete. This is
necessary in order to obtain a global commit point that corresponds to
the atomic commit state of the transaction (without this we would not
have the Atomic property for distributed transaction commits).
tx- The transaction identifier.
ValidationError- if the transaction could not be validated.
IllegalStateException- if tx is not an active transaction.
IOException- RMI errors.
void abort(long tx) throws IOException
void notifyCommit(long commitTime) throws IOException
ITransactionServicethat a commit has been performed with the given timestamp (which it assigned) and that it should update its lastCommitTime iff the given commitTime is GT its current lastCommitTime.
commitTime- The commit time.
long getLastCommitTime() throws IOException
long getReleaseTime() throws IOException
now-minReleaseAgeand is updated whenever the earliest running transaction terminates. This value is monotonically increasing. It will always be LT the last non-zero last commit time. It will never be negative. It MAY be ZERO (0L) and will be ZERO (0L) on startup (unless explicitly set by the database to the last known commit time).
The returned values is used to identify the most recent commit point LTE the releaseTime. This is the earliest commit point on whose data MAY be released. (Consequently, the first commit point GT the releaseTime is the earliest visible commit point.)
Copyright © 2006-2014 SYSTAP, LLC. All Rights Reserved.