[CP] [FIX] split_range failed because of concurrent btree split

This commit is contained in:
ZenoWang
2024-02-09 17:44:22 +00:00
committed by ob-robot
parent 0b6b6c3e57
commit 59fa4e7f0c
2 changed files with 61 additions and 45 deletions

View File

@ -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),

View File

@ -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;
}