diff options
Diffstat (limited to 'storage/innobase')
28 files changed, 630 insertions, 455 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 04677c1e1d3..e5befe2cddd 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -726,7 +726,7 @@ btr_page_get_father_node_ptr_func( btr_cur_t* cursor, /*!< in: cursor pointing to user record, out: cursor on node pointer record, its page x-latched */ - ulint latch_mode,/*!< in: BTR_CONT_MODIFY_TREE + btr_latch_mode latch_mode,/*!< in: BTR_CONT_MODIFY_TREE or BTR_CONT_SEARCH_TREE */ mtr_t* mtr) /*!< in: mtr */ { diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 336636bd8e7..7954c216c86 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -196,7 +196,7 @@ btr_rec_free_externally_stored_fields( void btr_cur_latch_leaves( buf_block_t* block, - ulint latch_mode, + btr_latch_mode latch_mode, btr_cur_t* cursor, mtr_t* mtr, btr_latch_leaves_t* latch_leaves) @@ -223,6 +223,8 @@ btr_cur_latch_leaves( static_assert(BTR_SEARCH_LEAF & BTR_SEARCH_TREE, ""); switch (latch_mode) { + default: + break; uint32_t left_page_no; uint32_t right_page_no; ulint save; @@ -392,10 +394,10 @@ unreadable: /* Relax the assertion in rec_init_offsets(). */ ut_ad(!index->in_instant_init); ut_d(index->in_instant_init = true); - err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF, - &cur, 0, mtr); + err = cur.open_leaf(true, index, BTR_SEARCH_LEAF, mtr); ut_d(index->in_instant_init = false); if (err != DB_SUCCESS) { + index->table->file_unreadable = true; index->table->corrupted = true; return err; } @@ -738,7 +740,7 @@ bool btr_cur_optimistic_latch_leaves( buf_block_t* block, ib_uint64_t modify_clock, - ulint* latch_mode, + btr_latch_mode* latch_mode, btr_cur_t* cursor, mtr_t* mtr) { @@ -803,7 +805,7 @@ btr_cur_optimistic_latch_leaves( buf_page_optimistic_get() buffer-fixes it again. */ ut_ad(2 <= block->page.buf_fix_count()); - *latch_mode = mode; + *latch_mode = btr_latch_mode(mode); return(true); } else { /* release the block and decrement of @@ -828,9 +830,7 @@ at the latch_mode. @param latch_mode in/out: pointer to latch_mode @return intention for latching tree */ static -btr_intention_t -btr_cur_get_and_clear_intention( - ulint *latch_mode) +btr_intention_t btr_cur_get_and_clear_intention(btr_latch_mode *latch_mode) { btr_intention_t intention; @@ -845,7 +845,8 @@ btr_cur_get_and_clear_intention( /* both or unknown */ intention = BTR_INTENTION_BOTH; } - *latch_mode &= ulint(~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE)); + *latch_mode = btr_latch_mode( + *latch_mode & ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE)); return(intention); } @@ -1232,7 +1233,8 @@ or on a page infimum record. TRANSACTIONAL_TARGET dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level, const dtuple_t *tuple, - page_cur_mode_t mode, ulint latch_mode, + page_cur_mode_t mode, + btr_latch_mode latch_mode, btr_cur_t *cursor, mtr_t *mtr, ib_uint64_t autoinc) { @@ -2408,6 +2410,239 @@ func_exit: DBUG_RETURN(err); } +dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index, + btr_latch_mode latch_mode, mtr_t *mtr) +{ + ulint node_ptr_max_size= srv_page_size / 2; + btr_intention_t lock_intention; + buf_block_t *tree_blocks[BTR_MAX_LEVELS]; // FIXME: just use mtr->m_memo + ulint tree_savepoints[BTR_MAX_LEVELS]; + ulint n_blocks= 0; + ulint n_releases= 0; + mem_heap_t *heap= nullptr; + rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; + rec_offs *offsets= offsets_; + dberr_t err; + + rec_offs_init(offsets_); + + const bool latch_by_caller= latch_mode & BTR_ALREADY_S_LATCHED; + latch_mode = btr_latch_mode(latch_mode & ~BTR_ALREADY_S_LATCHED); + + lock_intention= btr_cur_get_and_clear_intention(&latch_mode); + + /* This function doesn't need to lock left page of the leaf page */ + if (latch_mode == BTR_SEARCH_PREV) + latch_mode= BTR_SEARCH_LEAF; + else if (latch_mode == BTR_MODIFY_PREV) + latch_mode= BTR_MODIFY_LEAF; + + /* Store the position of the tree latch we push to mtr so that we + know how to release it when we have latched the leaf node */ + + auto savepoint= mtr->get_savepoint(); + + rw_lock_type_t upper_rw_latch= RW_X_LATCH; + + switch (latch_mode) { + case BTR_CONT_MODIFY_TREE: + case BTR_CONT_SEARCH_TREE: + abort(); + break; + case BTR_MODIFY_TREE: + /* Most of delete-intended operations are purging. Free blocks + and read IO bandwidth should be prioritized for them, when the + history list is growing huge. */ + savepoint+= sizeof(mtr_memo_slot_t); + if (lock_intention == BTR_INTENTION_DELETE + && buf_pool.n_pend_reads + && trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH) + mtr_x_lock_index(index, mtr); + else + mtr_sx_lock_index(index, mtr); + break; + default: + ut_ad(!latch_by_caller || + mtr->memo_contains_flagged(&index->lock, + MTR_MEMO_SX_LOCK | MTR_MEMO_S_LOCK)); + upper_rw_latch= RW_S_LATCH; + if (latch_by_caller) + break; + ut_ad(latch_mode != BTR_SEARCH_TREE); + savepoint+= sizeof(mtr_memo_slot_t); + mtr_s_lock_index(index, mtr); + } + + ut_ad(savepoint == mtr->get_savepoint()); + + const rw_lock_type_t root_leaf_rw_latch= + btr_cur_latch_for_root_leaf(latch_mode); + + this->index = index; + + page_id_t page_id(index->table->space_id, index->page); + const auto zip_size= index->table->space->zip_size(); + + if (root_leaf_rw_latch == RW_X_LATCH) + node_ptr_max_size= btr_node_ptr_max_size(index); + + for (ulint height= ULINT_UNDEFINED;;) + { + ut_ad(n_blocks < BTR_MAX_LEVELS); +#if 0 // FIXME: encryption.innodb_onlinealter_encryption innodb.alter_algorithm + ut_ad(savepoint + n_blocks * sizeof(mtr_memo_slot_t) == mtr->get_savepoint()); +#endif + tree_savepoints[n_blocks]= mtr->get_savepoint(); + + const rw_lock_type_t rw_latch= height && latch_mode != BTR_MODIFY_TREE + ? upper_rw_latch + : RW_NO_LATCH; + buf_block_t *block= buf_page_get_gen(page_id, zip_size, rw_latch, nullptr, + BUF_GET, mtr, &err, + !height && !index->is_clust()); + ut_ad(!block == (err != DB_SUCCESS)); + tree_blocks[n_blocks]= block; + + if (!block) + { + if (err == DB_DECRYPTION_FAILED) + btr_decryption_failed(*index); + break; + } + + const page_t *page= buf_block_get_frame(block); + + if (first) + page_cur_set_before_first(block, &page_cur); + else + page_cur_set_after_last(block, &page_cur); + + ut_ad(fil_page_index_page_check(page)); + ut_ad(index->id == btr_page_get_index_id(page)); + + if (height == ULINT_UNDEFINED) + { + /* We are in the root node */ + height= btr_page_get_level(page); + if (height); + else if (upper_rw_latch != root_leaf_rw_latch) + { + /* We should retry to get the page, because the root page + is latched with different level as a leaf page. */ + ut_ad(n_blocks == 0); + ut_ad(root_leaf_rw_latch != RW_NO_LATCH); + upper_rw_latch= root_leaf_rw_latch; + mtr->rollback_to_savepoint(savepoint); + continue; + } + else + { + reached_leaf: + if (rw_latch == RW_NO_LATCH) + btr_cur_latch_leaves(block, latch_mode, this, mtr); + + switch (latch_mode) { + case BTR_MODIFY_TREE: + case BTR_CONT_MODIFY_TREE: + case BTR_CONT_SEARCH_TREE: + break; + default: + if (UNIV_UNLIKELY(srv_read_only_mode)) + break; + if (!latch_by_caller) + /* Release the tree s-latch */ + mtr->release_s_latch_at_savepoint(savepoint - + sizeof(mtr_memo_slot_t), + &index->lock); + + /* release upper blocks */ + for (; n_releases < n_blocks; n_releases++) + mtr_release_block_at_savepoint(mtr, +#if 0 + savepoint + n_releases, +#else + tree_savepoints[n_releases], +#endif + tree_blocks[n_releases]); + } + break; + } + } + else if (UNIV_UNLIKELY(height != btr_page_get_level(page))) + { + corrupted: + err= DB_CORRUPTION; + break; + } + + if (!height) + goto reached_leaf; + + height--; + + if (first + ? !page_cur_move_to_next(&page_cur) + : !page_cur_move_to_prev(&page_cur)) + goto corrupted; + + const rec_t *node_ptr= page_cur.rec; + offsets= rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED, + &heap); + + ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH); + + if (latch_mode != BTR_MODIFY_TREE); + else if (btr_cur_need_opposite_intention(page, lock_intention, node_ptr)) + { + /* If the rec is the first or last in the page for pessimistic + delete intention, it might cause node_ptr insert for the upper + level. We should change the intention and retry. */ + + mtr->rollback_to_savepoint(savepoint); + lock_intention= BTR_INTENTION_BOTH; + page_id.set_page_no(index->page); + height= ULINT_UNDEFINED; + n_blocks= 0; + n_releases= 0; + continue; + } + else if (!btr_cur_will_modify_tree(index, page, lock_intention, node_ptr, + node_ptr_max_size, zip_size, mtr)) + { + ut_ad(n_releases <= n_blocks); + /* release non-leaf pages (except the root) */ + for (; n_releases < n_blocks; n_releases++) + if (n_releases) + mtr_release_block_at_savepoint(mtr, tree_savepoints[n_releases], + tree_blocks[n_releases]); + } + + if (latch_mode == BTR_MODIFY_TREE && !height) + { + ut_ad(upper_rw_latch == RW_X_LATCH); + /* we should U-latch root page, if released already. + It contains seg_header. */ + if (n_releases) + mtr_block_sx_latch_at_savepoint(mtr, tree_savepoints[0], + tree_blocks[0]); + + /* x-latch the branch blocks not released yet. */ + for (ulint i= n_releases; i <= n_blocks; i++) + mtr_block_x_latch_at_savepoint(mtr, + tree_savepoints[i], tree_blocks[i]); + } + + /* Go to the child node */ + page_id.set_page_no(btr_node_ptr_get_child_page_no(node_ptr, offsets)); + n_blocks++; + } + + if (UNIV_LIKELY_NULL(heap)) + mem_heap_free(heap); + + return err; +} + /*****************************************************************//** Opens a cursor at either end of an index. */ dberr_t @@ -2415,7 +2650,7 @@ btr_cur_open_at_index_side( bool from_left, /*!< in: true if open to the low end, false if to the high end */ dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: latch mode */ + btr_latch_mode latch_mode, /*!< in: latch mode */ btr_cur_t* cursor, /*!< in/out: cursor */ ulint level, /*!< in: level to search for (0=leaf). */ @@ -2440,7 +2675,7 @@ btr_cur_open_at_index_side( ut_ad(level != ULINT_UNDEFINED); const bool latch_by_caller = latch_mode & BTR_ALREADY_S_LATCHED; - latch_mode &= ulint(~BTR_ALREADY_S_LATCHED); + latch_mode = btr_latch_mode(latch_mode & ~BTR_ALREADY_S_LATCHED); lock_intention = btr_cur_get_and_clear_intention(&latch_mode); @@ -2607,20 +2842,15 @@ btr_cur_open_at_index_side( ut_ad(upper_rw_latch == RW_S_LATCH); ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX)); - - if (latch_by_caller) { - /* to exclude modifying tree operations - should sx-latch the index. */ - ut_ad(mtr->memo_contains(index->lock, - MTR_MEMO_SX_LOCK)); - /* because has sx-latch of index, - can release upper blocks. */ - for (; n_releases < n_blocks; n_releases++) { - mtr_release_block_at_savepoint( - mtr, - tree_savepoints[n_releases], - tree_blocks[n_releases]); - } + ut_ad(mtr->memo_contains(index->lock, + MTR_MEMO_SX_LOCK)); + /* because has sx-latch of index, + can release upper blocks. */ + for (; n_releases < n_blocks; n_releases++) { + mtr_release_block_at_savepoint( + mtr, + tree_savepoints[n_releases], + tree_blocks[n_releases]); } } @@ -2740,7 +2970,7 @@ if the index is unavailable */ bool btr_cur_open_at_rnd_pos( dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_cur_t* cursor, /*!< in/out: B-tree cursor */ mtr_t* mtr) /*!< in: mtr */ { @@ -2890,7 +3120,7 @@ btr_cur_open_at_rnd_pos( mtr); } - /* btr_cur_open_at_index_side() and + /* btr_cur_t::open_leaf() and btr_cur_search_to_nth_level() release tree s-latch here.*/ switch (latch_mode) { @@ -6055,8 +6285,8 @@ public: } ut_ad(page_rec_is_supremum(page_cur_get_rec(&m_page_cur))); - /* The range specified is wihout a right border, just 'x > 123' or 'x >= - 123' and btr_cur_open_at_index_side() positioned the cursor on the + /* The range specified is without a right border, just 'x > 123' + or 'x >= 123' and search_on_page() positioned the cursor on the supremum record on the rightmost page, which must not be counted. */ return false; } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 86b16b4408b..eaecc300c90 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -253,11 +253,12 @@ otherwise. */ struct optimistic_latch_leaves { btr_pcur_t *const cursor; - ulint *latch_mode; + btr_latch_mode *latch_mode; mtr_t *const mtr; - optimistic_latch_leaves(btr_pcur_t *cursor, ulint *latch_mode, mtr_t *mtr) - :cursor(cursor), latch_mode(latch_mode), mtr(mtr) {} + optimistic_latch_leaves(btr_pcur_t *cursor, btr_latch_mode *latch_mode, + mtr_t *mtr) + : cursor(cursor), latch_mode(latch_mode), mtr(mtr) {} bool operator() (buf_block_t *hint) const { @@ -289,7 +290,7 @@ record with the same unique field values as in the stored record, btr_pcur_t::NOT_SAME cursor position is not on user rec or points on the record with not the samebuniq field values as in the stored */ btr_pcur_t::restore_status -btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr) +btr_pcur_t::restore_position(btr_latch_mode restore_latch_mode, mtr_t *mtr) { dict_index_t* index; dtuple_t* tuple; @@ -309,10 +310,9 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr) /* In these cases we do not try an optimistic restoration, but always do a search */ - if (btr_cur_open_at_index_side( - rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, - index, restore_latch_mode, - &btr_cur, 0, mtr) != DB_SUCCESS) { + if (btr_cur.open_leaf(rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE, + index, restore_latch_mode, mtr) + != DB_SUCCESS) { return restore_status::CORRUPTED; } @@ -330,6 +330,8 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr) ut_a(old_n_fields); switch (restore_latch_mode) { + default: + break; case BTR_SEARCH_LEAF: case BTR_MODIFY_LEAF: case BTR_SEARCH_PREV: @@ -553,7 +555,7 @@ btr_pcur_move_backward_from_page( ut_ad(btr_pcur_is_before_first_on_page(cursor)); ut_ad(!btr_pcur_is_before_first_in_tree(cursor)); - const ulint latch_mode = cursor->latch_mode; + const auto latch_mode = cursor->latch_mode; ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF); btr_pcur_store_position(cursor, mtr); @@ -565,7 +567,8 @@ btr_pcur_move_backward_from_page( static_assert(BTR_SEARCH_PREV == (4 | BTR_SEARCH_LEAF), ""); static_assert(BTR_MODIFY_PREV == (4 | BTR_MODIFY_LEAF), ""); - if (UNIV_UNLIKELY(cursor->restore_position(4 | latch_mode, mtr) + if (UNIV_UNLIKELY(cursor->restore_position( + btr_latch_mode(4 | latch_mode), mtr) == btr_pcur_t::CORRUPTED)) { return true; } diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index ce31721bd72..b7f245a3787 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 diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 6e70cbf7547..a5806de7b6a 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1560,6 +1560,25 @@ empty_table: return err; } +/** Open persistent cursor at the first page in a tree level. +@param index B-tree index +@param pcur persistent cursor +@param level level to search for (0=leaf) +@param mtr mini-transaction */ +static dberr_t btr_pcur_open_level(dict_index_t *index, btr_pcur_t *pcur, + ulint level, mtr_t *mtr) +{ + btr_pcur_init(pcur); + pcur->trx_if_known= nullptr; + pcur->latch_mode= BTR_SEARCH_TREE; + pcur->search_mode= PAGE_CUR_G; + pcur->pos_state= BTR_PCUR_IS_POSITIONED; + + return btr_cur_open_at_index_side(true, index, + BTR_SEARCH_TREE_ALREADY_S_LATCHED, + btr_pcur_get_btr_cur(pcur), level, mtr); +} + /* @{ Pseudo code about the relation between the following functions let N = N_SAMPLE_PAGES(index) @@ -1649,9 +1668,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(index, &pcur, level, mtr) != DB_SUCCESS || !btr_pcur_move_to_next_on_page(&pcur)) { goto func_exit; } @@ -2289,9 +2306,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(index, &pcur, n_diff_data->level, mtr) != DB_SUCCESS || !btr_pcur_move_to_next_on_page(&pcur)) { return; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 8a410e56b56..9adc01d9cf5 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3551,12 +3551,11 @@ fts_get_max_doc_id( ut_ad(innobase_strcasecmp(FTS_DOC_ID_COL_NAME, dfield->name) == 0); #endif - mtr_start(&mtr); + mtr.start(); /* fetch the largest indexes value */ - if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, &pcur, - true, 0, &mtr) != DB_SUCCESS) { - } else if (!page_is_empty(btr_pcur_get_page(&pcur))) { + if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr) == DB_SUCCESS + && !page_is_empty(btr_pcur_get_page(&pcur))) { const rec_t* rec = NULL; do { @@ -3575,7 +3574,7 @@ fts_get_max_doc_id( } func_exit: - mtr_commit(&mtr); + mtr.commit(); return(doc_id); } diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 78d0a5b9705..03e386a6736 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -102,7 +102,6 @@ rtr_pcur_getnext_from_path( node_visit_t next_rec; rtr_info_t* rtr_info = btr_cur->rtr_info; node_seq_t page_ssn; - ulint my_latch_mode; ulint skip_parent = false; bool new_split = false; bool for_delete = false; @@ -115,7 +114,7 @@ rtr_pcur_getnext_from_path( ut_ad(dtuple_get_n_fields_cmp(tuple)); - my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); + const auto my_latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); for_delete = latch_mode & BTR_RTREE_DELETE_MARK; for_undo_ins = latch_mode & BTR_RTREE_UNDO_INS; @@ -351,17 +350,12 @@ rtr_pcur_getnext_from_path( BTR_PCUR_IS_POSITIONED; r_cursor->latch_mode = my_latch_mode; btr_pcur_store_position(r_cursor, mtr); -#ifdef UNIV_DEBUG - ulint num_stored = - rtr_store_parent_path( - block, btr_cur, - rw_latch, level, mtr); - ut_ad(num_stored > 0); -#else + ut_d(ulint num_stored =) rtr_store_parent_path( - block, btr_cur, rw_latch, + block, btr_cur, + btr_latch_mode(rw_latch), level, mtr); -#endif /* UNIV_DEBUG */ + ut_ad(num_stored > 0); } } } else { @@ -521,7 +515,7 @@ bool rtr_pcur_open( dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ mtr_t* mtr) /*!< in: mtr */ { @@ -1352,7 +1346,7 @@ rtr_store_parent_path( /*==================*/ const buf_block_t* block, /*!< in: block of the page */ btr_cur_t* btr_cur,/*!< in/out: persistent cursor */ - ulint latch_mode, + btr_latch_mode latch_mode, /*!< in: latch_mode */ ulint level, /*!< in: index level */ mtr_t* mtr) /*!< in: mtr */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dba0352b5ce..304e8990075 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2051,9 +2051,8 @@ static void drop_garbage_tables_after_restore() ut_d(purge_sys.stop_FTS()); mtr.start(); - if (btr_pcur_open_at_index_side(true, dict_sys.sys_tables->indexes.start, - BTR_SEARCH_LEAF, &pcur, true, 0, &mtr) != - DB_SUCCESS) + if (pcur.open_leaf(true, dict_sys.sys_tables->indexes.start, BTR_SEARCH_LEAF, + &mtr) != DB_SUCCESS) goto all_fail; for (;;) { @@ -15061,9 +15060,7 @@ inline int ha_innobase::defragment_table() mtr_t mtr; mtr.start(); - if (dberr_t err= btr_pcur_open_at_index_side(true, index, - BTR_SEARCH_LEAF, &pcur, - true, 0, &mtr)) + if (dberr_t err= pcur.open_leaf(true, index, BTR_SEARCH_LEAF, &mtr)) { mtr.commit(); return convert_error_code_to_mysql(err, 0, m_user_thd); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 8ef58d64167..f477355acae 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2128,8 +2128,7 @@ static bool innobase_table_is_empty(const dict_table_t *table, bool next_page= false; mtr.start(); - if (btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, - &pcur, true, 0, &mtr) != DB_SUCCESS) + if (pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr) != DB_SUCCESS) { non_empty: mtr.commit(); @@ -6023,8 +6022,7 @@ add_all_virtual: mtr.start(); index->set_modified(mtr); btr_pcur_t pcur; - dberr_t err = btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, - &pcur, true, 0, &mtr); + dberr_t err= pcur.open_leaf(true, index, BTR_MODIFY_TREE, &mtr); if (err != DB_SUCCESS) { func_exit: mtr.commit(); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index e6ce75d9799..36dfb99701d 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -466,9 +466,8 @@ err_exit: ib::info() << "Dumping the change buffer"; ibuf_mtr_start(&mtr); btr_pcur_t pcur; - if (DB_SUCCESS == btr_pcur_open_at_index_side( - true, ibuf.index, BTR_SEARCH_LEAF, &pcur, - true, 0, &mtr)) { + if (DB_SUCCESS + == pcur.open_leaf(true, ibuf.index, BTR_SEARCH_LEAF, &mtr)) { while (btr_pcur_move_to_next_user_rec(&pcur, &mtr)) { rec_print_old(stderr, btr_pcur_get_rec(&pcur)); } @@ -2911,8 +2910,8 @@ ibuf_update_max_tablespace_id(void) ibuf_mtr_start(&mtr); - if (btr_pcur_open_at_index_side(false, ibuf.index, BTR_SEARCH_LEAF, - &pcur, true, 0, &mtr) != DB_SUCCESS) { + if (pcur.open_leaf(false, ibuf.index, BTR_SEARCH_LEAF, &mtr) + != DB_SUCCESS) { func_exit: ibuf_mtr_commit(&mtr); return; @@ -3105,7 +3104,7 @@ or clustered static TRANSACTIONAL_TARGET MY_ATTRIBUTE((warn_unused_result)) dberr_t ibuf_insert_low( - ulint mode, + btr_latch_mode mode, ibuf_op_t op, ibool no_counter, const dtuple_t* entry, @@ -3919,7 +3918,7 @@ ibuf_restore_pos( const page_id_t page_id,/*!< in: page identifier */ const dtuple_t* search_tuple, /*!< in: search tuple for entries of page_no */ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_PURGE_TREE */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_PURGE_TREE */ btr_pcur_t* pcur, /*!< in/out: persistent cursor whose position is to be restored */ mtr_t* mtr) /*!< in/out: mini-transaction */ diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 74798a1e2c6..0fd1f6aeee6 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -55,103 +55,8 @@ not acceptable for it to lead to mysterious memory corruption, but it is acceptable for the program to die with a clear assert failure. */ #define BTR_MAX_LEVELS 100 -/** Latching modes for btr_cur_search_to_nth_level(). */ -enum btr_latch_mode { - /** Search a record on a leaf page and S-latch it. */ - BTR_SEARCH_LEAF = RW_S_LATCH, - /** (Prepare to) modify a record on a leaf page and X-latch it. */ - BTR_MODIFY_LEAF = RW_X_LATCH, - /** Obtain no latches. */ - BTR_NO_LATCHES = RW_NO_LATCH, - /** Search the previous record. */ - BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF, - /** Modify the previous record. */ - BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF, - /** Start searching the entire B-tree. */ - BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF, - /** Start modifying1 the entire B-tree. */ - BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF, - /** Continue searching the entire B-tree. */ - BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE, - /** Continue modifying the entire B-tree. */ - BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE, - - /* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually - exclusive. */ - /** The search tuple will be inserted to the secondary index - at the searched position. When the leaf page is not in the - buffer pool, try to use the change buffer. */ - BTR_INSERT = 64, - - /** Try to delete mark a secondary index leaf page record at - the searched position using the change buffer when the page is - not in the buffer pool. */ - BTR_DELETE_MARK = 128, - - /** Try to purge the record using the change buffer when the - secondary index leaf page is not in the buffer pool. */ - BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK, - - /** The caller is already holding dict_index_t::lock S-latch. */ - BTR_ALREADY_S_LATCHED = 256, - /** Search and S-latch a leaf page, assuming that the - dict_index_t::lock S-latch is being held. */ - BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF - | BTR_ALREADY_S_LATCHED, - /** Search the entire index tree, assuming that the - dict_index_t::lock S-latch is being held. */ - BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE - | BTR_ALREADY_S_LATCHED, - /** Search and X-latch a leaf page, assuming that the - dict_index_t::lock is being held in non-exclusive mode. */ - BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF - | BTR_ALREADY_S_LATCHED, - - /** Attempt to delete-mark a secondary index record. */ - BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK, - /** Attempt to delete-mark a secondary index record - while holding the dict_index_t::lock S-latch. */ - BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF - | BTR_ALREADY_S_LATCHED, - /** Attempt to purge a secondary index record. */ - BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE, - /** Attempt to purge a secondary index record - while holding the dict_index_t::lock S-latch. */ - BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF - | BTR_ALREADY_S_LATCHED, - - /** In the case of BTR_MODIFY_TREE, the caller specifies - the intention to delete record only. It is used to optimize - block->lock range.*/ - BTR_LATCH_FOR_DELETE = 512, - - /** In the case of BTR_MODIFY_TREE, the caller specifies - the intention to delete record only. It is used to optimize - block->lock range.*/ - BTR_LATCH_FOR_INSERT = 1024, - - /** Attempt to delete a record in the tree. */ - BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, - - /** Attempt to insert a record into the tree. */ - BTR_INSERT_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT -}; - -/** This flag ORed to BTR_INSERT says that we can ignore possible -UNIQUE definition on secondary indexes when we decide if we can use -the insert buffer to speed up inserts */ -#define BTR_IGNORE_SEC_UNIQUE 2048U - -/** This flag is for undo insert of rtree. For rtree, we need this flag -to find proper rec to undo insert.*/ -#define BTR_RTREE_UNDO_INS 4096U - -/** Try to delete mark the record at the searched position when the -record is in spatial index */ -#define BTR_RTREE_DELETE_MARK 16384U - #define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \ - ((latch_mode) & ulint(~(BTR_INSERT \ + btr_latch_mode((latch_mode) & ~(BTR_INSERT \ | BTR_DELETE_MARK \ | BTR_RTREE_UNDO_INS \ | BTR_RTREE_DELETE_MARK \ @@ -159,11 +64,11 @@ record is in spatial index */ | BTR_IGNORE_SEC_UNIQUE \ | BTR_ALREADY_S_LATCHED \ | BTR_LATCH_FOR_INSERT \ - | BTR_LATCH_FOR_DELETE))) + | BTR_LATCH_FOR_DELETE)) -#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \ - ((latch_mode) & ulint(~(BTR_LATCH_FOR_INSERT \ - | BTR_LATCH_FOR_DELETE))) +#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \ + btr_latch_mode((latch_mode) \ + & ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE)) /**************************************************************//** Checks and adjusts the root node of a tree during IMPORT TABLESPACE. diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 6626b2e948a..5158b125404 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -137,7 +137,7 @@ bool btr_cur_optimistic_latch_leaves( buf_block_t* block, ib_uint64_t modify_clock, - ulint* latch_mode, + btr_latch_mode* latch_mode, btr_cur_t* cursor, mtr_t* mtr); @@ -168,7 +168,8 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value. @return DB_SUCCESS on success or error code otherwise */ dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level, const dtuple_t *tuple, - page_cur_mode_t mode, ulint latch_mode, + page_cur_mode_t mode, + btr_latch_mode latch_mode, btr_cur_t *cursor, mtr_t *mtr, ib_uint64_t autoinc= 0); @@ -180,7 +181,7 @@ btr_cur_open_at_index_side( bool from_left, /*!< in: true if open to the low end, false if to the high end */ dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: latch mode */ + btr_latch_mode latch_mode, /*!< in: latch mode */ btr_cur_t* cursor, /*!< in/out: cursor */ ulint level, /*!< in: level to search for (0=leaf) */ @@ -194,7 +195,7 @@ if the index is unavailable */ bool btr_cur_open_at_rnd_pos( dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */ btr_cur_t* cursor, /*!< in/out: B-tree cursor */ mtr_t* mtr) /*!< in: mtr */ MY_ATTRIBUTE((nonnull,warn_unused_result)); @@ -689,7 +690,7 @@ btr_rec_copy_externally_stored_field( void btr_cur_latch_leaves( buf_block_t* block, - ulint latch_mode, + btr_latch_mode latch_mode, btr_cur_t* cursor, mtr_t* mtr, btr_latch_leaves_t* latch_leaves = nullptr); @@ -839,6 +840,15 @@ struct btr_cur_t { path_arr = NULL; rtr_info = NULL; } + + /** Open the cursor on the first or last record. + @param first true=first record, false=last record + @param index B-tree + @param latch_mode which latches to acquire + @param mtr mini-transaction + @return error code */ + dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode, + mtr_t *mtr); }; /** Modify the delete-mark flag of a record. diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index 8142d33f571..ba4c49c2f9b 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -105,7 +105,7 @@ btr_pcur_open_low( PAGE_CUR_LE, not PAGE_CUR_GE, as the latter may end up on the previous page from the record! */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written (0 if none) */ @@ -127,25 +127,10 @@ cursor. @return DB_SUCCESS on success or error code otherwise. */ inline dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple, - page_cur_mode_t mode, ulint latch_mode, + page_cur_mode_t mode, + btr_latch_mode latch_mode, btr_pcur_t *cursor, mtr_t *mtr); -/*****************************************************************//** -Opens a persistent cursor at either end of an index. */ -UNIV_INLINE -dberr_t -btr_pcur_open_at_index_side( -/*========================*/ - bool from_left, /*!< in: true if open to the low end, - false if to the high end */ - dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: latch mode */ - btr_pcur_t* pcur, /*!< in/out: cursor */ - bool init_pcur, /*!< in: whether to initialize pcur */ - ulint level, /*!< in: level to search for - (0=leaf) */ - mtr_t* mtr) /*!< in/out: mini-transaction */ - MY_ATTRIBUTE((nonnull,warn_unused_result)); /**************************************************************//** Gets the up_match value for a pcur after a search. @return number of matched fields at the cursor or to the right if @@ -356,100 +341,105 @@ enum pcur_pos_t { /* The persistent B-tree cursor structure. This is used mainly for SQL selects, updates, and deletes. */ -struct btr_pcur_t{ - /** Return value of restore_position() */ - enum restore_status { - /** cursor position on user rec and points on the record with - the same field values as in the stored record */ - SAME_ALL, - /** cursor position is on user rec and points on the record with - the same unique field values as in the stored record */ - SAME_UNIQ, - /** cursor position is not on user rec or points on the record - with not the same uniq field values as in the stored record */ - NOT_SAME, - /** the index tree is corrupted */ - CORRUPTED - }; - /** a B-tree cursor */ - btr_cur_t btr_cur; - /** see TODO note below! - BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES, - depending on the latching state of the page and tree where the cursor - is positioned; BTR_NO_LATCHES means that the cursor is not currently - positioned: - we say then that the cursor is detached; it can be restored to - attached if the old position was stored in old_rec */ - ulint latch_mode; - /** if cursor position is stored, contains an initial segment of the - latest record cursor was positioned either on, before or after */ - rec_t* old_rec; - /** btr_cur.index->n_core_fields when old_rec was copied */ - uint16 old_n_core_fields; - /** number of fields in old_rec */ - uint16 old_n_fields; - /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on - whether cursor was on, before, or after the old_rec record */ - enum btr_pcur_pos_t rel_pos; - /** buffer block when the position was stored */ - buf::Block_hint block_when_stored; - /** the modify clock value of the buffer block when the cursor position - was stored */ - ib_uint64_t modify_clock; - /** btr_pcur_store_position() and btr_pcur_restore_position() state. */ - enum pcur_pos_t pos_state; - /** PAGE_CUR_G, ... */ - page_cur_mode_t search_mode; - /** the transaction, if we know it; otherwise this field is not defined; - can ONLY BE USED in error prints in fatal assertion failures! */ - trx_t* trx_if_known; - /*-----------------------------*/ - /* NOTE that the following fields may possess dynamically allocated - memory which should be freed if not needed anymore! */ - - /** NULL, or a dynamically allocated buffer for old_rec */ - byte* old_rec_buf; - /** old_rec_buf size if old_rec_buf is not NULL */ - ulint buf_size; - - btr_pcur_t() : - btr_cur(), latch_mode(RW_NO_LATCH), - old_rec(NULL), - old_n_fields(0), rel_pos(btr_pcur_pos_t(0)), - block_when_stored(), - modify_clock(0), pos_state(BTR_PCUR_NOT_POSITIONED), - search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL), - old_rec_buf(NULL), buf_size(0) - { - btr_cur.init(); - } - - /** Return the index of this persistent cursor */ - dict_index_t* index() const { return(btr_cur.index); } - MY_ATTRIBUTE((nonnull, warn_unused_result)) - /** Restores the stored position of a persistent cursor bufferfixing - the page and obtaining the specified latches. If the cursor position - was saved when the - (1) cursor was positioned on a user record: this function restores the - position to the last record LESS OR EQUAL to the stored record; - (2) cursor was positioned on a page infimum record: restores the - position to the last record LESS than the user record which was the - successor of the page infimum; - (3) cursor was positioned on the page supremum: restores to the first - record GREATER than the user record which was the predecessor of the - supremum. - (4) cursor was positioned before the first or after the last in an - empty tree: restores to before first or after the last in the tree. - @param restore_latch_mode BTR_SEARCH_LEAF, ... - @param mtr mtr - @retval SAME_ALL cursor position on user rec and points on - the record with the same field values as in the stored record, - @retval SAME_UNIQ cursor position is on user rec and points on the - record with the same unique field values as in the stored record, - @retval NOT_SAME cursor position is not on user rec or points on - the record with not the same uniq field values as in the stored - @retval CORRUPTED if the index is corrupted */ - restore_status restore_position(ulint latch_mode, mtr_t *mtr); +struct btr_pcur_t +{ + /** Return value of restore_position() */ + enum restore_status { + /** cursor position on user rec and points on the record with + the same field values as in the stored record */ + SAME_ALL, + /** cursor position is on user rec and points on the record with + the same unique field values as in the stored record */ + SAME_UNIQ, + /** cursor position is not on user rec or points on the record + with not the same uniq field values as in the stored record */ + NOT_SAME, + /** the index tree is corrupted */ + CORRUPTED + }; + /** a B-tree cursor */ + btr_cur_t btr_cur; + /** @see BTR_PCUR_WAS_POSITIONED + BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES, + depending on the latching state of the page and tree where the cursor + is positioned; BTR_NO_LATCHES means that the cursor is not currently + positioned: + we say then that the cursor is detached; it can be restored to + attached if the old position was stored in old_rec */ + btr_latch_mode latch_mode= BTR_NO_LATCHES; + /** if cursor position is stored, contains an initial segment of the + latest record cursor was positioned either on, before or after */ + rec_t *old_rec= nullptr; + /** btr_cur.index->n_core_fields when old_rec was copied */ + uint16 old_n_core_fields= 0; + /** number of fields in old_rec */ + uint16 old_n_fields= 0; + /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on + whether cursor was on, before, or after the old_rec record */ + btr_pcur_pos_t rel_pos= btr_pcur_pos_t(0); + /** buffer block when the position was stored */ + buf::Block_hint block_when_stored; + /** the modify clock value of the buffer block when the cursor position + was stored */ + ib_uint64_t modify_clock= 0; + /** btr_pcur_store_position() and btr_pcur_restore_position() state. */ + enum pcur_pos_t pos_state= BTR_PCUR_NOT_POSITIONED; + page_cur_mode_t search_mode= PAGE_CUR_UNSUPP; + /** the transaction, if we know it; otherwise this field is not defined; + can ONLY BE USED in error prints in fatal assertion failures! */ + trx_t *trx_if_known= nullptr; + /** a dynamically allocated buffer for old_rec */ + byte *old_rec_buf= nullptr; + /** old_rec_buf size if old_rec_buf is not nullptr */ + ulint buf_size= 0; + + btr_pcur_t() : btr_cur() { btr_cur.init(); } + + /** Return the index of this persistent cursor */ + dict_index_t *index() const { return(btr_cur.index); } + MY_ATTRIBUTE((nonnull, warn_unused_result)) + /** Restores the stored position of a persistent cursor bufferfixing + the page and obtaining the specified latches. If the cursor position + was saved when the + (1) cursor was positioned on a user record: this function restores the + position to the last record LESS OR EQUAL to the stored record; + (2) cursor was positioned on a page infimum record: restores the + position to the last record LESS than the user record which was the + successor of the page infimum; + (3) cursor was positioned on the page supremum: restores to the first + record GREATER than the user record which was the predecessor of the + supremum. + (4) cursor was positioned before the first or after the last in an + empty tree: restores to before first or after the last in the tree. + @param restore_latch_mode BTR_SEARCH_LEAF, ... + @param mtr mtr + @retval SAME_ALL cursor position on user rec and points on + the record with the same field values as in the stored record, + @retval SAME_UNIQ cursor position is on user rec and points on the + record with the same unique field values as in the stored record, + @retval NOT_SAME cursor position is not on user rec or points on + the record with not the same uniq field values as in the stored + @retval CORRUPTED if the index is corrupted */ + restore_status restore_position(btr_latch_mode latch_mode, mtr_t *mtr); + + /** Open the cursor on the first or last record. + @param first true=first record, false=last record + @param index B-tree + @param latch_mode which latches to acquire + @param mtr mini-transaction + @return error code */ + dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode, + mtr_t *mtr) + + { + this->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); + search_mode= first ? PAGE_CUR_G : PAGE_CUR_L; + pos_state= BTR_PCUR_IS_POSITIONED; + old_rec= nullptr; + + return btr_cur.open_leaf(first, index, + BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode), mtr); + } }; inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor) @@ -480,7 +470,7 @@ btr_pcur_open_on_user_rec( dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */ - ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or + btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF or BTR_MODIFY_LEAF */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ diff --git a/storage/innobase/include/btr0pcur.inl b/storage/innobase/include/btr0pcur.inl index 26f0bd78276..1f7605e96a8 100644 --- a/storage/innobase/include/btr0pcur.inl +++ b/storage/innobase/include/btr0pcur.inl @@ -324,7 +324,7 @@ btr_pcur_open_low( PAGE_CUR_LE, not PAGE_CUR_GE, as the latter may end up on the previous page from the record! */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written (0 if none) */ @@ -355,7 +355,8 @@ cursor. @return DB_SUCCESS on success or error code otherwise. */ inline dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple, - page_cur_mode_t mode, ulint latch_mode, + page_cur_mode_t mode, + btr_latch_mode latch_mode, btr_pcur_t *cursor, mtr_t *mtr) { cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode); @@ -368,44 +369,6 @@ dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple, btr_pcur_get_btr_cur(cursor), mtr); } -/*****************************************************************//** -Opens a persistent cursor at either end of an index. */ -UNIV_INLINE -dberr_t -btr_pcur_open_at_index_side( -/*========================*/ - bool from_left, /*!< in: true if open to the low end, - false if to the high end */ - dict_index_t* index, /*!< in: index */ - ulint latch_mode, /*!< in: latch mode */ - btr_pcur_t* pcur, /*!< in/out: cursor */ - bool init_pcur, /*!< in: whether to initialize pcur */ - ulint level, /*!< in: level to search for - (0=leaf) */ - mtr_t* mtr) /*!< in/out: mini-transaction */ -{ - dberr_t err = DB_SUCCESS; - - pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode); - - pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L; - - if (init_pcur) { - btr_pcur_init(pcur); - } - - err = btr_cur_open_at_index_side( - from_left, index, latch_mode, - btr_pcur_get_btr_cur(pcur), level, mtr); - pcur->pos_state = BTR_PCUR_IS_POSITIONED; - - pcur->old_rec = nullptr; - - pcur->trx_if_known = NULL; - - return (err); -} - /**************************************************************//** Frees the possible memory heap of a persistent cursor and sets the latch mode of the persistent cursor to BTR_NO_LATCHES. diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h index 83c374e2561..6118bfbc128 100644 --- a/storage/innobase/include/btr0types.h +++ b/storage/innobase/include/btr0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2019, MariaDB Corporation. +Copyright (c) 2018, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,8 +24,7 @@ The index tree general types Created 2/17/1996 Heikki Tuuri *************************************************************************/ -#ifndef btr0types_h -#define btr0types_h +#pragma once #include "page0types.h" #include "rem0types.h" @@ -56,4 +55,93 @@ in the index record. */ #define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \ (BTR_EXTERN_FIELD_REF_SIZE * 2) -#endif +/** Latching modes for btr_cur_search_to_nth_level(). */ +enum btr_latch_mode { + /** Search a record on a leaf page and S-latch it. */ + BTR_SEARCH_LEAF = RW_S_LATCH, + /** (Prepare to) modify a record on a leaf page and X-latch it. */ + BTR_MODIFY_LEAF = RW_X_LATCH, + /** Obtain no latches. */ + BTR_NO_LATCHES = RW_NO_LATCH, + /** Search the previous record. */ + BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF, + /** Modify the previous record. */ + BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF, + /** Start searching the entire B-tree. */ + BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF, + /** Start modifying1 the entire B-tree. */ + BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF, + /** Continue searching the entire B-tree. */ + BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE, + /** Continue modifying the entire B-tree. */ + BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE, + + /* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually + exclusive. */ + /** The search tuple will be inserted to the secondary index + at the searched position. When the leaf page is not in the + buffer pool, try to use the change buffer. */ + BTR_INSERT = 64, + + /** Try to delete mark a secondary index leaf page record at + the searched position using the change buffer when the page is + not in the buffer pool. */ + BTR_DELETE_MARK = 128, + + /** Try to purge the record using the change buffer when the + secondary index leaf page is not in the buffer pool. */ + BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK, + + /** The caller is already holding dict_index_t::lock S-latch. */ + BTR_ALREADY_S_LATCHED = 256, + /** Search and S-latch a leaf page, assuming that the + dict_index_t::lock S-latch is being held. */ + BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF + | BTR_ALREADY_S_LATCHED, + /** Search the entire index tree, assuming that the + dict_index_t::lock S-latch is being held. */ + BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE + | BTR_ALREADY_S_LATCHED, + /** Search and X-latch a leaf page, assuming that the + dict_index_t::lock is being held in non-exclusive mode. */ + BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF + | BTR_ALREADY_S_LATCHED, + + /** Attempt to delete-mark a secondary index record. */ + BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK, + /** Attempt to delete-mark a secondary index record + while holding the dict_index_t::lock S-latch. */ + BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF + | BTR_ALREADY_S_LATCHED, + /** Attempt to purge a secondary index record. */ + BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE, + /** Attempt to purge a secondary index record + while holding the dict_index_t::lock S-latch. */ + BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF + | BTR_ALREADY_S_LATCHED, + + /** In the case of BTR_MODIFY_TREE, the caller specifies + the intention to delete record only. It is used to optimize + block->lock range.*/ + BTR_LATCH_FOR_DELETE = 512, + + /** In the case of BTR_MODIFY_TREE, the caller specifies + the intention to delete record only. It is used to optimize + block->lock range.*/ + BTR_LATCH_FOR_INSERT = 1024, + + /** Attempt to delete a record in the tree. */ + BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, + + /** Attempt to insert a record into the tree. */ + BTR_INSERT_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT, + + /** This flag ORed to BTR_INSERT says that we can ignore possible + UNIQUE definition on secondary indexes when we decide if we can use + the insert buffer to speed up inserts */ + BTR_IGNORE_SEC_UNIQUE = 2048, + /** Rollback in spatial index */ + BTR_RTREE_UNDO_INS = 4096, + /** Try to delete mark a spatial index record */ + BTR_RTREE_DELETE_MARK = 8192 +}; diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h index 8cd5e384530..05b59b295c4 100644 --- a/storage/innobase/include/gis0rtree.h +++ b/storage/innobase/include/gis0rtree.h @@ -298,7 +298,7 @@ rtr_store_parent_path( /*==================*/ const buf_block_t* block, /*!< in: block of the page */ btr_cur_t* btr_cur,/*!< in/out: persistent cursor */ - ulint latch_mode, + btr_latch_mode latch_mode, /*!< in: latch_mode */ ulint level, /*!< in: index level */ mtr_t* mtr); /*!< in: mtr */ @@ -310,7 +310,7 @@ bool rtr_pcur_open( dict_index_t* index, /*!< in: index */ const dtuple_t* tuple, /*!< in: tuple on which search done */ - ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ + btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ mtr_t* mtr) /*!< in: mtr */ MY_ATTRIBUTE((warn_unused_result)); diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index a1b2de73ed2..1f8af6030d1 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +Copyright (c) 2017, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -78,7 +78,7 @@ dberr_t row_ins_clust_index_entry_low( /*==========================*/ ulint flags, /*!< in: undo logging and locking flags */ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /*!< in: clustered index */ @@ -100,7 +100,7 @@ dberr_t row_ins_sec_index_entry_low( /*========================*/ ulint flags, /*!< in: undo logging and locking flags */ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE, + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE, depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /*!< in: secondary index */ diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index 1e0fdc65238..42b00b8925c 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2020, MariaDB Corporation. +Copyright (c) 2016, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -303,13 +303,13 @@ row_build_row_ref_fast( /***************************************************************//** Searches the clustered index record for a row, if we have the row reference. -@return TRUE if found */ -ibool +@return true if found */ +bool row_search_on_row_ref( /*==================*/ btr_pcur_t* pcur, /*!< out: persistent cursor, which must be closed by the caller */ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ const dict_table_t* table, /*!< in: table */ const dtuple_t* ref, /*!< in: row reference */ mtr_t* mtr) /*!< in/out: mtr */ @@ -321,7 +321,7 @@ on the secondary index record are preserved. rec_t* row_get_clust_rec( /*==============*/ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ const rec_t* rec, /*!< in: record in a secondary index */ dict_index_t* index, /*!< in: secondary index */ dict_index_t** clust_index,/*!< out: clustered index */ @@ -365,7 +365,7 @@ row_search_index_entry( /*===================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* entry, /*!< in: index entry */ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must be closed by the caller */ mtr_t* mtr) /*!< in: mtr */ diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 9948f2e4d68..da6447c390e 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -611,7 +611,7 @@ rec_init_offsets( ulint i = 0; rec_offs offs; - /* This assertion was relaxed for the btr_cur_open_at_index_side() + /* This assertion was relaxed for the btr_cur_t::open_leaf() call in btr_cur_instant_init_low(). We cannot invoke index->is_instant(), because the same assertion would fail there until btr_cur_instant_init_low() has invoked @@ -839,7 +839,7 @@ rec_get_offsets_func( bool alter_metadata = false; ut_ad(index->n_core_fields >= n_core); - /* This assertion was relaxed for the btr_cur_open_at_index_side() + /* This assertion was relaxed for the btr_cur_t::open_leaf() call in btr_cur_instant_init_low(). We cannot invoke index->is_instant(), because the same assertion would fail there until btr_cur_instant_init_low() has invoked diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 971fa557ad3..b25864f91e8 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1525,8 +1525,9 @@ inline bool IndexPurge::open() noexcept m_mtr.start(); m_mtr.set_log_mode(MTR_LOG_NO_REDO); - if (btr_pcur_open_at_index_side(true, m_index, BTR_MODIFY_LEAF, - &m_pcur, true, 0, &m_mtr) != DB_SUCCESS) + btr_pcur_init(&m_pcur); + + if (m_pcur.open_leaf(true, m_index, BTR_MODIFY_LEAF, &m_mtr) != DB_SUCCESS) return false; rec_t *rec= page_rec_get_next(btr_pcur_get_rec(&m_pcur)); @@ -2300,8 +2301,8 @@ row_import_set_sys_max_row_id( mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, - &pcur, true, 0, &mtr) == DB_SUCCESS) { + if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, &mtr) + == DB_SUCCESS) { rec = btr_pcur_move_to_prev_on_page(&pcur); if (!rec) { diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 88b0edc1d84..1d772b02704 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2522,7 +2522,7 @@ dberr_t row_ins_clust_index_entry_low( /*==========================*/ ulint flags, /*!< in: undo logging and locking flags */ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /*!< in: clustered index */ @@ -2749,8 +2749,8 @@ do_insert: rec_t* insert_rec; if (mode != BTR_MODIFY_TREE) { - ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED)) - == BTR_MODIFY_LEAF); + ut_ad(mode == BTR_MODIFY_LEAF || + mode == BTR_MODIFY_LEAF_ALREADY_LATCHED); err = btr_cur_optimistic_insert( flags, cursor, &offsets, &offsets_heap, entry, &insert_rec, &big_rec, @@ -2832,7 +2832,7 @@ dberr_t row_ins_sec_index_entry_low( /*========================*/ ulint flags, /*!< in: undo logging and locking flags */ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE, + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE, depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /*!< in: secondary index */ @@ -2847,7 +2847,7 @@ row_ins_sec_index_entry_low( DBUG_ENTER("row_ins_sec_index_entry_low"); btr_cur_t cursor; - ulint search_mode = mode; + btr_latch_mode search_mode = mode; dberr_t err; ulint n_unique; mtr_t mtr; @@ -2872,9 +2872,6 @@ row_ins_sec_index_entry_low( mtr.set_log_mode(MTR_LOG_NO_REDO); } else { index->set_modified(mtr); - if (!dict_index_is_spatial(index)) { - search_mode |= BTR_INSERT; - } } /* Note that we use PAGE_CUR_LE as the search mode, because then @@ -2916,8 +2913,12 @@ row_ins_sec_index_entry_low( goto func_exit;}); } else { - if (!thr_get_trx(thr)->check_unique_secondary) { - search_mode |= BTR_IGNORE_SEC_UNIQUE; + if (!index->table->is_temporary()) { + search_mode = btr_latch_mode( + search_mode + | (thr_get_trx(thr)->check_unique_secondary + ? BTR_INSERT | BTR_IGNORE_SEC_UNIQUE + : BTR_INSERT)); } err = btr_cur_search_to_nth_level( @@ -2998,11 +2999,12 @@ row_ins_sec_index_entry_low( locked with s-locks the necessary records to prevent any insertion of a duplicate by another transaction. Let us now reposition the cursor and - continue the insertion. */ + continue the insertion (bypassing the change buffer). */ err = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_LE, - (search_mode - & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),//??? + btr_latch_mode(search_mode + & ~(BTR_INSERT + | BTR_IGNORE_SEC_UNIQUE)), &cursor, &mtr); if (err != DB_SUCCESS) { goto func_exit; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 571e8cf3a83..56b5ab2f883 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1829,8 +1829,7 @@ row_merge_read_clustered_index( ? col_map[old_trx_id_col] : old_trx_id_col; uint64_t n_rows = 0; - err = btr_pcur_open_at_index_side(true, clust_index, BTR_SEARCH_LEAF, - &pcur, true, 0, &mtr); + err = pcur.open_leaf(true, clust_index, BTR_SEARCH_LEAF, &mtr); if (err != DB_SUCCESS) { err_exit: trx->error_key_num = 0; diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index e26038209fe..3c3beeb0eda 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -67,7 +67,7 @@ static ibool row_purge_reposition_pcur( /*======================*/ - ulint mode, /*!< in: latching mode */ + btr_latch_mode mode, /*!< in: latching mode */ purge_node_t* node, /*!< in: row purge node */ mtr_t* mtr) /*!< in: mtr */ { @@ -104,7 +104,7 @@ bool row_purge_remove_clust_if_poss_low( /*===============================*/ purge_node_t* node, /*!< in/out: row purge node */ - ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ + btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { dict_index_t* index = dict_table_get_first_index(node->table); table_id_t table_id = 0; diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 9218e739e96..62a41be115e 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1183,32 +1183,27 @@ row_build_row_ref_in_tuple( /***************************************************************//** Searches the clustered index record for a row, if we have the row reference. @return TRUE if found */ -ibool +bool row_search_on_row_ref( /*==================*/ btr_pcur_t* pcur, /*!< out: persistent cursor, which must be closed by the caller */ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ const dict_table_t* table, /*!< in: table */ const dtuple_t* ref, /*!< in: row reference */ mtr_t* mtr) /*!< in/out: mtr */ { - ulint low_match; - rec_t* rec; - dict_index_t* index; - ut_ad(dtuple_check_typed(ref)); - index = dict_table_get_first_index(table); + dict_index_t *index = dict_table_get_first_index(table); if (UNIV_UNLIKELY(ref->info_bits != 0)) { ut_ad(ref->is_metadata()); ut_ad(ref->n_fields <= index->n_uniq); - if (btr_pcur_open_at_index_side( - true, index, mode, pcur, true, 0, mtr) - != DB_SUCCESS + btr_pcur_init(pcur); + if (pcur->open_leaf(true, index, mode, mtr) != DB_SUCCESS || !btr_pcur_move_to_next_user_rec(pcur, mtr)) { - return FALSE; + return false; } /* We do not necessarily have index->is_instant() here, because we could be executing a rollback of an @@ -1222,25 +1217,12 @@ row_search_on_row_ref( ut_a(ref->n_fields == index->n_uniq); if (btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr) != DB_SUCCESS) { - return FALSE; + return false; } } - low_match = btr_pcur_get_low_match(pcur); - - rec = btr_pcur_get_rec(pcur); - - if (page_rec_is_infimum(rec)) { - - return(FALSE); - } - - if (low_match != dtuple_get_n_fields(ref)) { - - return(FALSE); - } - - return(TRUE); + return !page_rec_is_infimum(btr_pcur_get_rec(pcur)) + && btr_pcur_get_low_match(pcur) == dtuple_get_n_fields(ref); } /*********************************************************************//** @@ -1250,7 +1232,7 @@ on the secondary index record are preserved. rec_t* row_get_clust_rec( /*==============*/ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ const rec_t* rec, /*!< in: record in a secondary index */ dict_index_t* index, /*!< in: secondary index */ dict_index_t** clust_index,/*!< out: clustered index */ @@ -1285,7 +1267,7 @@ row_search_index_entry( /*===================*/ dict_index_t* index, /*!< in: index */ const dtuple_t* entry, /*!< in: index entry */ - ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */ + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */ btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must be closed by the caller */ mtr_t* mtr) /*!< in: mtr */ diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 31aa9695430..615f767e7d2 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1436,9 +1436,8 @@ row_sel_open_pcur( plan->mode, BTR_SEARCH_LEAF, &plan->pcur, mtr); } else { - err = btr_pcur_open_at_index_side(plan->asc, index, - BTR_SEARCH_LEAF, &plan->pcur, - false, 0, mtr); + err = plan->pcur.open_leaf(plan->asc, index, BTR_SEARCH_LEAF, + mtr); } plan->pcur_is_open = err == DB_SUCCESS; @@ -3643,7 +3642,8 @@ record with the same ordering prefix in in the B-tree index @return true if we may need to process the record the cursor is now positioned on (i.e. we should not go to the next record yet) */ static bool sel_restore_position_for_mysql(bool *same_user_rec, - ulint latch_mode, btr_pcur_t *pcur, + btr_latch_mode latch_mode, + btr_pcur_t *pcur, bool moves_up, mtr_t *mtr) { auto status = pcur->restore_position(latch_mode, mtr); @@ -4837,9 +4837,8 @@ page_corrupted: } } } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_L) { - err = btr_pcur_open_at_index_side( - mode == PAGE_CUR_G, index, BTR_SEARCH_LEAF, - pcur, false, 0, &mtr); + err = pcur->open_leaf(mode == PAGE_CUR_G, index, + BTR_SEARCH_LEAF, &mtr); if (err != DB_SUCCESS) { if (err == DB_DECRYPTION_FAILED) { @@ -6213,9 +6212,7 @@ dberr_t row_check_index(row_prebuilt_t *prebuilt, ulint *n_rows) mtr.start(); dict_index_t *clust_index= dict_table_get_first_index(prebuilt->table); - - dberr_t err= btr_pcur_open_at_index_side(true, index, BTR_SEARCH_LEAF, - prebuilt->pcur, false, 0, &mtr); + dberr_t err= prebuilt->pcur->open_leaf(true, index, BTR_SEARCH_LEAF, &mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { func_exit: @@ -6888,8 +6885,7 @@ row_search_get_max_rec( btr_pcur_t pcur; const rec_t* rec; /* Open at the high/right end (false), and init cursor */ - if (btr_pcur_open_at_index_side(false, index, BTR_SEARCH_LEAF, &pcur, - true, 0, mtr) != DB_SUCCESS) { + if (pcur.open_leaf(false, index, BTR_SEARCH_LEAF, mtr) != DB_SUCCESS) { return nullptr; } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 01304ebd474..eae89a36a6d 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -253,7 +253,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t row_undo_ins_remove_sec_low( /*========================*/ - ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, + btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE, depending on whether we wish optimistic or pessimistic descent down the index tree */ dict_index_t* index, /*!< in: index */ @@ -268,19 +268,20 @@ row_undo_ins_remove_sec_low( row_mtr_start(&mtr, index, !modify_leaf); if (modify_leaf) { - mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED; + mode = BTR_MODIFY_LEAF_ALREADY_LATCHED; mtr_s_lock_index(index, &mtr); } else { ut_ad(mode == BTR_PURGE_TREE); mtr_sx_lock_index(index, &mtr); } - if (dict_index_is_spatial(index)) { - if (modify_leaf) { - mode |= BTR_RTREE_DELETE_MARK; - } + if (index->is_spatial()) { + mode = modify_leaf + ? btr_latch_mode(BTR_MODIFY_LEAF_ALREADY_LATCHED + | BTR_RTREE_DELETE_MARK + | BTR_RTREE_UNDO_INS) + : btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS); btr_pcur_get_btr_cur(&pcur)->thr = thr; - mode |= BTR_RTREE_UNDO_INS; } switch (row_search_index_entry(index, entry, mode, &pcur, &mtr)) { diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 90b3e0b2ebe..01b639db085 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -84,7 +84,7 @@ row_undo_mod_clust_low( que_thr_t* thr, /*!< in: query thread */ mtr_t* mtr, /*!< in: mtr; must be committed before latching any further pages */ - ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ + btr_latch_mode mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { btr_pcur_t* pcur; btr_cur_t* btr_cur; @@ -106,8 +106,8 @@ row_undo_mod_clust_low( || node->update->info_bits == REC_INFO_METADATA_ALTER); if (mode != BTR_MODIFY_TREE) { - ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED)) - == BTR_MODIFY_LEAF); + ut_ad(mode == BTR_MODIFY_LEAF + || mode == BTR_MODIFY_LEAF_ALREADY_LATCHED); err = btr_cur_optimistic_update( BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG @@ -482,7 +482,7 @@ row_undo_mod_del_mark_or_remove_sec_low( que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: index */ dtuple_t* entry, /*!< in: index entry */ - ulint mode) /*!< in: latch mode BTR_MODIFY_LEAF or + btr_latch_mode mode) /*!< in: latch mode BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { btr_pcur_t pcur; @@ -495,12 +495,21 @@ row_undo_mod_del_mark_or_remove_sec_low( row_mtr_start(&mtr, index, !modify_leaf); - if (!index->is_committed()) { + btr_cur = btr_pcur_get_btr_cur(&pcur); + + if (index->is_spatial()) { + mode = modify_leaf + ? btr_latch_mode(BTR_MODIFY_LEAF + | BTR_RTREE_DELETE_MARK + | BTR_RTREE_UNDO_INS) + : btr_latch_mode(BTR_PURGE_TREE | BTR_RTREE_UNDO_INS); + btr_cur->thr = thr; + } else if (!index->is_committed()) { /* The index->online_status may change if the index is or was being created online, but not committed yet. It is protected by index->lock. */ if (modify_leaf) { - mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED; + mode = BTR_MODIFY_LEAF_ALREADY_LATCHED; mtr_s_lock_index(index, &mtr); } else { ut_ad(mode == BTR_PURGE_TREE); @@ -513,16 +522,6 @@ row_undo_mod_del_mark_or_remove_sec_low( ut_ad(!dict_index_is_online_ddl(index)); } - btr_cur = btr_pcur_get_btr_cur(&pcur); - - if (dict_index_is_spatial(index)) { - if (modify_leaf) { - btr_cur->thr = thr; - mode |= BTR_RTREE_DELETE_MARK; - } - mode |= BTR_RTREE_UNDO_INS; - } - search_result = row_search_index_entry(index, entry, mode, &pcur, &mtr); @@ -651,7 +650,7 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t row_undo_mod_del_unmark_sec_and_undo_update( /*========================================*/ - ulint mode, /*!< in: search mode: BTR_MODIFY_LEAF or + btr_latch_mode mode, /*!< in: search mode: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ que_thr_t* thr, /*!< in: query thread */ dict_index_t* index, /*!< in: index */ @@ -667,7 +666,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( const ulint flags = BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG; row_search_result search_result; - ulint orig_mode = mode; + const auto orig_mode = mode; ut_ad(trx->id != 0); @@ -678,7 +677,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( secondary index updates to avoid this. */ static_assert(BTR_MODIFY_TREE == (8 | BTR_MODIFY_LEAF), ""); ut_ad(!(mode & 8)); - mode |= BTR_RTREE_DELETE_MARK; + mode = btr_latch_mode(mode | BTR_RTREE_DELETE_MARK); } try_again: diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 26c434ca474..36941798bc2 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1840,7 +1840,7 @@ row_upd_sec_index_entry( btr_cur_t* btr_cur; dberr_t err = DB_SUCCESS; trx_t* trx = thr_get_trx(thr); - ulint mode; + btr_latch_mode mode; ulint flags; enum row_search_result search_result; @@ -1870,14 +1870,16 @@ row_upd_sec_index_entry( "before_row_upd_sec_index_entry"); mtr.start(); + mode = BTR_MODIFY_LEAF; switch (index->table->space_id) { case SRV_TMP_SPACE_ID: mtr.set_log_mode(MTR_LOG_NO_REDO); flags = BTR_NO_LOCKING_FLAG; - mode = index->is_spatial() - ? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK) - : ulint(BTR_MODIFY_LEAF); + if (index->is_spatial()) { + mode = btr_latch_mode(BTR_MODIFY_LEAF + | BTR_RTREE_DELETE_MARK); + } break; default: index->set_modified(mtr); @@ -1887,9 +1889,10 @@ row_upd_sec_index_entry( /* We can only buffer delete-mark operations if there are no foreign key constraints referring to the index. */ mode = index->is_spatial() - ? ulint(BTR_MODIFY_LEAF | BTR_RTREE_DELETE_MARK) + ? btr_latch_mode(BTR_MODIFY_LEAF + | BTR_RTREE_DELETE_MARK) : referenced - ? ulint(BTR_MODIFY_LEAF) : ulint(BTR_DELETE_MARK_LEAF); + ? BTR_MODIFY_LEAF : BTR_DELETE_MARK_LEAF; break; } @@ -2590,13 +2593,13 @@ row_upd_clust_step( ut_a(pcur->rel_pos == BTR_PCUR_ON); - ulint mode; + btr_latch_mode mode; DEBUG_SYNC_C_IF_THD(trx->mysql_thd, "innodb_row_upd_clust_step_enter"); if (dict_index_is_online_ddl(index)) { ut_ad(node->table->id != DICT_INDEXES_ID); - mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED; + mode = BTR_MODIFY_LEAF_ALREADY_LATCHED; mtr_s_lock_index(index, &mtr); } else { mode = BTR_MODIFY_LEAF; |