Skip to content

Commit 7d3fdbf

Browse files
craig[bot]jeffrey-xiao
craig[bot]
andcommitted
Merge #38221
38221: sql: remove manually split ranges during TRUNCATE and DROP r=jeffrey-xiao a=jeffrey-xiao If a table/index is dropped/truncated, any manually split ranges in the table/index should be unsplit so the automatic merge queue can clean up after it. Additionally, re-enable splits in clearrange which was previously timing out because manual splits could not be automatically merged. Release note: None Co-authored-by: Jeffrey Xiao <[email protected]>
2 parents c9ad321 + 7375d59 commit 7d3fdbf

File tree

4 files changed

+139
-6
lines changed

4 files changed

+139
-6
lines changed

pkg/cmd/roachtest/clearrange.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,8 @@ func runClearRange(ctx context.Context, t *test, c *cluster, aggressiveChecks bo
5050

5151
// NB: on a 10 node cluster, this should take well below 3h.
5252
tBegin := timeutil.Now()
53-
// Currently we must set `--ranges=0` since automatic merges cannot merge ranges created by
54-
// manual splits, and dropping the table does not remove manual splits. The latter may change
55-
// in the future in which case it'll be fine to set `--ranges` to something else. But for now,
56-
// setting it to nonzero causes the test to hang forever waiting on ranges to be merged.
5753
c.Run(ctx, c.Node(1), "./cockroach", "workload", "fixtures", "import", "bank",
58-
"--payload-bytes=10240", "--ranges=0", "--rows=65104166", "--seed=4", "--db=bigbank")
54+
"--payload-bytes=10240", "--ranges=10", "--rows=65104166", "--seed=4", "--db=bigbank")
5955
c.l.Printf("import took %.2fs", timeutil.Since(tBegin).Seconds())
6056
c.Stop(ctx)
6157
t.Status()

pkg/sql/drop_index.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ package sql
1313
import (
1414
"context"
1515
"fmt"
16+
"strings"
1617

18+
"github.com/cockroachdb/cockroach/pkg/roachpb"
1719
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
1820
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
1921
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
2022
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
2123
"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
24+
"github.com/cockroachdb/cockroach/pkg/util/hlc"
2225
"github.com/cockroachdb/errors"
2326
)
2427

@@ -222,6 +225,31 @@ func (p *planner) dropIndexByName(
222225
found := false
223226
for i, idxEntry := range tableDesc.Indexes {
224227
if idxEntry.ID == idx.ID {
228+
// Unsplit all manually split ranges in the index so they can be
229+
// automatically merged by the merge queue.
230+
span := tableDesc.IndexSpan(idxEntry.ID)
231+
ranges, err := ScanMetaKVs(ctx, p.txn, span)
232+
if err != nil {
233+
return err
234+
}
235+
for _, r := range ranges {
236+
var desc roachpb.RangeDescriptor
237+
if err := r.ValueProto(&desc); err != nil {
238+
return err
239+
}
240+
// We have to explicitly check that the range descriptor's start key
241+
// lies within the span of the index since ScanMetaKVs returns all
242+
// intersecting spans.
243+
if (desc.StickyBit != hlc.Timestamp{}) && span.Key.Compare(desc.StartKey.AsRawKey()) <= 0 {
244+
// Swallow "key is not the start of a range" errors because it would
245+
// mean that the sticky bit was removed and merged concurrently. DROP
246+
// INDEX should not fail because of this.
247+
if err := p.ExecCfg().DB.AdminUnsplit(ctx, desc.StartKey); err != nil && strings.Contains(err.Error(), "is not the start of a range") {
248+
return err
249+
}
250+
}
251+
}
252+
225253
// the idx we picked up with FindIndexByID at the top may not
226254
// contain the same field any more due to other schema changes
227255
// intervening since the initial lookup. So we send the recent

pkg/sql/drop_table.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ package sql
1313
import (
1414
"context"
1515
"fmt"
16+
"strings"
1617

1718
"github.com/cockroachdb/cockroach/pkg/jobs"
1819
"github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
1920
"github.com/cockroachdb/cockroach/pkg/keys"
21+
"github.com/cockroachdb/cockroach/pkg/roachpb"
2022
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
2123
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
2224
"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
2325
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
26+
"github.com/cockroachdb/cockroach/pkg/util/hlc"
2427
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
2528
"github.com/cockroachdb/errors"
2629
)
@@ -350,6 +353,27 @@ func (p *planner) initiateDropTable(
350353
tableDesc.DropTime = timeutil.Now().UnixNano()
351354
}
352355

356+
// Unsplit all manually split ranges in the table so they can be
357+
// automatically merged by the merge queue.
358+
ranges, err := ScanMetaKVs(ctx, p.txn, tableDesc.TableSpan())
359+
if err != nil {
360+
return err
361+
}
362+
for _, r := range ranges {
363+
var desc roachpb.RangeDescriptor
364+
if err := r.ValueProto(&desc); err != nil {
365+
return err
366+
}
367+
if (desc.StickyBit != hlc.Timestamp{}) {
368+
// Swallow "key is not the start of a range" errors because it would mean
369+
// that the sticky bit was removed and merged concurrently. DROP TABLE
370+
// should not fail because of this.
371+
if err := p.ExecCfg().DB.AdminUnsplit(ctx, desc.StartKey); err != nil && strings.Contains(err.Error(), "is not the start of a range") {
372+
return err
373+
}
374+
}
375+
}
376+
353377
tableDesc.State = sqlbase.TableDescriptor_DROP
354378
if drainName {
355379
// Queue up name for draining.

pkg/sql/logictest/testdata/logic_test/crdb_internal

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ node_id store_id attrs used
325325
1 1 [] 0
326326

327327
statement ok
328-
CREATE TABLE foo (a INT PRIMARY KEY); INSERT INTO foo VALUES(1)
328+
CREATE TABLE foo (a INT PRIMARY KEY, INDEX idx(a)); INSERT INTO foo VALUES(1)
329329

330330
statement ok
331331
ALTER TABLE foo SPLIT AT VALUES(2)
@@ -485,3 +485,88 @@ ORDER BY key, f
485485
SELECT crdb_internal.force_retry(_) true false
486486
SELECT crdb_internal.force_retry(_) true true
487487
SET application_name = DEFAULT false false
488+
489+
490+
# Testing split_enforced_until when truncating and dropping.
491+
statement ok
492+
ALTER TABLE foo SPLIT AT VALUES (1), (2), (3)
493+
494+
statement ok
495+
ALTER INDEX foo@idx SPLIT AT VALUES (1), (2), (3)
496+
497+
query TT colnames
498+
SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
499+
----
500+
start_pretty end_pretty
501+
/Table/56/1/1 /Table/56/1/2
502+
/Table/56/1/2 /Table/56/1/3
503+
/Table/56/1/3 /Table/56/2/1
504+
/Table/56/2/1 /Table/56/2/2
505+
/Table/56/2/2 /Table/56/2/3
506+
/Table/56/2/3 /Max
507+
508+
statement ok
509+
TRUNCATE TABLE foo
510+
511+
query TT colnames
512+
SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
513+
----
514+
start_pretty end_pretty
515+
516+
statement ok
517+
ALTER TABLE foo SPLIT AT VALUES (1), (2), (3)
518+
519+
statement ok
520+
ALTER INDEX foo@idx SPLIT AT VALUES (1), (2), (3)
521+
522+
query TT colnames
523+
SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
524+
----
525+
start_pretty end_pretty
526+
/Table/57/1/1 /Table/57/1/2
527+
/Table/57/1/2 /Table/57/1/3
528+
/Table/57/1/3 /Table/57/2/1
529+
/Table/57/2/1 /Table/57/2/2
530+
/Table/57/2/2 /Table/57/2/3
531+
/Table/57/2/3 /Max
532+
533+
statement ok
534+
DROP TABLE foo
535+
536+
query TT colnames
537+
SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
538+
----
539+
start_pretty end_pretty
540+
541+
statement ok
542+
CREATE TABLE foo (a INT PRIMARY KEY, INDEX idx(a)); INSERT INTO foo VALUES(1)
543+
544+
statement ok
545+
ALTER TABLE foo SPLIT AT VALUES (1), (2), (3)
546+
547+
statement ok
548+
ALTER INDEX foo@idx SPLIT AT VALUES (1), (2), (3)
549+
550+
query TT colnames
551+
SELECT start_pretty, end_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
552+
----
553+
start_pretty end_pretty
554+
/Table/58/1/1 /Table/58/1/2
555+
/Table/58/1/2 /Table/58/1/3
556+
/Table/58/1/3 /Table/58/2/1
557+
/Table/58/2/1 /Table/58/2/2
558+
/Table/58/2/2 /Table/58/2/3
559+
/Table/58/2/3 /Max
560+
561+
statement ok
562+
DROP INDEX foo@idx
563+
564+
# Verify only the start keys of the manually split ranges because the merge queue could merge the
565+
# ranges [/Table/58/1/3, /Table/58/2/1) with its right neighbors.
566+
query T colnames
567+
SELECT start_pretty FROM crdb_internal.ranges WHERE split_enforced_until IS NOT NULL
568+
----
569+
start_pretty
570+
/Table/58/1/1
571+
/Table/58/1/2
572+
/Table/58/1/3

0 commit comments

Comments
 (0)