-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
keys: Clean up MakeRowSentinelKey
and EnsureSafeSplitKey
#16344
Comments
This is a quick fix; cockroachdb#16344 is tracking the longer-term cleanup. In short, `AdminSplit` does not actually split at the requested key, but rather runs the key through `keys.EnsureSafeSplitKey` first. This means that whoever calls `AdminSplit` with a table key needs to adjust the split key to account for `EnsureSafeSplitKey`'s modification by running the key through `keys.MakeRowSentinelKey`. When using row keys like `/Table/51/` or `/Table/51/1`, this is perfectly safe. In RESTORE, though, we call `MakeRowSentinelKey` on longer keys, like `/Table/51/1/0`. This can create a key in a *different* range, because e.g. negative primary keys may have caused a split at `/Table/51/1/-10`, so the request gets routed to the wrong range even though `EnsureSafeSplitKey` would have selected the right key had the request been routed to the right range. See cockroachdb#16008 for a more detailed explanation. This commit solves the issue by adjusting `AdminSplit` to take both a "span key" and a "split key". The span key is used to route the request to the right range, while the split key contains the `MakeRowSentinelKey` modifications that will be undone by `MakeRowSentinelKey` on the receiver. Fixes cockroachdb#16008.
This is a quick fix; cockroachdb#16344 is tracking the longer-term cleanup. In short, `AdminSplit` does not actually split at the requested key, but rather runs the key through `keys.EnsureSafeSplitKey` first. This means that whoever calls `AdminSplit` with a table key needs to adjust the split key to account for `EnsureSafeSplitKey`'s modification by running the key through `keys.MakeRowSentinelKey`. When using row keys like `/Table/51/` or `/Table/51/1`, this is perfectly safe. In RESTORE, though, we call `MakeRowSentinelKey` on longer keys, like `/Table/51/1/0`. This can create a key in a *different* range, because e.g. negative primary keys may have caused a split at `/Table/51/1/-10`, so the request gets routed to the wrong range even though `EnsureSafeSplitKey` would have selected the right key had the request been routed to the right range. See cockroachdb#16008 for a more detailed explanation. This commit solves the issue by adjusting `AdminSplit` to take both a "span key" and a "split key". The span key is used to route the request to the right range, while the split key contains the `MakeRowSentinelKey` modifications that will be undone by `MakeRowSentinelKey` on the receiver. Fixes cockroachdb#16008.
@bdarnell Maybe I could have a try for this. |
@a6802739 Go ahead! |
@bdarnell, So we need to cleanup the usage of I have a confusion here, after we call |
The problem is that the way we're using EnsureSafeSplitKey, it removes something, but it's not always the family ID. We want to get rid of most uses of both of these functions. I think what we want to do is remove the calls to MakeRowSentinelKey from config.go and restore.go and the call to EnsureSafeSplitKey in AdminSplit. MVCCFindSplitKey should call both MakeRowSentinelKey and EnsureSafeSplitKey to get a valid split key, and the SQL |
@bdarnell So |
I said earlier that MVCCFindSplitKey should do both, but now I think that was a mistake. MVCCFindSplitKey should only call EnsureSafeSplitKey to remove the family ID from the key on disk. |
We could end up splitting between column families of the same row, which is illegal. Unfortunately the KV layer has to uphold invariants here that it doesn't quite have introspection into, but after this commit it hopefully stops breaking them. See cockroachdb#16344 for some additional history. Possibly the solution for cockroachdb#39794. Possibly the solution for cockroachdb#36834. Possibly the solution for cockroachdb#36356. (Intentionally not closing the above; leaving that to the SQL folks). Closes cockroachdb#42056 (which is the go-to for reading up on this issue). Release note (bug fix): prevent a number of panics from the SQL layer caused by an invalid range split. These would usually manifest with messages mentioning encoding errors ("found null on not null column" but also possibly various others).
We could end up splitting between column families of the same row, which is illegal. Unfortunately the KV layer has to uphold invariants here that it doesn't quite have introspection into, but after this commit it hopefully stops breaking them. See cockroachdb#16344 for some additional history. Possibly the solution for cockroachdb#39794. Possibly the solution for cockroachdb#36834. Possibly the solution for cockroachdb#36356. (Intentionally not closing the above; leaving that to the SQL folks). Closes cockroachdb#42056 (which is the go-to for reading up on this issue). Release note (bug fix): prevent a number of panics from the SQL layer caused by an invalid range split. These would usually manifest with messages mentioning encoding errors ("found null on not null column" but also possibly various others).
42833: storage: call EnsureSafeSplitKey during load-based splits r=bdarnell a=tbg We could end up splitting between column families of the same row, which is illegal. Unfortunately the KV layer has to uphold invariants here that it doesn't quite have introspection into, but after this commit it hopefully stops breaking them. See #16344 for some additional history. Possibly the solution for #39794. Possibly the solution for #36834. Possibly the solution for #36356. (Intentionally not closing the above; leaving that to the SQL folks). Closes #42056 (which is the go-to for reading up on this issue). Release note (bug fix): prevent a number of panics from the SQL layer caused by an invalid range split. These would usually manifest with messages mentioning encoding errors ("found null on not null column" but also possibly various others). Co-authored-by: Tobias Schottdorf <[email protected]>
We could end up splitting between column families of the same row, which is illegal. Unfortunately the KV layer has to uphold invariants here that it doesn't quite have introspection into, but after this commit it hopefully stops breaking them. See cockroachdb#16344 for some additional history. Possibly the solution for cockroachdb#39794. Possibly the solution for cockroachdb#36834. Possibly the solution for cockroachdb#36356. (Intentionally not closing the above; leaving that to the SQL folks). Closes cockroachdb#42056 (which is the go-to for reading up on this issue). Release note (bug fix): prevent a number of panics from the SQL layer caused by an invalid range split. These would usually manifest with messages mentioning encoding errors ("found null on not null column" but also possibly various others).
This argument was added in 9234460 as a fix for cockroachdb#16008 and a short-term workaround for the cleanup in cockroachdb#16344. That cleanup was addressed in cockroachdb#16649, which removed the one place where spanKey and splitKey diverged (https://github.com/cockroachdb/cockroach/pull/16649/files#diff-6955fb0c3216b1d7d4292ccdf2e18dcf). They have been identical in all uses of AdminSplit ever since.
This argument was added in 9234460 as a fix for cockroachdb#16008 and a short-term workaround for the cleanup in cockroachdb#16344. That cleanup was addressed in cockroachdb#16649, which removed the one place where spanKey and splitKey diverged (https://github.com/cockroachdb/cockroach/pull/16649/files#diff-6955fb0c3216b1d7d4292ccdf2e18dcf). They have been identical in all uses of AdminSplit ever since.
Our mechanisms for avoiding splits in the middle of a row are a bit of a mess (see #16008 (comment)).
AdminSplit
does not split at the requested key: if the key points to the/Table
keyspace then it removes a trailing integer from the key which is assumed to be the column family ID. This is fine when splitting at a key that actually exists (which is true for all size-based splits), but it is difficult to synthesize keys that work correctly in this model (e.g. at table boundaries).We currently use
MakeRowSentinelKey
to add a dummy column family ID with a value of 0 (inconfig.go
and restore.go), but this is not really correct. It works OK inconfig.go
where it applies at the table level (and the added zero sorts before all the index IDs that are the normal inhabitants of this level), but inrestore.go
this zero is intermingled with actual row data, and it sorts higher than any negative values that may be stored in the primary key (assuming an integer PK).We should fix this by making
AdminSplit
act on the requested key as given. The key selection process is responsible for choosing a key that is not in the middle of a row. That is,MVCCFindSplitKey
and the SQLSPLIT AT
command should remove the column family ID from the keys that they use, and splits at the boundaries of tables and indexes should not add them.Compatibility notes: Splits performed by the split queue are always executed on the same node that selects the keys, so the split queue is safe in mixed-version environments as this change rolls out. The SPLIT AT and RESTORE commands execute splits remotely, which requires some care (or a warning in the release notes that these commands may not be used during a rolling upgrade).
The text was updated successfully, but these errors were encountered: