diff options
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r-- | storage/innobase/dict/dict0crea.cc | 7 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 6 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.cc | 35 | ||||
-rw-r--r-- | storage/innobase/dict/dict0stats.cc | 129 |
4 files changed, 131 insertions, 46 deletions
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index fab6ff4db8e..e2afe17f892 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -755,11 +755,12 @@ dict_create_index_tree_step( search_tuple = dict_create_search_tuple(node->ind_row, node->heap); node->page_no = FIL_NULL; + pcur.btr_cur.page_cur.index = + UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes); dberr_t err = - btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes), - search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF, - &pcur, &mtr); + btr_pcur_open(search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF, + &pcur, 0, &mtr); if (err != DB_SUCCESS) { func_exit: diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 51bb5dc4eba..e90dff03e16 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -4147,8 +4147,9 @@ void dict_set_corrupted(dict_index_t *index, const char *ctx) dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 2); + cursor.page_cur.index = sys_index; - if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE, + if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_LE, BTR_MODIFY_LEAF, &cursor, &mtr) != DB_SUCCESS) { goto fail; @@ -4222,8 +4223,9 @@ dict_index_set_merge_threshold( dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 2); + cursor.page_cur.index = sys_index; - if (btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE, + if (btr_cur_search_to_nth_level(0, tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF, &cursor, &mtr) != DB_SUCCESS) { goto func_exit; diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 0e937ebe63b..1ee10ec8232 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -215,8 +215,9 @@ dict_startscan_system( mtr_t* mtr, /*!< in: the mini-transaction */ dict_table_t* table) /*!< in: system table */ { - if (btr_pcur_open_at_index_side(true, table->indexes.start, BTR_SEARCH_LEAF, - pcur, true, 0, mtr) != DB_SUCCESS) + btr_pcur_init(pcur); + if (pcur->open_leaf(true, table->indexes.start, BTR_SEARCH_LEAF, mtr) != + DB_SUCCESS) return nullptr; const rec_t *rec; do @@ -1316,8 +1317,9 @@ static dberr_t dict_load_columns(dict_table_t *table, unsigned use_uncommitted, mach_write_to_8(table_id, table->id); dfield_set_data(&dfield, table_id, 8); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; - dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS) { goto func_exit; @@ -1446,9 +1448,9 @@ dict_load_virtual_col(dict_table_t *table, bool uncommitted, ulint nth_v_col) dfield_set_data(&dfield[1], vcol_pos, 4); dict_index_copy_types(&tuple, sys_virtual_index, 2); + pcur.btr_cur.page_cur.index = sys_virtual_index; - dberr_t err = btr_pcur_open_on_user_rec(sys_virtual_index, &tuple, - PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS) { goto func_exit; @@ -1686,8 +1688,9 @@ static dberr_t dict_load_fields(dict_index_t *index, bool uncommitted, mach_write_to_8(index_id, index->id); dfield_set_data(&dfield, index_id, 8); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; - dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple, + dberr_t error = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (error != DB_SUCCESS) { @@ -1944,8 +1947,9 @@ dberr_t dict_load_indexes(dict_table_t *table, bool uncommitted, mach_write_to_8(table_id, table->id); dfield_set_data(&dfield, table_id, 8); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; - dberr_t error = btr_pcur_open_on_user_rec(sys_index, &tuple, + dberr_t error = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (error != DB_SUCCESS) { @@ -2338,11 +2342,12 @@ static dict_table_t *dict_load_table_one(const span<const char> &name, }; dfield_set_data(&dfield, name.data(), name.size()); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; bool uncommitted = false; reload: mtr.start(); - dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS || !btr_pcur_is_on_user_rec(&pcur)) { @@ -2596,10 +2601,11 @@ dict_load_table_on_id( mach_write_to_8(id_buf, table_id); dfield_set_data(&dfield, id_buf, 8); dict_index_copy_types(&tuple, sys_table_ids, 1); + pcur.btr_cur.page_cur.index = sys_table_ids; dict_table_t* table = nullptr; - if (btr_pcur_open_on_user_rec(sys_table_ids, &tuple, PAGE_CUR_GE, + if (btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr) == DB_SUCCESS && btr_pcur_is_on_user_rec(&pcur)) { @@ -2703,9 +2709,10 @@ static dberr_t dict_load_foreign_cols(dict_foreign_t *foreign, trx_id_t trx_id) dfield_set_data(&dfield, foreign->id, id_len); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; mem_heap_t* heap = nullptr; - dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS) { goto func_exit; @@ -2877,11 +2884,12 @@ dict_load_foreign( }; dfield_set_data(&dfield, id.data(), id.size()); dict_index_copy_types(&tuple, sys_index, 1); + pcur.btr_cur.page_cur.index = sys_index; mtr.start(); mem_heap_t* heap = nullptr; - dberr_t err = btr_pcur_open_on_user_rec(sys_index, &tuple, PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS) { goto err_exit; @@ -3090,8 +3098,9 @@ start_load: mtr.start(); dfield_set_data(&dfield, table_name, strlen(table_name)); dict_index_copy_types(&tuple, sec_index, 1); + pcur.btr_cur.page_cur.index = sec_index; - dberr_t err = btr_pcur_open_on_user_rec(sec_index, &tuple, PAGE_CUR_GE, + dberr_t err = btr_pcur_open_on_user_rec(&tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); if (err != DB_SUCCESS) { DBUG_RETURN(err); @@ -3192,7 +3201,6 @@ next_rec: load_next_index: mtr.commit(); - ut_free(pcur.old_rec_buf); if ((sec_index = dict_table_get_next_index(sec_index))) { /* Switch to scan index on REF_NAME, fk_max_recusive_level @@ -3202,5 +3210,6 @@ load_next_index: goto start_load; } + ut_free(pcur.old_rec_buf); DBUG_RETURN(DB_SUCCESS); } diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 84fac55a304..c7355f85c2e 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1560,6 +1560,96 @@ empty_table: return err; } +/** Open a cursor at the first page in a tree level. +@param page_cur cursor +@param level level to search for (0=leaf) +@param mtr mini-transaction */ +static dberr_t page_cur_open_level(page_cur_t *page_cur, ulint level, + mtr_t *mtr) +{ + mem_heap_t *heap= nullptr; + rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; + rec_offs *offsets= offsets_; + dberr_t err; + + dict_index_t *const index= page_cur->index; + + rec_offs_init(offsets_); + ut_ad(level != ULINT_UNDEFINED); + ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_SX_LOCK)); + ut_ad(mtr->get_savepoint() == 1); + + uint32_t page= index->page; + + for (ulint height = ULINT_UNDEFINED;; height--) + { + buf_block_t* block= + btr_block_get(*index, page, RW_S_LATCH, + !height && !index->is_clust(), mtr, &err); + if (!block) + break; + + const uint32_t l= btr_page_get_level(block->page.frame); + + if (height == ULINT_UNDEFINED) + { + ut_ad(!heap); + /* We are in the root node */ + height= l; + if (UNIV_UNLIKELY(height < level)) + return DB_CORRUPTION; + } + else if (UNIV_UNLIKELY(height != l) || page_has_prev(block->page.frame)) + { + err= DB_CORRUPTION; + break; + } + + page_cur_set_before_first(block, page_cur); + + if (height == level) + break; + + ut_ad(height); + + if (!page_cur_move_to_next(page_cur)) + { + err= DB_CORRUPTION; + break; + } + + offsets= rec_get_offsets(page_cur->rec, index, offsets, 0, ULINT_UNDEFINED, + &heap); + page= btr_node_ptr_get_child_page_no(page_cur->rec, offsets); + } + + if (UNIV_LIKELY_NULL(heap)) + mem_heap_free(heap); + + /* Release all page latches except the one on the desired page. */ + const auto end= mtr->get_savepoint(); + if (end > 1) + mtr->rollback_to_savepoint(1, end - 1); + + return err; +} + +/** Open a cursor at the first page in a tree level. +@param page_cur cursor +@param level level to search for (0=leaf) +@param mtr mini-transaction +@param index index tree */ +static dberr_t btr_pcur_open_level(btr_pcur_t *pcur, ulint level, mtr_t *mtr, + dict_index_t *index) +{ + pcur->latch_mode= BTR_SEARCH_TREE; + pcur->search_mode= PAGE_CUR_G; + pcur->pos_state= BTR_PCUR_IS_POSITIONED; + pcur->btr_cur.page_cur.index= index; + return page_cur_open_level(&pcur->btr_cur.page_cur, level, mtr); +} + + /* @{ Pseudo code about the relation between the following functions let N = N_SAMPLE_PAGES(index) @@ -1616,7 +1706,8 @@ dict_stats_analyze_index_level( DEBUG_PRINTF(" %s(table=%s, index=%s, level=" ULINTPF ")\n", __func__, index->table->name, index->name, level); - ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); + *total_recs = 0; + *total_pages = 0; n_uniq = dict_index_get_n_unique(index); @@ -1649,9 +1740,7 @@ dict_stats_analyze_index_level( /* Position pcur on the leftmost record on the leftmost page on the desired level. */ - if (btr_pcur_open_at_index_side( - true, index, BTR_SEARCH_TREE_ALREADY_S_LATCHED, - &pcur, true, level, mtr) != DB_SUCCESS + if (btr_pcur_open_level(&pcur, level, mtr, index) != DB_SUCCESS || !btr_pcur_move_to_next_on_page(&pcur)) { goto func_exit; } @@ -1661,21 +1750,10 @@ dict_stats_analyze_index_level( /* The page must not be empty, except when it is the root page (and the whole index is empty). */ ut_ad(btr_pcur_is_on_user_rec(&pcur) || page_is_leaf(page)); - ut_ad(btr_pcur_get_rec(&pcur) - == page_rec_get_next_const(page_get_infimum_rec(page))); prev_rec = NULL; prev_rec_is_copied = false; - /* no records by default */ - *total_recs = 0; - - *total_pages = 0; - - if (page_has_prev(page) || btr_page_get_level(page) != level) { - goto func_exit; - } - if (REC_INFO_MIN_REC_FLAG & rec_get_info_bits( btr_pcur_get_rec(&pcur), page_is_comp(page))) { ut_ad(btr_pcur_is_on_user_rec(&pcur)); @@ -1728,10 +1806,7 @@ dict_stats_analyze_index_level( if (level == 0 && !srv_stats_include_delete_marked - && rec_get_deleted_flag( - rec, - page_is_comp(btr_pcur_get_page(&pcur)))) { - + && rec_get_deleted_flag(rec, page_rec_is_comp(rec))) { if (rec_is_last_on_page && !prev_rec_is_copied && prev_rec != NULL) { @@ -1811,7 +1886,7 @@ dict_stats_analyze_index_level( records on this level at some point we will jump from one page to the next and then rec and prev_rec will be on different pages and - btr_pcur_move_to_next_user_rec() will release the + btr_cur_move_to_next_user_rec() will release the latch on the page that prev_rec is on */ prev_rec = rec_copy_prefix_to_buf( rec, index, n_uniq, @@ -1820,7 +1895,7 @@ dict_stats_analyze_index_level( } else { /* still on the same page, the next call to - btr_pcur_move_to_next_user_rec() will not jump + btr_cur_move_to_next_user_rec() will not jump on the next page, we can simply assign pointers instead of copying the records like above */ @@ -1891,7 +1966,6 @@ dict_stats_analyze_index_level( } #endif /* UNIV_STATS_DEBUG */ - btr_leaf_page_release(btr_pcur_get_block(&pcur), BTR_SEARCH_LEAF, mtr); func_exit: ut_free(prev_rec_buf); mem_heap_free(heap); @@ -2280,7 +2354,6 @@ dict_stats_analyze_index_for_n_prefix( n_prefix, n_diff_data->n_diff_on_level); #endif - ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_SX_LOCK)); ut_ad(n_diff_data->level); /* Position pcur on the leftmost record on the leftmost page @@ -2289,9 +2362,7 @@ dict_stats_analyze_index_for_n_prefix( n_diff_data->n_diff_all_analyzed_pages = 0; n_diff_data->n_external_pages_sum = 0; - if (btr_pcur_open_at_index_side(true, index, - BTR_SEARCH_TREE_ALREADY_S_LATCHED, - &pcur, true, n_diff_data->level, mtr) + if (btr_pcur_open_level(&pcur, n_diff_data->level, mtr, index) != DB_SUCCESS || !btr_pcur_move_to_next_on_page(&pcur)) { return; @@ -2680,6 +2751,7 @@ empty_index: mtr.commit(); mtr.start(); mtr_sx_lock_index(index, &mtr); + ut_ad(mtr.get_savepoint() == 1); buf_block_t *root = btr_root_block_get(index, RW_S_LATCH, &mtr, &err); if (!root || root_level != btr_page_get_level(root->page.frame) @@ -2695,7 +2767,7 @@ empty_index: break; } - mtr.memo_release(root, MTR_MEMO_PAGE_S_FIX); + mtr.rollback_to_savepoint(1); /* check whether we should pick the current level; we pick level 1 even if it does not have enough @@ -2757,6 +2829,7 @@ empty_index: break; } + mtr.rollback_to_savepoint(1); dict_stats_analyze_index_level(index, level, n_diff_on_level, @@ -2764,7 +2837,7 @@ empty_index: &total_pages, n_diff_boundaries, &mtr); - + mtr.rollback_to_savepoint(1); level_is_analyzed = true; if (level == 1 |