Skip to content

Commit 47d34c9

Browse files
craig[bot]yuzefovich
craig[bot]
andcommitted
Merge #85286
85286: kvcoord: subject refresh spans to the limit when importing from leaves r=yuzefovich a=yuzefovich Whenever we're importing the refresh spans from the LeafTxnFinalState, we're inserting those refresh spans into the refresh footprint set and attempt to condense the set to stay under the maximum (determined by a setting). However, the condensing is performed on a best-effort basis, so previously it was possible to significantly over-shoot the limit. Furthermore, this refresh footprint is not accounted for. This commit improves things a bit by giving up on the ability to refresh (i.e. invalidating the refresh footprint) once the limit is exceeded when importing the refresh spans from the leaves - it is similar to what we do after `Send`ing the BatchRequest. Addresses: #64906. Release note: None Co-authored-by: Yahor Yuzefovich <[email protected]>
2 parents 7326bbb + 4e8b0bc commit 47d34c9

File tree

1 file changed

+34
-29
lines changed

1 file changed

+34
-29
lines changed

pkg/kv/kvclient/kvcoord/txn_interceptor_span_refresher.go

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -171,39 +171,43 @@ func (sr *txnSpanRefresher) SendLocked(
171171
return nil, roachpb.NewError(err)
172172
}
173173
// Check whether we should condense the refresh spans.
174-
maxBytes := MaxTxnRefreshSpansBytes.Get(&sr.st.SV)
175-
if sr.refreshFootprint.bytes >= maxBytes {
176-
condensedBefore := sr.refreshFootprint.condensed
177-
condensedSufficient := sr.tryCondenseRefreshSpans(ctx, maxBytes)
178-
if condensedSufficient {
179-
log.VEventf(ctx, 2, "condensed refresh spans for txn %s to %d bytes",
180-
br.Txn, sr.refreshFootprint.bytes)
181-
} else {
182-
// Condensing was not enough. Giving up on tracking reads. Refreshed
183-
// will not be possible.
184-
log.VEventf(ctx, 2, "condensed refresh spans didn't save enough memory. txn %s. "+
185-
"refresh spans after condense: %d bytes",
186-
br.Txn, sr.refreshFootprint.bytes)
187-
sr.refreshInvalid = true
188-
sr.refreshFootprint.clear()
189-
}
190-
191-
if sr.refreshFootprint.condensed && !condensedBefore {
192-
sr.refreshMemoryLimitExceeded.Inc(1)
193-
}
194-
}
174+
sr.maybeCondenseRefreshSpans(ctx, br.Txn)
195175
}
196176
return br, nil
197177
}
198178

199-
// tryCondenseRefreshSpans attempts to condense the refresh spans in order to
200-
// save memory. Returns true if we managed to condense them below maxBytes.
201-
func (sr *txnSpanRefresher) tryCondenseRefreshSpans(ctx context.Context, maxBytes int64) bool {
202-
if sr.knobs.CondenseRefreshSpansFilter != nil && !sr.knobs.CondenseRefreshSpansFilter() {
203-
return false
179+
// maybeCondenseRefreshSpans checks whether the refresh footprint exceeds the
180+
// maximum size (as determined by the MaxTxnRefreshSpansBytes cluster setting)
181+
// and attempts to condense it if so. If condensing is insufficient, then the
182+
// refresh is invalidated. It is assumed that the refresh is valid when this
183+
// method is called.
184+
func (sr *txnSpanRefresher) maybeCondenseRefreshSpans(
185+
ctx context.Context, txn *roachpb.Transaction,
186+
) {
187+
maxBytes := MaxTxnRefreshSpansBytes.Get(&sr.st.SV)
188+
if sr.refreshFootprint.bytes >= maxBytes {
189+
condensedBefore := sr.refreshFootprint.condensed
190+
var condensedSufficient bool
191+
if sr.knobs.CondenseRefreshSpansFilter == nil || sr.knobs.CondenseRefreshSpansFilter() {
192+
sr.refreshFootprint.maybeCondense(ctx, sr.riGen, maxBytes)
193+
condensedSufficient = sr.refreshFootprint.bytes < maxBytes
194+
}
195+
if condensedSufficient {
196+
log.VEventf(ctx, 2, "condensed refresh spans for txn %s to %d bytes",
197+
txn, sr.refreshFootprint.bytes)
198+
} else {
199+
// Condensing was not enough. Giving up on tracking reads. Refreshes
200+
// will not be possible.
201+
log.VEventf(ctx, 2, "condensed refresh spans didn't save enough memory. txn %s. "+
202+
"refresh spans after condense: %d bytes",
203+
txn, sr.refreshFootprint.bytes)
204+
sr.refreshInvalid = true
205+
sr.refreshFootprint.clear()
206+
}
207+
if sr.refreshFootprint.condensed && !condensedBefore {
208+
sr.refreshMemoryLimitExceeded.Inc(1)
209+
}
204210
}
205-
sr.refreshFootprint.maybeCondense(ctx, sr.riGen, maxBytes)
206-
return sr.refreshFootprint.bytes < maxBytes
207211
}
208212

209213
// sendLockedWithRefreshAttempts sends the batch through the wrapped sender. It
@@ -679,7 +683,8 @@ func (sr *txnSpanRefresher) importLeafFinalState(
679683
sr.refreshFootprint.clear()
680684
} else if !sr.refreshInvalid {
681685
sr.refreshFootprint.insert(tfs.RefreshSpans...)
682-
sr.refreshFootprint.maybeCondense(ctx, sr.riGen, MaxTxnRefreshSpansBytes.Get(&sr.st.SV))
686+
// Check whether we should condense the refresh spans.
687+
sr.maybeCondenseRefreshSpans(ctx, &tfs.Txn)
683688
}
684689
}
685690

0 commit comments

Comments
 (0)