summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--storage/innobase/btr/btr0btr.cc2
-rw-r--r--storage/innobase/btr/btr0cur.cc290
-rw-r--r--storage/innobase/btr/btr0pcur.cc23
-rw-r--r--storage/innobase/dict/dict0load.cc5
-rw-r--r--storage/innobase/dict/dict0stats.cc27
-rw-r--r--storage/innobase/fts/fts0fts.cc9
-rw-r--r--storage/innobase/gis/gis0sea.cc20
-rw-r--r--storage/innobase/handler/ha_innodb.cc9
-rw-r--r--storage/innobase/handler/handler0alter.cc6
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc13
-rw-r--r--storage/innobase/include/btr0btr.h105
-rw-r--r--storage/innobase/include/btr0cur.h20
-rw-r--r--storage/innobase/include/btr0pcur.h216
-rw-r--r--storage/innobase/include/btr0pcur.inl43
-rw-r--r--storage/innobase/include/btr0types.h96
-rw-r--r--storage/innobase/include/gis0rtree.h4
-rw-r--r--storage/innobase/include/row0ins.h6
-rw-r--r--storage/innobase/include/row0row.h12
-rw-r--r--storage/innobase/rem/rem0rec.cc4
-rw-r--r--storage/innobase/row/row0import.cc9
-rw-r--r--storage/innobase/row/row0ins.cc28
-rw-r--r--storage/innobase/row/row0merge.cc3
-rw-r--r--storage/innobase/row/row0purge.cc4
-rw-r--r--storage/innobase/row/row0row.cc40
-rw-r--r--storage/innobase/row/row0sel.cc20
-rw-r--r--storage/innobase/row/row0uins.cc15
-rw-r--r--storage/innobase/row/row0umod.cc37
-rw-r--r--storage/innobase/row/row0upd.cc19
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;