From 459b8bf69d653452df8df3dfbf019ef88de651d3 Mon Sep 17 00:00:00 2001 From: Oleg Afanasyev Date: Thu, 11 Aug 2022 19:29:29 +0100 Subject: [PATCH] batcheval: add clear range option to cmd_gc GC request will perform fast path clear operation on the whole range if instructed by GC. Its range bounds should match descriptor bounds exactly for operation to succeed. Underlying mvcc operation will validate if no data is present for safety. Release note: None --- pkg/kv/kvserver/batcheval/cmd_gc.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/pkg/kv/kvserver/batcheval/cmd_gc.go b/pkg/kv/kvserver/batcheval/cmd_gc.go index 95491d3ee48a..b148481d6d3b 100644 --- a/pkg/kv/kvserver/batcheval/cmd_gc.go +++ b/pkg/kv/kvserver/batcheval/cmd_gc.go @@ -53,6 +53,10 @@ func declareKeysGC( )) { latchSpans.AddMVCC(spanset.SpanReadWrite, span, hlc.MaxTimestamp) } + if rk := gcr.ClearRangeKey; rk != nil { + latchSpans.AddMVCC(spanset.SpanReadWrite, roachpb.Span{Key: rk.StartKey, EndKey: rk.EndKey}, + hlc.MaxTimestamp) + } // The RangeGCThresholdKey is only written to if the // req.(*GCRequest).Threshold is set. However, we always declare an exclusive // access over this key in order to serialize with other GC requests. @@ -134,12 +138,19 @@ func GC( // GC request's effect from the raft log. Latches held on the leaseholder // would have no impact on a follower read. if !args.Threshold.IsEmpty() && - (len(args.Keys) != 0 || len(args.RangeKeys) != 0) && + (len(args.Keys) != 0 || len(args.RangeKeys) != 0 || args.ClearRangeKey != nil) && !cArgs.EvalCtx.EvalKnobs().AllowGCWithNewThresholdAndKeys { return result.Result{}, errors.AssertionFailedf( "GC request can set threshold or it can GC keys, but it is unsafe for it to do both") } + // We do not allow removal of point or range keys combined with clear range + // operation as they could cover the same set of keys. + if (len(args.Keys) != 0 || len(args.RangeKeys) != 0) && args.ClearRangeKey != nil { + return result.Result{}, errors.AssertionFailedf( + "GC request can remove point and range keys or clear entire range, but it is unsafe for it to do both") + } + // All keys must be inside the current replica range. Keys outside // of this range in the GC request are dropped silently, which is // safe because they can simply be re-collected later on the correct @@ -178,6 +189,18 @@ func GC( return result.Result{}, err } + // Fast path operation to try to remove all user key data from the range. + if rk := args.ClearRangeKey; rk != nil { + if !rk.StartKey.Equal(desc.StartKey.AsRawKey()) || !rk.EndKey.Equal(desc.EndKey.AsRawKey()) { + return result.Result{}, errors.Errorf("gc with clear range operation could only be used on the full range") + } + + if err := storage.MVCCGarbageCollectWholeRange(ctx, readWriter, cArgs.Stats, + rk.StartKey, rk.EndKey, cArgs.EvalCtx.GetGCThreshold(), cArgs.EvalCtx.GetMVCCStats()); err != nil { + return result.Result{}, err + } + } + // Optionally bump the GC threshold timestamp. var res result.Result if !args.Threshold.IsEmpty() {