Individual transactions also have timestamp state. These timestamps are queried using WT_SESSION::query_timestamp but are potentially set in a variety of methods to allow configuration at various stages of the transaction: WT_SESSION::begin_transaction, WT_SESSION::commit_transaction, WT_SESSION::prepare_transaction and WT_SESSION::timestamp_transaction.
Applications will focus on two transactional timestamps: the read timestamp and the commit timestamp. Without a read timestamp, reads will occur based on the transaction's snapshot, which will include the latest values as of when the snapshot is taken. With a read timestamp, reads will occur as of the specified time.
The transaction's commit timestamp is the time at which the transaction takes effect. This is the time at which other transactions, with appropriately set read timestamps, will see the transaction's writes instead of any previous value. Applications can also set commit timestamps on a per-update basis in a single transaction, in which case the commit timestamp is the time of the visibility of the effected updates.
Updating a key without a commit timestamp creates a value that has "always existed" and is visible regardless of timestamp. This makes sense when loading initial data into an object or in applications wishing to clear historic values, but once timestamps are used to update a particular value, subsequent updates will likely also use a commit timestamp. Similarly, because implicit transactions have no associated timestamp, implicit transactions are generally only useful until timestamps have been used to update a table. Updating a key with a commit timestamp and then subsequently updating it without a commit timestamp will discard all prior historical values, and future reads will read the new value regardless of read timestamp. In other words, readers with already acquired snapshots will see prior historical values based on their timestamps. Readers acquiring a snapshot after the commit of the update without a timestamp will not see prior historical values regardless of their read timestamps.
By default, WiredTiger requires timestamps be used in "ordered" mode: updates to a table can be made either with and without a commit timestamp, but once a commit timestamp is used to update a key, all future updates to the key will require a commit timestamp. Further, each update to a key must have a commit timestamp at or after any previous update.
These requirements can be changed on a per-table basis to require no updates to a table have timestamps, or that updates without timestamps be permitted even when a key has already been updated using a timestamp. Using timestamps that are before previously applied timestamps is never permitted.
Enforcing application timestamp behavior can be challenging for application writers. WiredTiger includes diagnostic support for many common restrictions; see Using diagnostic configurations to enforce timestamp usage.
The following table lists the timestamps that can be queried using WT_SESSION::query_timestamp:
Timestamp | Description |
---|---|
commit | the transaction's most recently set commit timestamp |
first_commit | the transaction's first/earliest set commit timestamp |
prepare | the timestamp used to prepare the transaction |
read | the timestamp at which the transaction is reading |
In all cases, WT_NOTFOUND is returned if there is no matching timestamp.
The following table lists the transaction's timestamps and behaviors that can be set when the transaction begins, using WT_SESSION::begin_transaction:
Timestamp | Constraint | Description |
---|---|---|
read_timestamp | >= oldest | the transaction's read timestamp, see Setting the transaction's read timestamp for details |
roundup_timestamps | None | boolean setting for timestamp auto-adjustments, see Automatic prepare timestamp rounding and Rounding up the read timestamp for details |
The following table lists the transaction's timestamps that can be set when the transaction commits, using WT_SESSION::commit_transaction:
Timestamp | Constraint | Description |
---|---|---|
commit_timestamp | > stable and >= prepare and >= any system read timestamp | the transaction's commit timestamp, see Setting the transaction's commit timestamp for details |
durable_timestamp | >= commit | the transaction's durable timestamp, only applicable to prepared transactions, see Using transaction prepare with timestamps for details |
The following table lists the transaction's timestamps that can be set when the transaction is prepared, using WT_SESSION::prepare_transaction:
Timestamp | Constraint | Description |
---|---|---|
prepare_timestamp | > stable and >= any system read timestamp | the transaction's prepare timestamp, see Using transaction prepare with timestamps for details |
The following table lists the transaction's timestamps that can be set at other points in the transaction's lifetime, using WT_SESSION::timestamp_transaction:
Timestamp | Constraint | Description |
---|---|---|
commit_timestamp | > stable and >= prepare and >= any system read timestamp | the transaction's commit timestamp, see Setting the transaction's commit timestamp for details |
durable_timestamp | >= commit | the transaction's durable timestamp, only applicable to prepared transactions, see Using transaction prepare with timestamps for details |
prepare_timestamp | > stable and >= any system read timestamp | the transaction's prepare timestamp, see Using transaction prepare with timestamps for details |
read_timestamp | >= oldest | the transaction's read timestamp, see Setting the transaction's read timestamp for details |
The commit
time is the time at which other transactions with appropriately set read timestamps will see the transaction's updates.
The commit timestamp can be set at any point in the transaction's lifecycle. For prepared transactions, however, it can only be set after the transaction has been successfully prepared.
Applications using timestamps usually specify a timestamp to the WT_SESSION::commit_transaction method to set the commit time for all updates in the transaction.
Applications may set different commit timestamps for different updates in a single transaction by calling WT_SESSION::timestamp_transaction repeatedly to set a new commit timestamp between updates in the transaction. Each new commit timestamp is applied to any subsequent updates. This gives applications the ability to commit updates that take effect at different times; that is, it is possible to create chains of updates where each update appears at a different time to readers. For transactions that set multiple commit timestamps, the first commit timestamp set is also required to be the earliest: the second and subsequent commit timestamps may not be earlier than the first commit timestamp. This feature is not compatible with prepared transactions, which must use only a single commit timestamp.
For prepared transactions, the commit timestamp must not be before the prepare timestamp. Otherwise, the commit timestamp must be after the stable timestamp.
Setting the transaction's read timestamp causes a transaction to not see any commits with a newer timestamp. (Updates may still conflict with commits having a newer timestamp, of course.),
The read timestamp may be set to any time equal to or after the system's oldest
timestamp.
This restriction is enforced and applications can rely on an error return to detect attempts to set the read timestamp older than the oldest
timestamp.
The read timestamp may only be set once in the lifetime of a transaction.