Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kv/kvclient: support generalized server-side refreshes
This commit generalizes the concept of a server-side transaction refresh for any request issued by a transaction before it has accumulated refresh spans. Server-side refreshes were previously only possible for batches that contained an EndTxn, but this was limiting for no particularly strong reason. The commit supports this new functionality by adding a new flag to the BatchRequest header called `CanForwardReadTimestamp`. This flag indicates that the batch can be evaluated at a higher timestamp than the transaction's read timestamp. It is set by the client if the transaction has not performed any reads that must be refreshed prior to sending this current batch. When set, it allows the server to handle pushes and write too old conditions locally. In the future, we'd like to remove the EndTxn.CanCommitAtHigherTimestamp flag entirely in favor of this more general mechanism. While adding support for this new form of server-side refresh, the commit also adds a retry loop on the read-only request evaluation path. This is almost never exercised because most read-only requests acquire MVCC read latches and also don't throw WriteTooOld errors, but it can be exercised for locking scans, which acquire MVCC write latches and do occasionally throw WriteTooOld errors. Release justification: necessary to avoid a performance regression due to implicit SELECT FOR UPDATE in certain cases where UPDATEs are heavily contended. Before implicit SFU, a heavily contended UPDATE statement would always eventually commit after 3 retries: epoch 1: {Scan} succeeds, {Put, EndTxn} hits WriteTooOld epoch 2: {Scan} succeeds, {Put} defers WriteTooOld and writes intent, {EndTxn} fails epoch 3: {Scan} succeeds, {Put} rewrites intent, {EndTxn} succeeds After SFU but before this change we could get cases where the {Scan} continues to hit WriteTooOld errors and has no bound on the number of attempts it will make. After SFU and this change the UPDATE will always commit after exactly 1 retry: epoch 1: {Scan} hits WriteTooOld and server-side refreshes, {Put, EndTxn} succeeds.
- Loading branch information