-
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
kv: load-based splitter permits splits between SQL rows, given non-SQL row inputs #103483
Comments
My guess is because these ranges don't grow to exceed the size threshold? |
One interesting thing I have noticed is that Lines 942 to 952 in 5af7d05
So the safe split key function is not idempotent. We should separate split key validation from creating a safe key to split at, although perhaps we cannot always do so. |
The commit to ignore errors from Detailsdiff --git a/pkg/kv/kvserver/split/decider.go b/pkg/kv/kvserver/split/decider.go
index ac099825744..71f27aa5809 100644
--- a/pkg/kv/kvserver/split/decider.go
+++ b/pkg/kv/kvserver/split/decider.go
@@ -329,6 +329,8 @@ func (d *Decider) MaybeSplitKey(ctx context.Context, now time.Time) roachpb.Key
key = d.mu.splitFinder.Key()
if safeKey, err := keys.EnsureSafeSplitKey(key); err == nil {
key = safeKey
+ } else {
+ key = nil
}
}
return key I also checked to see whether non-sql ranges were affected by I tested this with tsd keys initially
Lines 897 to 901 in a0e80d2
Meta1 It appears reasonable to take an approach similar to the weighted splitter, where only safe sampled keys are retained. Since there isn't a risk that system ranges will no longer load based split. There's still a risk that no safe key ever gets retained, however we have been testing this on master/23.1 and have yet to find issues. cockroach/pkg/kv/kvserver/split/weighted_finder.go Lines 127 to 135 in a0e80d2
Footnotes
|
It's interesting that you were unable to reproduce the issue. Your previous comment has me wondering — would we be hitting the issue if So I wonder if a change in SQL-assigned request keys might explain this difference in behavior between 2019 and now. For instance, at some point in there, we started issuing The following script isn't exactly proof of that, but it does demonstrate that we are more precise with specifying the column family suffix for create table kv (k int primary key, v int);
create table kv2 (k int primary key, v int, family (k), family (v));
set tracing = on; select * from kv where k = 5; set tracing = off;
select message from [show trace for session] where message ~ 'executing (Get|Scan)';
message
----------------------------------------------------------------------------
executing Get [/Table/106/1/5/0,/Min), [txn: 88024b8f], [can-forward-ts]
set tracing = on; select * from kv where k between 4 and 5; set tracing = off;
select message from [show trace for session] where message ~ 'executing (Get|Scan)';
message
-------------------------------------------------------------------------------------
executing Scan [/Table/106/1/4,/Table/106/1/6), [txn: 8edc306f], [can-forward-ts]
set tracing = on; select * from kv2 where k = 5; set tracing = off;
select message from [show trace for session] where message ~ 'executing (Get|Scan)';
message
-------------------------------------------------------------------------------------
executing Scan [/Table/110/1/5,/Table/110/1/6), [txn: 96897cc7], [can-forward-ts] |
Previously, the load based range splitter could suggest split keys which were in-between SQL rows. This violated assumptions made in SQL code, which require that rows are never split across ranges. This patch updates the unweighted split finder to only retain safe sample keys. The weighted split finder already does this (e4f003b). Note that the weighted split finder is used by default (>=23.1), whilst the unweighted split finder is used when `kv.allocator.load_based_rebalancing.objective` is set to `qps` (default `cpu`). Informs: cockroachdb#43094 Fixes: cockroachdb#103483 Release note: None
An update. The initial approach (only retain safe samples) could lead to the load based splitter never finding a split. This issue also affects the weighted finder (23.1, not 23.1.0), which already uses this approach. I will open an issue tomorrow. There are two (known) key patterns which will cause the range to never load based split.
The combination means we can't determine safeness with just the sampled key without excluding potentially safe keys. When a range only receives these types of requests it will never split for load, even if it satisfies the load criteria. The proportion (bad/all) keys in requesrs determines the odds we find enougn safe samples to split. Note there haven't been any performance regressions or test failures caused by this. Given we cannot avoid unsafe split keys without also excluding table keys with no column family ID, the best approach I could think of was to stop trying entirely in the load based splitter. Instead, we can update the local admin split command to take a flag indicating the provided split key is potentially unsafe. The command then checks the safeness, if unsafe it will iterate to the first safe key in I drafted a patch doing the above and am running the split tests overnight, as well as tests involving the problem keys at high %. The change isn't without potential risks. The risks boil down to not splitting the load on a range. There is no risk of creating an unsafe split.
Risk 2 and 3 would also arise for size based splits, they both appear unlikely. Risk 1 appears more likely. We could iterate left once to check the key before doing the above iteration. This has issues when we wish to split at the 2nd row in a range. |
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key loggin message is now ordered differently. Informs: cockroachdb#103672 Informs: cockroachdb#103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with just the sampled request keys, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to the next real key, after the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. As such, all safe split key checks are also removed from the `split` pkg, with a warning added. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now sample the real keys, rather than just request keys to determine load-based split points.
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: cockroachdb#103672 Informs: cockroachdb#103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: cockroachdb#103672 Informs: cockroachdb#103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: cockroachdb#103672 Informs: cockroachdb#103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
103690: kvserver: avoid load based splits in middle of SQL row r=nvanbenschoten a=kvoli It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with just the sampled request keys, whether a key is certainly unsafe or safe, so a split key is returned regardless of error. This PR side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Note that the weighted load based split finder, used for CPU splits did not suffer from returning potentially unsafe splits due to e4f003b. However, it was possible that no load-based split key was ever found when using the weighted finder. This was because we discard potentially unsafe samples, which could have been safe split points. This PR reverts commit e4f003b, as the safe split key is enforced elsewhere, mentioned above. Resolves: #103483 Resolves: #103672 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now sample the real keys, rather than just request keys to determine load-based split points. Co-authored-by: Austen McClernon <[email protected]>
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: #103672 Informs: #103483 Release note: None
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: #103672 Informs: #103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: #103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
Previously, there was no way to peak the contents of the load based splitter samples when inspecting nodes. This commit adds string methods for the `UnweightedFinder`, `WeightedFinder` and `Decider`. This commit also swaps the order of the should split check to avoid computation. As a result the output of `cpu_decider_cartesian` changed slightly as the no split key logging message is now ordered differently. Informs: #103672 Informs: #103483 Release note: None
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: #103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
Backport tracking issue: |
It was possible for a SQL row to be torn across two ranges due to the load-based splitter not rejecting potentially unsafe split keys. It is impossible to determine with keys sampled from response spans, whether a key is certainly unsafe or safe. This commit side steps this problem by re-using the `adminSplitWithDescriptor` command to find the first real key, after or at the provided `args.SplitKey`. This ensures that the split key will always be a real key whilst not requiring any checks in the splitter itself. The updated `adminSplitWithDescriptor` is local only and requires opting into finding the first safe key by setting `findFirstSafeKey` to `true`. As such, all safe split key checks are also removed from the `split` pkg, with a warning added that the any split key returned is unsafe. Resolves: cockroachdb#103483 Release note (bug fix): It was possible for a SQL row to be split across two ranges. When this occurred, SQL queries could return unexpected errors. This bug is resolved by these changes, as we now inspect the real keys, rather than just request keys to determine load-based split points.
An important constraint maintained (loosely) by kv is that it will not split between the column families of a single row. This ensures that a single row is never torn across ranges. This constraint is maintained during both size-based split and load-based splits. For size-based splits, split points are derived from the keys in the range. For load-based splits, split points are derived from the requests to the range. This is a subtle distinction, but it means that the load-based splitter has a harder job to do, because while there is a general guarantee that keys in a range will be valid, there is no such guarantee that requests to the range will target valid keys.
We added split key sanitization (a call to
keys.EnsureSafeSplitKey
) to the load-based splitter in fad2024. Shortly after, we added logic to ignore errors from such sanitation in 1d5eb7c, which was important to allow load-based splits in non-SQL keyspaces 1.We've now seen that ignoring errors from key sanitation can allow for invalid key access to keys between column families in a single row to create load-based split points. This can lead to torn rows and panics in SQL queries that access these rows. For example, consider a scan over a table with two column families on each key:
Jira issue: CRDB-28024
Footnotes
why isn't this a problem for size-based splits, which use the same logic but don't ignore the error? ↩
The text was updated successfully, but these errors were encountered: