[CP] [FIX] split_range failed because of concurrent btree split
This commit is contained in:
@ -1535,6 +1535,11 @@ int BtreeRawIterator<BtreeKey, BtreeVal>::split_range(int64_t top_level,
|
||||
for (int64_t iter_node_count = 0; OB_SUCC(ret) && iter_node_count < btree_node_cnt_in_this_range;
|
||||
iter_node_count++) {
|
||||
if (OB_FAIL(iter_->next_on_level(level, key, val))) {
|
||||
if (OB_ITER_END == ret) {
|
||||
// It is not atomic between find_split_range_level and split_range,
|
||||
// so split_range need retry if iterate end on the specific level
|
||||
ret = OB_EAGAIN;
|
||||
} else {
|
||||
OB_LOG(WARN,
|
||||
"iterate btree node on level failed",
|
||||
KR(ret),
|
||||
@ -1546,6 +1551,7 @@ int BtreeRawIterator<BtreeKey, BtreeVal>::split_range(int64_t top_level,
|
||||
K(range_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update remaining btree node count
|
||||
remaining_btree_node_count = remaining_btree_node_count - btree_node_cnt_in_this_range;
|
||||
@ -1561,8 +1567,10 @@ int BtreeRawIterator<BtreeKey, BtreeVal>::split_range(int64_t top_level,
|
||||
}
|
||||
}
|
||||
|
||||
if (range_idx < range_count) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
if (OB_EAGAIN == ret) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(ret) || range_idx < range_count) {
|
||||
ret = OB_SUCC(ret) ? OB_ERR_UNEXPECTED : ret;
|
||||
OB_LOG(WARN,
|
||||
"btree split range: can not get enough sub range",
|
||||
K(btree_node_count),
|
||||
|
@ -511,13 +511,16 @@ int ObQueryEngine::split_range(const ObMemtableKey *start_key,
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
TRANS_LOG(WARN, "range count should be greater than 1 if you try to split range", KR(ret), K(range_count));
|
||||
} else {
|
||||
bool need_retry = false;
|
||||
do {
|
||||
// Here we can not use ESTIMATE_CHILD_COUNT_THRESHOLD to init SEArray due to the stack size limit
|
||||
ObSEArray<ObStoreRowkeyWrapper, ESTIMATE_CHILD_COUNT_THRESHOLD / 2> key_array;
|
||||
if (OB_FAIL(find_split_range_level_(start_key, end_key, range_count, top_level, btree_node_count)) &&
|
||||
OB_ENTRY_NOT_EXIST != ret) {
|
||||
TRANS_LOG(WARN, "estimate size fail", K(ret), K(*start_key), K(*end_key));
|
||||
} else if (OB_ENTRY_NOT_EXIST == ret) {
|
||||
TRANS_LOG(WARN, "range too small, not enough rows ro split", K(ret), K(*start_key), K(*end_key), K(range_count));
|
||||
TRANS_LOG(
|
||||
WARN, "range too small, not enough rows ro split", K(ret), K(*start_key), K(*end_key), K(range_count));
|
||||
} else if (btree_node_count < range_count) {
|
||||
ret = OB_ENTRY_NOT_EXIST;
|
||||
TRANS_LOG(WARN, "branch fan out less than range count", K(btree_node_count), K(range_count));
|
||||
@ -535,6 +538,10 @@ int ObQueryEngine::split_range(const ObMemtableKey *start_key,
|
||||
K(top_level),
|
||||
K(btree_node_count),
|
||||
K(range_count));
|
||||
if (OB_EAGAIN == ret) {
|
||||
need_retry = true;
|
||||
ret = OB_SUCCESS;
|
||||
}
|
||||
} else if (OB_FAIL(convert_keys_to_store_ranges_(start_key, end_key, range_count, key_array, range_array))) {
|
||||
TRANS_LOG(WARN, "convert keys to store ranges failed", KR(ret), K(range_count), K(key_array));
|
||||
} else {
|
||||
@ -546,6 +553,7 @@ int ObQueryEngine::split_range(const ObMemtableKey *start_key,
|
||||
raw_iter_alloc_.free(iter);
|
||||
iter = NULL;
|
||||
}
|
||||
} while (need_retry);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user