MDEV-29603: Implement btr_cur_t::open_leaf()

btr_cur_t::open_leaf(): Replaces btr_cur_open_at_index_side() for
most calls, except dict_stats_analyze_index(), which is the only
place where we need to open a page at the non-leaf level.
Use btr_block_get() for better error handling.

Also, use the enumeration type btr_latch_mode wherever possible.

Reviewed by: Vladislav Lesin
This commit is contained in:
Marko Mäkelä 2022-11-16 09:43:48 +02:00
parent 6b2d6a81d4
commit 89ec4b53ac
28 changed files with 627 additions and 452 deletions

View file

@ -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 */
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */

View file

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

View file

@ -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();

View file

@ -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 */

View file

@ -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.

View file

@ -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.

View file

@ -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! */
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;
/** 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() { btr_cur.init(); }
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(btr_latch_mode latch_mode, mtr_t *mtr);
/** 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);
/** 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 */

View file

@ -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.

View file

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

View file

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

View file

@ -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 */

View file

@ -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 */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */

View file

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

View file

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

View file

@ -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:

View file

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