-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sql: add ALTER TABLE/INDEX .. UNSPLIT AT .. #37603
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 26 of 27 files at r1.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @ajwerner, @jeffrey-xiao, and @nvanbenschoten)
pkg/sql/unsplit.go, line 115 at r1 (raw file):
if err := params.extendedEvalCtx.ExecCfg.DB.AdminUnsplit(params.ctx, rowKey); err != nil { return false, err
Do we need to do any special error mapping here? Is it okay to just propagate the error directly? This isn't a question to which I know the answer.
pkg/sql/unsplit_test.go, line 96 at r1 (raw file):
{ in: "ALTER TABLE d.t UNSPLIT AT VALUES (1, 'non-existent')", error: "unsplit key is not the start of a range",
This is the error case I'm worried about. I mean worst case is that it's just an XX00 SQL error but is that desirable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 27 files at r1.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @jeffrey-xiao and @nvanbenschoten)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 26 of 27 files at r1.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @jeffrey-xiao)
pkg/internal/client/db.go, line 484 at r1 (raw file):
// AdminUnsplit removes the sticky bit of the range specified by splitKey. // // spanKey is the start key of the range whose sticky bit should be removed.
Comment about what happens if the sticky bit doesn't exist. Also, talk about what happens if the provided key is not the start key of the range.
pkg/roachpb/api.proto, line 672 at r1 (raw file):
}
Extra line.
pkg/sql/unsplit.go, line 101 at r1 (raw file):
func (n *unsplitNode) startExec(params runParams) error { return nil
We'll need to check the cluster version to see if VersionStickyBit
is active. If not, we'll want to reject the statement.
pkg/sql/unsplit.go, line 124 at r1 (raw file):
func (n *unsplitNode) Values() tree.Datums { return tree.Datums{
I'm curious whether you think this is what a user will be interested in as the result of an UNSPLIT AT
statement. Should we return the split point that we removed? The new start of the range? A boolean saying whether the split point was removed or not? I haven't thought much into the desired UX here. Having written this all up and used it in a few tests, do you have any thoughts about this?
pkg/sql/unsplit_test.go, line 64 at r1 (raw file):
} tests := []struct {
Nice tests!
There are a few other logic_tests that we'll want to add as well. To start, I think we'll want to add some basic tests to alter_table
. Next, we'll want to expand on the crdb_internal
tests that we added last time. Finally, the ranges
test seems like an appropriate place to add some higher-level functional tests.
pkg/storage/client_merge_test.go, line 3434 at r1 (raw file):
verifyUnmerged(t) // TODO(jeffreyxiao): Use same mechanism as ALTER TABLE ... UNSPLIT AT
Very satisfying.
pkg/storage/replica_command.go, line 384 at r1 (raw file):
// AdminUnsplit removes the sticky bit of the range specified by the // splitKey
s/splitKey/args.Key/
right?
Also, period at the end.
pkg/storage/replica_command.go, line 385 at r1 (raw file):
// AdminUnsplit removes the sticky bit of the range specified by the // splitKey func (r *Replica) AdminUnsplit(
For now, this is probably fine, but at some point we'll probably need a retry loop like we have for AdminSplit
.
pkg/storage/replica_command.go, line 403 at r1 (raw file):
if err := r.store.DB().Txn(ctx, func(ctx context.Context, txn *client.Txn) error { b := txn.NewBatch() desc := *r.Desc()
We already have a desc
in scope, so no need to shadow it.
pkg/storage/replica_command.go, line 419 at r1 (raw file):
InternalCommitTrigger: &roachpb.InternalCommitTrigger{ StickyBitTrigger: &roachpb.StickyBitTrigger{ StickyBit: nil,
Leave a comment noting that this removes the sticky bit. It's always a little strange seeing a field set to nil in a constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @ajwerner, @jeffrey-xiao, and @nvanbenschoten)
pkg/sql/unsplit.go, line 115 at r1 (raw file):
Previously, ajwerner wrote…
Do we need to do any special error mapping here? Is it okay to just propagate the error directly? This isn't a question to which I know the answer.
I've now wrapped it in a pgerror.CodeDataExceptionError
.
pkg/sql/unsplit.go, line 124 at r1 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
I'm curious whether you think this is what a user will be interested in as the result of an
UNSPLIT AT
statement. Should we return the split point that we removed? The new start of the range? A boolean saying whether the split point was removed or not? I haven't thought much into the desired UX here. Having written this all up and used it in a few tests, do you have any thoughts about this?
I think returning the split point we removed makes sense and it's symmetric with that we return with an SPLIT AT
statement (even in the no-op case the unsplit/split key is returned). The new start of the range is misleading because it's not guaranteed that unsplitting the range will result in the range being merged.
pkg/sql/unsplit_test.go, line 96 at r1 (raw file):
Previously, ajwerner wrote…
This is the error case I'm worried about. I mean worst case is that it's just an XX00 SQL error but is that desirable?
I've now wrapped it in a pgerror.CodeDataExceptionError
.
pkg/storage/client_merge_test.go, line 3434 at r1 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
Very satisfying.
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 2 files at r2, 7 of 7 files at r3.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @ajwerner and @jeffrey-xiao)
pkg/internal/client/db.go, line 486 at r3 (raw file):
// splitKey is the start key of the range whose sticky bit should be removed. // // If spanKey is not the start key of a range, then this method will throw an
"If splitKey"
pkg/sql/unsplit.go, line 124 at r1 (raw file):
Previously, jeffrey-xiao (Jeffrey Xiao) wrote…
I think returning the split point we removed makes sense and it's symmetric with that we return with an
SPLIT AT
statement (even in the no-op case the unsplit/split key is returned). The new start of the range is misleading because it's not guaranteed that unsplitting the range will result in the range being merged.
Ok, that all sounds reasonable.
pkg/storage/replica_command.go, line 392 at r3 (raw file):
desc := *r.Desc() if !bytes.Equal(desc.StartKey.AsRawKey(), args.Header().Key) { return reply, roachpb.NewError(fmt.Errorf("key is not the start of a range"))
Why did this change?
pkg/storage/replica_command.go, line 425 at r3 (raw file):
return txn.Run(ctx, b) }); err != nil { return reply, roachpb.NewError(errors.Wrapf(err, "unsplit at key %s failed", args.Key))
Does NewErrorf
not work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @ajwerner, @jeffrey-xiao, and @nvanbenschoten)
pkg/storage/replica_command.go, line 392 at r3 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
Why did this change?
Originally, I wanted it not to print the file and line number, but since that's fine, I've changed it back.
pkg/storage/replica_command.go, line 425 at r3 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
Does
NewErrorf
not work here?
I'm wrapping another error and it doesn't seem like roachpb
has a Wrapf
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 2 of 2 files at r4.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @jeffrey-xiao and @nvanbenschoten)
pkg/storage/replica_command.go, line 425 at r3 (raw file):
Previously, jeffrey-xiao (Jeffrey Xiao) wrote…
I'm wrapping another error and it doesn't seem like
roachpb
has aWrapf
.
This roachpb.NewError is going to serialize the error to a string so the wrapping for use with Cause doesn't matter.
0d131b9
to
b858290
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @ajwerner, @jeffrey-xiao, and @nvanbenschoten)
pkg/storage/replica_command.go, line 425 at r3 (raw file):
Previously, ajwerner wrote…
This roachpb.NewError is going to serialize the error to a string so the wrapping for use with Cause doesn't matter.
I see, I've changed it to a NewErrorf
.
c6bade0
to
802550f
Compare
Now that manual splits add a sticky bit to the range descriptor, and the merge queue respects this sticky bit, we can expose functionality to manually unset this sticky bit. If the key to unsplit is not the start of a range, then the unsplit command will throw an error. If the range was manually split (I.E. the sticky bit is set), then the sticky bit will be unset. Otherwise, this command is a no-op. Syntactically, the unsplit command is identical to the split command. Release note (sql change): Add ALTER TABLE/INDEX .. UNSPLIT AT ..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @ajwerner and @nvanbenschoten)
pkg/sql/unsplit_test.go, line 64 at r1 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
Nice tests!
There are a few other logic_tests that we'll want to add as well. To start, I think we'll want to add some basic tests to
alter_table
. Next, we'll want to expand on thecrdb_internal
tests that we added last time. Finally, theranges
test seems like an appropriate place to add some higher-level functional tests.
I can't add tests to ranges
until manual_split_time
is added to SHOW EXPERIMENTAL_RANGES
, but I can do this in a follow-up PR.
pkg/storage/replica_command.go, line 385 at r1 (raw file):
Previously, nvanbenschoten (Nathan VanBenschoten) wrote…
For now, this is probably fine, but at some point we'll probably need a retry loop like we have for
AdminSplit
.
Left a TODO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 2 files at r5, 8 of 8 files at r6.
Reviewable status: complete! 1 of 0 LGTMs obtained (and 1 stale) (waiting on @nvanbenschoten)
bors r+ |
Build failed (retrying...) |
37492: roachprod: create geo-distributed clusters with extra nodes placed at the end r=nvanbenschoten a=ajwerner roachprod: create geo-distributed clusters with extra nodes placed at the end Prior to this change, roachprod would create geo-distributed clusters by placing nodes in AZs in contiguous chunks. If the number of total nodes was not evenly divisible by the number of regions, the first regions would be allocated one additional node. This allocation pattern is rarely desirable. A user will commonly allocate a single extra node as a load generator and would generally like that load node to be the final node and for that final node to be the extra node. This changes the allocation where the extra nodes are placed in the same regions as before but are given node indices at the end rather than with the other nodes in their region. After this change a cluster created with `roachprod create $CLUSTER -n 7 --geo` will look like: ``` ajwerner-test-roachprod-gce: [gce] 12h47m58s remaining ajwerner-test-roachprod-gce-0001 ajwerner-test-roachprod-gce-0001.us-east1-b.cockroach-ephemeral 10.142.0.70 34.74.58.108 ajwerner-test-roachprod-gce-0002 ajwerner-test-roachprod-gce-0002.us-east1-b.cockroach-ephemeral 10.142.0.5 35.237.74.155 ajwerner-test-roachprod-gce-0003 ajwerner-test-roachprod-gce-0003.us-west1-b.cockroach-ephemeral 10.138.0.99 35.199.159.104 ajwerner-test-roachprod-gce-0004 ajwerner-test-roachprod-gce-0004.us-west1-b.cockroach-ephemeral 10.138.0.100 35.197.94.83 ajwerner-test-roachprod-gce-0005 ajwerner-test-roachprod-gce-0005.europe-west2-b.cockroach-ephemeral 10.154.15.237 35.230.143.190 ajwerner-test-roachprod-gce-0006 ajwerner-test-roachprod-gce-0006.europe-west2-b.cockroach-ephemeral 10.154.15.236 35.234.156.121 ajwerner-test-roachprod-gce-0007 ajwerner-test-roachprod-gce-0007.us-east1-b.cockroach-ephemeral 10.142.0.33 35.185.62.76 ``` Instead of the previous: ``` ajwerner-test-old: [gce] 12h19m21s remaining ajwerner-test-old-0001 ajwerner-test-old-0001.us-east1-b.cockroach-ephemeral 10.142.0.139 34.74.150.216 ajwerner-test-old-0002 ajwerner-test-old-0002.us-east1-b.cockroach-ephemeral 10.142.0.140 34.73.154.246 ajwerner-test-old-0003 ajwerner-test-old-0003.us-east1-b.cockroach-ephemeral 10.142.0.141 35.243.176.131 ajwerner-test-old-0004 ajwerner-test-old-0004.us-west1-b.cockroach-ephemeral 10.138.0.71 34.83.16.1 ajwerner-test-old-0005 ajwerner-test-old-0005.us-west1-b.cockroach-ephemeral 10.138.0.60 34.83.78.172 ajwerner-test-old-0006 ajwerner-test-old-0006.europe-west2-b.cockroach-ephemeral 10.154.15.200 35.234.148.191 ajwerner-test-old-0007 ajwerner-test-old-0007.europe-west2-b.cockroach-ephemeral 10.154.15.199 35.242.179.144 ``` Fixes #35866. Release note: None 37603: sql: add ALTER TABLE/INDEX .. UNSPLIT AT .. r=jeffrey-xiao a=jeffrey-xiao Now that manual splits add a sticky bit to the range descriptor, and the merge queue respects this sticky bit, we can expose functionality to manually unset this sticky bit. If the key to unsplit is not the start of a range, then the unsplit command will throw an error. If the range was manually split (I.E. the sticky bit is set), then the sticky bit will be unset. Otherwise, this command is a no-op. Syntactically, the unsplit command is identical to the split command. Release note: None Co-authored-by: Andrew Werner <[email protected]> Co-authored-by: Jeffrey Xiao <[email protected]>
Build succeeded |
Now that manual splits add a sticky bit to the range descriptor, and
the merge queue respects this sticky bit, we can expose functionality to
manually unset this sticky bit.
If the key to unsplit is not the start of a range, then the unsplit
command will throw an error. If the range was manually split (I.E. the
sticky bit is set), then the sticky bit will be unset. Otherwise, this
command is a no-op.
Syntactically, the unsplit command is identical to the split command.
Release note: None