[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,15 +1535,21 @@ 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))) {
OB_LOG(WARN,
"iterate btree node on level failed",
KR(ret),
K(level),
K(iter_node_count),
K(btree_node_cnt_in_this_range),
K(remaining_btree_node_count),
K(range_count),
K(range_idx));
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),
K(level),
K(iter_node_count),
K(btree_node_cnt_in_this_range),
K(remaining_btree_node_count),
K(range_count),
K(range_idx));
}
}
}
@ -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,41 +511,49 @@ 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 {
// 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));
} 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));
} else if (OB_FAIL(init_raw_iter_for_estimate(iter, start_key, end_key))) {
TRANS_LOG(WARN, "init raw iter fail", K(ret), K(*start_key), K(*end_key));
} else if (NULL == iter) {
ret = OB_ERR_UNEXPECTED;
} else if (OB_FAIL(iter->get_read_handle().split_range(top_level, btree_node_count, range_count, key_array))) {
TRANS_LOG(WARN,
"split range fail",
K(ret),
K(*start_key),
K(*end_key),
K(range_count),
K(top_level),
K(btree_node_count),
K(range_count));
} 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 {
// split range succeed
}
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));
} 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));
} else if (OB_FAIL(init_raw_iter_for_estimate(iter, start_key, end_key))) {
TRANS_LOG(WARN, "init raw iter fail", K(ret), K(*start_key), K(*end_key));
} else if (NULL == iter) {
ret = OB_ERR_UNEXPECTED;
} else if (OB_FAIL(iter->get_read_handle().split_range(top_level, btree_node_count, range_count, key_array))) {
TRANS_LOG(WARN,
"split range fail",
K(ret),
K(*start_key),
K(*end_key),
K(range_count),
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 {
// split range succeed
}
if (OB_NOT_NULL(iter)) {
iter->reset();
raw_iter_alloc_.free(iter);
iter = NULL;
}
if (OB_NOT_NULL(iter)) {
iter->reset();
raw_iter_alloc_.free(iter);
iter = NULL;
}
} while (need_retry);
}
return ret;
}