Skip to content

Commit

Permalink
Merge pull request #31827 from nvanbenschoten/backport2.0-31733
Browse files Browse the repository at this point in the history
release-2.0: kv: avoid transaction too large error if already refreshed
nvanbenschoten authored Oct 25, 2018
2 parents ca7aaa3 + b341d2a commit 174cead
Showing 2 changed files with 30 additions and 2 deletions.
26 changes: 26 additions & 0 deletions pkg/kv/dist_sender_server_test.go
Original file line number Diff line number Diff line change
@@ -2125,6 +2125,32 @@ func TestTxnCoordSenderRetries(t *testing.T) {
},
expFailure: "transaction is too large to complete; try splitting into pieces",
},
{
// If we've exhausted the limit for tracking refresh spans but we
// already refreshed, keep running the txn.
name: "forwarded timestamp with too many refreshes, read only",
afterTxnStart: func(ctx context.Context, db *client.DB) error {
return db.Put(ctx, "a", "value")
},
retryable: func(ctx context.Context, txn *client.Txn) error {
// Make the batch large enough such that when we accounted for
// all of its spans then we exceed the limit on refresh spans.
// This is not an issue because we refresh before tracking their
// spans.
keybase := strings.Repeat("a", 1024)
maxRefreshBytes := kv.MaxTxnRefreshSpansBytes.Get(&s.ClusterSettings().SV)
scanToExceed := int(maxRefreshBytes) / len(keybase)
b := txn.NewBatch()
// Hit the uncertainty error at the beginning of the batch.
b.Get("a")
for i := 0; i < scanToExceed; i++ {
key := roachpb.Key(fmt.Sprintf("%s%10d", keybase, i))
b.Scan(key, key.Next())
}
return txn.Run(ctx, b)
},
filter: newUncertaintyFilter(roachpb.Key([]byte("a"))),
},
{
// Even if accounting for the refresh spans would have exhausted the
// limit for tracking refresh spans and our transaction's timestamp
6 changes: 4 additions & 2 deletions pkg/kv/txn_coord_sender.go
Original file line number Diff line number Diff line change
@@ -1175,8 +1175,10 @@ func (tc *TxnCoordSender) updateState(
// exhausted, return a non-retryable error indicating that the
// transaction is too large and should potentially be split.
// We do this to avoid endlessly retrying a txn likely refail.
if pErr == nil && !tc.mu.meta.RefreshValid &&
(br.Txn.WriteTooOld || br.Txn.OrigTimestamp != br.Txn.Timestamp) {
ts := br.Txn.OrigTimestamp
ts.Forward(br.Txn.RefreshedTimestamp)
needsRefresh := br.Txn.WriteTooOld || ts != br.Txn.Timestamp
if needsRefresh && !tc.mu.meta.RefreshValid {
pErr = roachpb.NewErrorWithTxn(
errors.New("transaction is too large to complete; try splitting into pieces"), br.Txn,
)

0 comments on commit 174cead

Please sign in to comment.