From 8a97160cf759df0afa7fda93b5ed3a400fdc854e Mon Sep 17 00:00:00 2001 From: Rich Loveland Date: Mon, 25 Aug 2025 14:12:14 -0400 Subject: [PATCH] Link from retry error reference to timestamp cache Fixes DOC-14698 NB. Changes applied to all supported versions v24.1+ --- .../architecture/life-of-a-distributed-transaction.md | 8 ++++---- src/current/v24.1/transaction-retry-error-reference.md | 4 ++-- .../architecture/life-of-a-distributed-transaction.md | 8 ++++---- src/current/v24.3/transaction-retry-error-reference.md | 4 ++-- .../architecture/life-of-a-distributed-transaction.md | 8 ++++---- src/current/v25.1/transaction-retry-error-reference.md | 4 ++-- .../architecture/life-of-a-distributed-transaction.md | 8 ++++---- src/current/v25.2/transaction-retry-error-reference.md | 4 ++-- .../architecture/life-of-a-distributed-transaction.md | 8 ++++---- src/current/v25.3/transaction-retry-error-reference.md | 4 ++-- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/current/v24.1/architecture/life-of-a-distributed-transaction.md b/src/current/v24.1/architecture/life-of-a-distributed-transaction.md index 872e3add35d..c8ca84f63a7 100644 --- a/src/current/v24.1/architecture/life-of-a-distributed-transaction.md +++ b/src/current/v24.1/architecture/life-of-a-distributed-transaction.md @@ -96,7 +96,7 @@ In this case, the `DistSender` must look up the current leaseholder using the [c ##### Success -Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the timestamp cache. +Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the [timestamp cache](#timestamp-cache). ### Timestamp cache @@ -134,7 +134,7 @@ If an operation encounters a write intent for a key, it attempts to "resolve" th - If the push succeeds, the operation continues. - If this push fails (which is the majority of the time), this transaction goes into the [`TxnWaitQueue`]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#txnwaitqueue) on this node. The incoming transaction can only continue once the blocking transaction completes (i.e., commits or aborts). - `MISSING`, the resolver consults the write intent's timestamp. - - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's timestamp cache, which will inform the transaction that its timestamp was pushed once the transaction record gets created. + - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's [timestamp cache](#timestamp-cache), which will inform the transaction that its timestamp was pushed once the transaction record gets created. - If the write intent is older than the transaction liveness threshold, the resolution exhibits the `ABORTED` behavior. Note that transaction records might be missing because we've avoided writing the record until the transaction commits. For more information, see [Transaction Layer: Transaction records]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). @@ -147,7 +147,7 @@ If the read doesn't encounter a write intent and the key-value operation is mean The leaseholder aggregates all read responses into a `BatchResponse` that will get returned to the gateway node's `DistSender`. -As we mentioned before, each read operation also updates the timestamp cache. +As we mentioned before, each read operation also updates the [timestamp cache](#timestamp-cache). ### Write Operations @@ -179,7 +179,7 @@ Now that we have followed an operation all the way down from the SQL client to t it sends an commit acknowledgment to the gateway node's `DistSender`, which was waiting for this signal (having already received the provisional acknowledgment from the leaseholder's evaluator). 1. The gateway node's `DistSender` aggregates commit acknowledgments from all of the write operations in the `BatchRequest`, as well as any values from read operations that should be returned to the client. 1. Once all operations have successfully completed (i.e., reads have returned values and write intents have been committed), the `DistSender` tries to record the transaction's success in the transaction record (which provides a durable mechanism of tracking the transaction's state), which can cause a few situations to arise: - - It checks the timestamp cache of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. + - It checks the [timestamp cache](#timestamp-cache) of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. - If the transaction is in an `ABORTED` state, the `DistSender` sends a response indicating as much, which ends up back at the SQL interface. Upon passing these checks the transaction record is either written for the first time with the `COMMITTED` state, or if it was in a `PENDING` state, it is moved to `COMMITTED`. Only at this point is the transaction considered committed. diff --git a/src/current/v24.1/transaction-retry-error-reference.md b/src/current/v24.1/transaction-retry-error-reference.md index fdb3f33e63f..28ce6e70ae2 100644 --- a/src/current/v24.1/transaction-retry-error-reference.md +++ b/src/current/v24.1/transaction-retry-error-reference.md @@ -345,7 +345,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_NEW_L **Description:** -The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the timestamp cache will not allow transaction _A_ to create a transaction record. A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. +The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. **Action:** @@ -361,7 +361,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_TIMES **Description:** -The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the timestamp cache will not allow transaction _A_ to create a transaction record. This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the timestamp cache is an in-memory cache, and has outgrown its memory limit (about 64 MB). +The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) is an in-memory cache, and has outgrown its memory limit (about 64 MB). **Action:** diff --git a/src/current/v24.3/architecture/life-of-a-distributed-transaction.md b/src/current/v24.3/architecture/life-of-a-distributed-transaction.md index 872e3add35d..c8ca84f63a7 100644 --- a/src/current/v24.3/architecture/life-of-a-distributed-transaction.md +++ b/src/current/v24.3/architecture/life-of-a-distributed-transaction.md @@ -96,7 +96,7 @@ In this case, the `DistSender` must look up the current leaseholder using the [c ##### Success -Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the timestamp cache. +Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the [timestamp cache](#timestamp-cache). ### Timestamp cache @@ -134,7 +134,7 @@ If an operation encounters a write intent for a key, it attempts to "resolve" th - If the push succeeds, the operation continues. - If this push fails (which is the majority of the time), this transaction goes into the [`TxnWaitQueue`]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#txnwaitqueue) on this node. The incoming transaction can only continue once the blocking transaction completes (i.e., commits or aborts). - `MISSING`, the resolver consults the write intent's timestamp. - - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's timestamp cache, which will inform the transaction that its timestamp was pushed once the transaction record gets created. + - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's [timestamp cache](#timestamp-cache), which will inform the transaction that its timestamp was pushed once the transaction record gets created. - If the write intent is older than the transaction liveness threshold, the resolution exhibits the `ABORTED` behavior. Note that transaction records might be missing because we've avoided writing the record until the transaction commits. For more information, see [Transaction Layer: Transaction records]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). @@ -147,7 +147,7 @@ If the read doesn't encounter a write intent and the key-value operation is mean The leaseholder aggregates all read responses into a `BatchResponse` that will get returned to the gateway node's `DistSender`. -As we mentioned before, each read operation also updates the timestamp cache. +As we mentioned before, each read operation also updates the [timestamp cache](#timestamp-cache). ### Write Operations @@ -179,7 +179,7 @@ Now that we have followed an operation all the way down from the SQL client to t it sends an commit acknowledgment to the gateway node's `DistSender`, which was waiting for this signal (having already received the provisional acknowledgment from the leaseholder's evaluator). 1. The gateway node's `DistSender` aggregates commit acknowledgments from all of the write operations in the `BatchRequest`, as well as any values from read operations that should be returned to the client. 1. Once all operations have successfully completed (i.e., reads have returned values and write intents have been committed), the `DistSender` tries to record the transaction's success in the transaction record (which provides a durable mechanism of tracking the transaction's state), which can cause a few situations to arise: - - It checks the timestamp cache of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. + - It checks the [timestamp cache](#timestamp-cache) of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. - If the transaction is in an `ABORTED` state, the `DistSender` sends a response indicating as much, which ends up back at the SQL interface. Upon passing these checks the transaction record is either written for the first time with the `COMMITTED` state, or if it was in a `PENDING` state, it is moved to `COMMITTED`. Only at this point is the transaction considered committed. diff --git a/src/current/v24.3/transaction-retry-error-reference.md b/src/current/v24.3/transaction-retry-error-reference.md index fdb3f33e63f..28ce6e70ae2 100644 --- a/src/current/v24.3/transaction-retry-error-reference.md +++ b/src/current/v24.3/transaction-retry-error-reference.md @@ -345,7 +345,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_NEW_L **Description:** -The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the timestamp cache will not allow transaction _A_ to create a transaction record. A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. +The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. **Action:** @@ -361,7 +361,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_TIMES **Description:** -The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the timestamp cache will not allow transaction _A_ to create a transaction record. This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the timestamp cache is an in-memory cache, and has outgrown its memory limit (about 64 MB). +The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) is an in-memory cache, and has outgrown its memory limit (about 64 MB). **Action:** diff --git a/src/current/v25.1/architecture/life-of-a-distributed-transaction.md b/src/current/v25.1/architecture/life-of-a-distributed-transaction.md index 872e3add35d..c8ca84f63a7 100644 --- a/src/current/v25.1/architecture/life-of-a-distributed-transaction.md +++ b/src/current/v25.1/architecture/life-of-a-distributed-transaction.md @@ -96,7 +96,7 @@ In this case, the `DistSender` must look up the current leaseholder using the [c ##### Success -Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the timestamp cache. +Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the [timestamp cache](#timestamp-cache). ### Timestamp cache @@ -134,7 +134,7 @@ If an operation encounters a write intent for a key, it attempts to "resolve" th - If the push succeeds, the operation continues. - If this push fails (which is the majority of the time), this transaction goes into the [`TxnWaitQueue`]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#txnwaitqueue) on this node. The incoming transaction can only continue once the blocking transaction completes (i.e., commits or aborts). - `MISSING`, the resolver consults the write intent's timestamp. - - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's timestamp cache, which will inform the transaction that its timestamp was pushed once the transaction record gets created. + - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's [timestamp cache](#timestamp-cache), which will inform the transaction that its timestamp was pushed once the transaction record gets created. - If the write intent is older than the transaction liveness threshold, the resolution exhibits the `ABORTED` behavior. Note that transaction records might be missing because we've avoided writing the record until the transaction commits. For more information, see [Transaction Layer: Transaction records]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). @@ -147,7 +147,7 @@ If the read doesn't encounter a write intent and the key-value operation is mean The leaseholder aggregates all read responses into a `BatchResponse` that will get returned to the gateway node's `DistSender`. -As we mentioned before, each read operation also updates the timestamp cache. +As we mentioned before, each read operation also updates the [timestamp cache](#timestamp-cache). ### Write Operations @@ -179,7 +179,7 @@ Now that we have followed an operation all the way down from the SQL client to t it sends an commit acknowledgment to the gateway node's `DistSender`, which was waiting for this signal (having already received the provisional acknowledgment from the leaseholder's evaluator). 1. The gateway node's `DistSender` aggregates commit acknowledgments from all of the write operations in the `BatchRequest`, as well as any values from read operations that should be returned to the client. 1. Once all operations have successfully completed (i.e., reads have returned values and write intents have been committed), the `DistSender` tries to record the transaction's success in the transaction record (which provides a durable mechanism of tracking the transaction's state), which can cause a few situations to arise: - - It checks the timestamp cache of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. + - It checks the [timestamp cache](#timestamp-cache) of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. - If the transaction is in an `ABORTED` state, the `DistSender` sends a response indicating as much, which ends up back at the SQL interface. Upon passing these checks the transaction record is either written for the first time with the `COMMITTED` state, or if it was in a `PENDING` state, it is moved to `COMMITTED`. Only at this point is the transaction considered committed. diff --git a/src/current/v25.1/transaction-retry-error-reference.md b/src/current/v25.1/transaction-retry-error-reference.md index fdb3f33e63f..28ce6e70ae2 100644 --- a/src/current/v25.1/transaction-retry-error-reference.md +++ b/src/current/v25.1/transaction-retry-error-reference.md @@ -345,7 +345,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_NEW_L **Description:** -The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the timestamp cache will not allow transaction _A_ to create a transaction record. A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. +The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. **Action:** @@ -361,7 +361,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_TIMES **Description:** -The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the timestamp cache will not allow transaction _A_ to create a transaction record. This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the timestamp cache is an in-memory cache, and has outgrown its memory limit (about 64 MB). +The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) is an in-memory cache, and has outgrown its memory limit (about 64 MB). **Action:** diff --git a/src/current/v25.2/architecture/life-of-a-distributed-transaction.md b/src/current/v25.2/architecture/life-of-a-distributed-transaction.md index dc1d41a6ed0..993de4125a7 100644 --- a/src/current/v25.2/architecture/life-of-a-distributed-transaction.md +++ b/src/current/v25.2/architecture/life-of-a-distributed-transaction.md @@ -96,7 +96,7 @@ In this case, the `DistSender` must look up the current leaseholder using the [c ##### Success -Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the timestamp cache. +Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the [timestamp cache](#timestamp-cache). ### Timestamp cache @@ -134,7 +134,7 @@ If an operation encounters a write intent for a key, it attempts to "resolve" th - If the push succeeds, the operation continues. - If this push fails (which is the majority of the time), this transaction goes into the [`TxnWaitQueue`]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#txnwaitqueue) on this node. The incoming transaction can only continue once the blocking transaction completes (i.e., commits or aborts). - `MISSING`, the resolver consults the write intent's timestamp. - - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's timestamp cache, which will inform the transaction that its timestamp was pushed once the transaction record gets created. + - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's [timestamp cache](#timestamp-cache), which will inform the transaction that its timestamp was pushed once the transaction record gets created. - If the write intent is older than the transaction liveness threshold, the resolution exhibits the `ABORTED` behavior. Note that transaction records might be missing because we've avoided writing the record until the transaction commits. For more information, see [Transaction Layer: Transaction records]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). @@ -147,7 +147,7 @@ If the read doesn't encounter a write intent and the key-value operation is mean The leaseholder aggregates all read responses into a `BatchResponse` that will get returned to the gateway node's `DistSender`. -As we mentioned before, each read operation also updates the timestamp cache. +As we mentioned before, each read operation also updates the [timestamp cache](#timestamp-cache). ### Write Operations @@ -177,7 +177,7 @@ Now that we have followed an operation all the way down from the SQL client to t it sends an commit acknowledgment to the gateway node's `DistSender`, which was waiting for this signal (having already received the provisional acknowledgment from the leaseholder's evaluator). 1. The gateway node's `DistSender` aggregates commit acknowledgments from all of the write operations in the `BatchRequest`, as well as any values from read operations that should be returned to the client. 1. Once all operations have successfully completed (i.e., reads have returned values and write intents have been committed), the `DistSender` tries to record the transaction's success in the transaction record (which provides a durable mechanism of tracking the transaction's state), which can cause a few situations to arise: - - It checks the timestamp cache of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. + - It checks the [timestamp cache](#timestamp-cache) of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. - If the transaction is in an `ABORTED` state, the `DistSender` sends a response indicating as much, which ends up back at the SQL interface. Upon passing these checks the transaction record is either written for the first time with the `COMMITTED` state, or if it was in a `PENDING` state, it is moved to `COMMITTED`. Only at this point is the transaction considered committed. diff --git a/src/current/v25.2/transaction-retry-error-reference.md b/src/current/v25.2/transaction-retry-error-reference.md index 66c40369f7b..f3ca35fae76 100644 --- a/src/current/v25.2/transaction-retry-error-reference.md +++ b/src/current/v25.2/transaction-retry-error-reference.md @@ -345,7 +345,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_NEW_L **Description:** -The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the timestamp cache will not allow transaction _A_ to create a transaction record. A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. +The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. **Action:** @@ -361,7 +361,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_TIMES **Description:** -The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the timestamp cache will not allow transaction _A_ to create a transaction record. This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the timestamp cache is an in-memory cache, and has outgrown its memory limit (about 64 MB). +The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) is an in-memory cache, and has outgrown its memory limit (about 64 MB). **Action:** diff --git a/src/current/v25.3/architecture/life-of-a-distributed-transaction.md b/src/current/v25.3/architecture/life-of-a-distributed-transaction.md index a6d464fca85..08d641dc854 100644 --- a/src/current/v25.3/architecture/life-of-a-distributed-transaction.md +++ b/src/current/v25.3/architecture/life-of-a-distributed-transaction.md @@ -96,7 +96,7 @@ In this case, the `DistSender` must look up the current leaseholder using the [c ##### Success -Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the timestamp cache. +Once the node that contains the leaseholder of the range receives the `BatchRequest`, it begins processing it, and progresses onto checking the [timestamp cache](#timestamp-cache). ### Timestamp cache @@ -134,7 +134,7 @@ If an operation encounters a write intent for a key, it attempts to "resolve" th - If the push succeeds, the operation continues. - If this push fails (which is the majority of the time), this transaction goes into the [`TxnWaitQueue`]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#txnwaitqueue) on this node. The incoming transaction can only continue once the blocking transaction completes (i.e., commits or aborts). - `MISSING`, the resolver consults the write intent's timestamp. - - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's timestamp cache, which will inform the transaction that its timestamp was pushed once the transaction record gets created. + - If it was created within the transaction liveness threshold, it treats the transaction record as exhibiting the `PENDING` behavior, with the addition of tracking the push in the range's [timestamp cache](#timestamp-cache), which will inform the transaction that its timestamp was pushed once the transaction record gets created. - If the write intent is older than the transaction liveness threshold, the resolution exhibits the `ABORTED` behavior. Note that transaction records might be missing because we've avoided writing the record until the transaction commits. For more information, see [Transaction Layer: Transaction records]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). @@ -147,7 +147,7 @@ If the read doesn't encounter a write intent and the key-value operation is mean The leaseholder aggregates all read responses into a `BatchResponse` that will get returned to the gateway node's `DistSender`. -As we mentioned before, each read operation also updates the timestamp cache. +As we mentioned before, each read operation also updates the [timestamp cache](#timestamp-cache). ### Write Operations @@ -177,7 +177,7 @@ Now that we have followed an operation all the way down from the SQL client to t it sends an commit acknowledgment to the gateway node's `DistSender`, which was waiting for this signal (having already received the provisional acknowledgment from the leaseholder's evaluator). 1. The gateway node's `DistSender` aggregates commit acknowledgments from all of the write operations in the `BatchRequest`, as well as any values from read operations that should be returned to the client. 1. Once all operations have successfully completed (i.e., reads have returned values and write intents have been committed), the `DistSender` tries to record the transaction's success in the transaction record (which provides a durable mechanism of tracking the transaction's state), which can cause a few situations to arise: - - It checks the timestamp cache of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. + - It checks the [timestamp cache](#timestamp-cache) of the range where the first write occurred to see if its timestamp got pushed forward. If it did, the transaction performs a [read refresh]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#read-refreshing) to see if any values it needed have been changed. If the read refresh is successful, the transaction can commit at the pushed timestamp. If the read refresh fails, the transaction must be restarted. - If the transaction is in an `ABORTED` state, the `DistSender` sends a response indicating as much, which ends up back at the SQL interface. Upon passing these checks the transaction record is either written for the first time with the `COMMITTED` state, or if it was in a `PENDING` state, it is moved to `COMMITTED`. Only at this point is the transaction considered committed. diff --git a/src/current/v25.3/transaction-retry-error-reference.md b/src/current/v25.3/transaction-retry-error-reference.md index 66c40369f7b..f3ca35fae76 100644 --- a/src/current/v25.3/transaction-retry-error-reference.md +++ b/src/current/v25.3/transaction-retry-error-reference.md @@ -345,7 +345,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_NEW_L **Description:** -The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the timestamp cache will not allow transaction _A_ to create a transaction record. A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. +The `ABORT_REASON_NEW_LEASE_PREVENTS_TXN` error occurs because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). A new lease wipes the timestamp cache, so this could mean the [leaseholder]({% link {{ page.version.version }}/architecture/life-of-a-distributed-transaction.md %}#leaseholder-node) was moved and the duration of transaction _A_ was unlucky enough to happen across a lease acquisition. In other words, leaseholders got shuffled out from underneath transaction _A_ (due to no fault of the client application or schema design), and now it has to be retried. **Action:** @@ -361,7 +361,7 @@ TransactionRetryWithProtoRefreshError:TransactionAbortedError(ABORT_REASON_TIMES **Description:** -The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the timestamp cache will not allow transaction _A_ to create a transaction record. This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the timestamp cache is an in-memory cache, and has outgrown its memory limit (about 64 MB). +The `ABORT_REASON_TIMESTAMP_CACHE_REJECTED` error occurs when the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) will not allow transaction _A_ to create a [transaction record]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#transaction-records). This can happen due to a [range merge]({% link {{ page.version.version }}/architecture/distribution-layer.md %}#range-merges) happening in the background, or because the [timestamp cache]({% link {{ page.version.version }}/architecture/transaction-layer.md %}#timestamp-cache) is an in-memory cache, and has outgrown its memory limit (about 64 MB). **Action:**