MDEV-27927 row_sel_try_search_shortcut_for_mysql() does not latch a page, violating read view isolation

btr_search_guess_on_hash() would only acquire an index page latch if it
is invoked with ahi_latch=NULL. If it's invoked from
row_sel_try_search_shortcut_for_mysql() with ahi_latch!=NULL, a page
will not be latched, and row_search_mvcc() will get a pointer to the
record, which can be changed by some other transaction before the record
was stored in result buffer with row_sel_store_mysql_rec() call.

ahi_latch argument of btr_cur_search_to_nth_level_func() and
btr_pcur_open_with_no_init_func() is used only for
row_sel_try_search_shortcut_for_mysql().
btr_cur_search_to_nth_level_func(..., ahi_latch !=0, ...) is invoked
only from btr_pcur_open_with_no_init_func(..., ahi_latch !=0, ...),
which, in turns, is invoked only from
row_sel_try_search_shortcut_for_mysql().

I suppose that separate case with ahi_latch!=0 was intentionally
implemented to protect row_sel_store_mysql_rec() call in
row_search_mvcc() just after row_sel_try_search_shortcut_for_mysql()
call. After the ahi_latch was moved from row_seach_mvcc() to
row_sel_try_search_shortcut_for_mysql(), there is no need in it at all
if btr_search_guess_on_hash() latches a page unconditionally. And if
btr_search_guess_on_hash() latched the page, any access to the record in
row_sel_try_search_shortcut_for_mysql() after btr_pcur_open_with_no_init()
call will be protected with the page latch.

The fix is to remove ahi_latch argument from
btr_pcur_open_with_no_init_func(), btr_cur_search_to_nth_level_func()
and btr_search_guess_on_hash().

There will not be test, as to test it we need to freeze some SELECT
execution in the point between row_sel_try_search_shortcut_for_mysql()
and row_sel_store_mysql_rec() calls in row_search_mvcc(), and to change
the record in some other transaction to let row_sel_store_mysql_rec() to
store changed record in result buffer. Buf we can't do this with the
fix, as the page will be latched in btr_search_guess_on_hash() call.
This commit is contained in:
Vlad Lesin 2022-08-31 17:49:38 +03:00
parent 111cbdf3da
commit c0eda62aec
16 changed files with 160 additions and 267 deletions

View File

@ -876,7 +876,7 @@ btr_page_get_father_node_ptr_func(
err = btr_cur_search_to_nth_level(
index, level + 1, tuple,
PAGE_CUR_LE, latch_mode, cursor, 0,
PAGE_CUR_LE, latch_mode, cursor,
file, line, mtr);
if (err != DB_SUCCESS) {
@ -2380,7 +2380,7 @@ btr_insert_on_non_leaf_level_func(
dberr_t err = btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr);
&cursor, file, line, mtr);
if (err != DB_SUCCESS) {
ib::warn() << " Error code: " << err
@ -2401,7 +2401,7 @@ btr_insert_on_non_leaf_level_func(
btr_cur_search_to_nth_level(index, level, tuple,
PAGE_CUR_RTREE_INSERT,
BTR_CONT_MODIFY_TREE,
&cursor, 0, file, line, mtr);
&cursor, file, line, mtr);
}
ut_ad(cursor.flag == BTR_CUR_BINARY);

View File

@ -1102,38 +1102,36 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
If mode is PAGE_CUR_LE , cursor is left at the place where an insert of the
search tuple should be performed in the B-tree. InnoDB does an insert
immediately after the cursor. Thus, the cursor may end up on a user record,
or on a page infimum record. */
dberr_t
btr_cur_search_to_nth_level_func(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
tuple must be set so that it cannot get
compared to the node ptr page number field! */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
Inserts should always be made using
PAGE_CUR_LE to search the position! */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
at most one of BTR_INSERT, BTR_DELETE_MARK,
BTR_DELETE, or BTR_ESTIMATE;
cursor->left_block is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch
protects the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: currently held btr_search_latch
(in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in: mtr */
ib_uint64_t autoinc)/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
or on a page infimum record.
@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@param mode PAGE_CUR_L, NOTE that if the search is made using a unique
prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record! Inserts should always be made using PAGE_CUR_LE
to search the position!
@param latch_mode BTR_SEARCH_LEAF, ..., ORed with at most one of BTR_INSERT,
BTR_DELETE_MARK, BTR_DELETE, or BTR_ESTIMATE;
cursor->left_block is used to store a pointer to the left
neighbor page, in the cases BTR_SEARCH_PREV and
BTR_MODIFY_PREV; NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch protects the
record!
@param cursor tree cursor; the cursor page is s- or x-latched, but see also
above!
@param file file name
@param line line where called
@param mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@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,
btr_cur_t *cursor, const char *file,
unsigned line, mtr_t *mtr,
ib_uint64_t autoinc)
{
page_t* page = NULL; /* remove warning */
buf_block_t* block;
@ -1301,15 +1299,14 @@ btr_cur_search_to_nth_level_func(
&& mode != PAGE_CUR_LE_OR_EXTENDS
# endif /* PAGE_CUR_LE_OR_EXTENDS */
&& !dict_index_is_spatial(index)
/* If !ahi_latch, we do a dirty read of
/* We do a dirty read of
btr_search_enabled below, and btr_search_guess_on_hash()
will have to check it again. */
&& btr_search_enabled
&& !modify_external
&& !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)
&& btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor,
ahi_latch, mtr)) {
latch_mode, cursor, mtr)) {
/* Search using the hash index succeeded */
@ -1330,13 +1327,6 @@ btr_cur_search_to_nth_level_func(
/* If the hash search did not succeed, do binary search down the
tree */
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
/* Release possible search latch to obey latching order */
rw_lock_s_unlock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
/* Store the position of the tree latch we push to mtr so that we
know how to release it when we have latched leaf node(s) */
@ -2397,12 +2387,6 @@ func_exit:
cursor->rtr_info->mbr_adj = true;
}
#ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
rw_lock_s_lock(ahi_latch);
}
#endif /* BTR_CUR_HASH_ADAPT */
DBUG_RETURN(err);
}
@ -6232,8 +6216,7 @@ btr_estimate_n_rows_in_range_low(
btr_cur_search_to_nth_level(index, 0, tuple1, mode1,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0,
__FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
ut_ad(!page_rec_is_infimum(btr_cur_get_rec(&cursor)));
@ -6286,8 +6269,7 @@ btr_estimate_n_rows_in_range_low(
btr_cur_search_to_nth_level(index, 0, tuple2, mode2,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0,
__FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
const rec_t* rec = btr_cur_get_rec(&cursor);

View File

@ -424,11 +424,7 @@ btr_pcur_t::restore_position(ulint restore_latch_mode, const char *file,
}
btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode,
this,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
this, file, line, mtr);
/* Restore the old search mode */
search_mode = old_mode;

View File

@ -895,8 +895,6 @@ both have sensible values.
we assume the caller uses his search latch
to protect the record!
@param[out] cursor tree cursor
@param[in] ahi_latch the adaptive hash index latch being held,
or NULL
@param[in] mtr mini transaction
@return whether the search succeeded */
bool
@ -907,7 +905,6 @@ btr_search_guess_on_hash(
ulint mode,
ulint latch_mode,
btr_cur_t* cursor,
rw_lock_t* ahi_latch,
mtr_t* mtr)
{
ulint fold;
@ -916,8 +913,6 @@ btr_search_guess_on_hash(
btr_cur_t cursor2;
btr_pcur_t pcur;
#endif
ut_ad(!ahi_latch || rw_lock_own_flagged(
ahi_latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
if (!btr_search_enabled) {
return false;
@ -925,7 +920,6 @@ btr_search_guess_on_hash(
ut_ad(index && info && tuple && cursor && mtr);
ut_ad(!dict_index_is_ibuf(index));
ut_ad(!ahi_latch || ahi_latch == btr_get_search_latch(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));
@ -956,28 +950,21 @@ btr_search_guess_on_hash(
cursor->fold = fold;
cursor->flag = BTR_CUR_HASH;
rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
const rec_t* rec;
if (use_latch) {
rw_lock_s_lock(use_latch);
rw_lock_s_lock(ahi_latch);
if (!btr_search_enabled) {
goto fail;
}
} else {
ut_ad(btr_search_enabled);
ut_ad(rw_lock_own(ahi_latch, RW_LOCK_S));
if (!btr_search_enabled) {
goto fail;
}
rec = static_cast<const rec_t*>(
ha_search_and_get_data(btr_get_search_table(index), fold));
if (!rec) {
if (use_latch) {
fail:
rw_lock_s_unlock(use_latch);
}
rw_lock_s_unlock(ahi_latch);
btr_search_failure(info, cursor);
return false;
@ -985,25 +972,19 @@ fail:
buf_block_t* block = buf_block_from_ahi(rec);
if (use_latch) {
if (!buf_page_get_known_nowait(
latch_mode, block, BUF_MAKE_YOUNG,
__FILE__, __LINE__, mtr)) {
goto fail;
}
if (!buf_page_get_known_nowait(latch_mode, block, BUF_MAKE_YOUNG,
__FILE__, __LINE__, mtr)) {
goto fail;
}
const bool fail = index != block->index
&& index_id == block->index->id;
ut_a(!fail || block->index->freed());
rw_lock_s_unlock(use_latch);
const bool fail = index != block->index
&& index_id == block->index->id;
ut_a(!fail || block->index->freed());
ut_ad(fail || !block->page.file_page_was_freed);
rw_lock_s_unlock(ahi_latch);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
if (UNIV_UNLIKELY(fail)) {
goto fail_and_release_page;
}
} else if (UNIV_UNLIKELY(index != block->index
&& index_id == block->index->id)) {
ut_a(block->index->freed());
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
if (UNIV_UNLIKELY(fail)) {
goto fail_and_release_page;
}
@ -1012,9 +993,7 @@ fail:
ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH);
fail_and_release_page:
if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr);
}
btr_leaf_page_release(block, latch_mode, mtr);
btr_search_failure(info, cursor);
return false;
@ -1032,7 +1011,7 @@ fail_and_release_page:
record to determine if our guess for the cursor position is
right. */
if (index_id != btr_page_get_index_id(block->frame)
|| !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) {
|| !btr_search_check_guess(cursor, 0, tuple, mode)) {
goto fail_and_release_page;
}
@ -1081,7 +1060,7 @@ fail_and_release_page:
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++;
#endif
if (!ahi_latch && buf_page_peek_if_too_old(&block->page)) {
if (buf_page_peek_if_too_old(&block->page)) {
buf_page_make_young(&block->page);
}

View File

@ -4815,6 +4815,10 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
/* The check for the page was not freed would already have been
performed when the block descriptor was acquired by the thread for the
first time.*/
buf_block_buf_fix_inc(block, file, line);
buf_page_set_accessed(&block->page);
@ -4861,24 +4865,6 @@ buf_page_get_known_nowait(
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG
if (mode != BUF_KEEP_OLD) {
/* If mode == BUF_KEEP_OLD, we are executing an I/O
completion routine. Avoid a bogus assertion failure
when ibuf_merge_or_delete_for_page() is processing a
page that was just freed due to DROP INDEX, or
deleting a record from SYS_INDEXES. This check will be
skipped in recv_recover_page() as well. */
# ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->page.file_page_was_freed
|| btr_search_check_marked_free_index(block));
# else /* BTR_CUR_HASH_ADAPT */
ut_ad(!block->page.file_page_was_freed);
# endif /* BTR_CUR_HASH_ADAPT */
}
#endif /* UNIV_DEBUG */
buf_pool->stat.n_page_gets++;
return(TRUE);

View File

@ -5435,7 +5435,7 @@ dict_set_corrupted(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type
@ -5538,7 +5538,7 @@ dict_index_set_merge_threshold(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple)
&& rec_get_n_fields_old(btr_cur_get_rec(&cursor))

View File

@ -3437,7 +3437,7 @@ fts_add_doc_by_id(
btr_pcur_open_with_no_init(
fts_id_index, tuple, PAGE_CUR_LE, BTR_SEARCH_LEAF,
&pcur, 0, &mtr);
&pcur, &mtr);
/* If we have a match, add the data to doc structure */
if (btr_pcur_get_low_match(&pcur) == 1) {
@ -3475,7 +3475,7 @@ fts_add_doc_by_id(
btr_pcur_open_with_no_init(
clust_index, clust_ref, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &clust_pcur, 0, &mtr);
BTR_SEARCH_LEAF, &clust_pcur, &mtr);
doc_pcur = &clust_pcur;
clust_rec = btr_pcur_get_rec(&clust_pcur);

View File

@ -588,7 +588,7 @@ rtr_pcur_open_low(
}
btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
btr_cursor, 0, file, line, mtr);
btr_cursor, file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known = NULL;
@ -756,8 +756,7 @@ static void rtr_get_father_node(
/* root split, and search the new root */
btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, 0,
__FILE__, __LINE__, mtr);
BTR_CONT_MODIFY_TREE, btr_cur, __FILE__, __LINE__, mtr);
} else {
/* btr_validate */
@ -766,8 +765,7 @@ static void rtr_get_father_node(
btr_cur_search_to_nth_level(
index, level, tuple, PAGE_CUR_RTREE_LOCATE,
BTR_CONT_MODIFY_TREE, btr_cur, 0,
__FILE__, __LINE__, mtr);
BTR_CONT_MODIFY_TREE, btr_cur, __FILE__, __LINE__, mtr);
rec = btr_cur_get_rec(btr_cur);
n_fields = dtuple_get_n_fields_cmp(tuple);

View File

@ -170,56 +170,41 @@ btr_cur_optimistic_latch_leaves(
unsigned line,
mtr_t* mtr);
/********************************************************************//**
Searches an index tree and positions a tree cursor on a given level.
/** Searches an index tree and positions a tree cursor on a given level.
NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
to node pointer page number fields on the upper levels of the tree!
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
dberr_t
btr_cur_search_to_nth_level_func(
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
tuple must be set so that it cannot get
compared to the node ptr page number field! */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
prefix of a record, mode should be PAGE_CUR_LE,
not PAGE_CUR_GE, as the latter may end up on
the previous page of the record! Inserts
should always be made using PAGE_CUR_LE to
search the position! */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ..., ORed with
at most one of BTR_INSERT, BTR_DELETE_MARK,
BTR_DELETE, or BTR_ESTIMATE;
cursor->left_block is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch
protects the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: currently held btr_search_latch
(in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in/out: mini-transaction */
ib_uint64_t autoinc = 0);
/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
#ifdef BTR_CUR_HASH_ADAPT
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,a,fi,li,mtr)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_cur_search_to_nth_level(i,l,t,m,lm,c,a,fi,li,mtr) \
btr_cur_search_to_nth_level_func(i,l,t,m,lm,c,fi,li,mtr)
#endif /* BTR_CUR_HASH_ADAPT */
If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@param mode PAGE_CUR_L, NOTE that if the search is made using a unique
prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record! Inserts should always be made using PAGE_CUR_LE
to search the position!
@param latch_mode BTR_SEARCH_LEAF, ..., ORed with at most one of BTR_INSERT,
BTR_DELETE_MARK, BTR_DELETE, or BTR_ESTIMATE;
cursor->left_block is used to store a pointer to the left
neighbor page, in the cases BTR_SEARCH_PREV and
BTR_MODIFY_PREV; NOTE that if ahi_latch, we might not have a
cursor page latch, we assume that ahi_latch protects the
record!
@param cursor tree cursor; the cursor page is s- or x-latched, but see also
above!
@param file file name
@param line line where called
@param mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@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,
btr_cur_t *cursor, const char *file,
unsigned line, mtr_t *mtr,
ib_uint64_t autoinc= 0);
/*****************************************************************//**
Opens a cursor at either end of an index.

View File

@ -116,41 +116,30 @@ btr_pcur_open_low(
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open(i,t,md,l,c,m) \
btr_pcur_open_low(i,0,t,md,l,c,__FILE__,__LINE__,0,m)
/**************************************************************//**
Opens an persistent cursor to an index tree without initializing the
cursor. */
/** Opens an persistent cursor to an index tree without initializing the
cursor.
@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record!
@param latch_mode BTR_SEARCH_LEAF, ...; NOTE that if ahi_latch then we might
not acquire a cursor page latch, but assume that the
ahi_latch protects the record!
@param cursor memory buffer for persistent cursor
@param file file name
@param line line where called
@param mtr mtr
@return DB_SUCCESS on success or error code otherwise. */
UNIV_INLINE
dberr_t
btr_pcur_open_with_no_init_func(
/*============================*/
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, ...;
NOTE that if the search is made using a unique
prefix of a record, mode should be
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#ifdef BTR_CUR_HASH_ADAPT
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,ahi,__FILE__,__LINE__,m)
#else /* BTR_CUR_HASH_ADAPT */
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,ahi,m) \
dberr_t btr_pcur_open_with_no_init_func(dict_index_t *index,
const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode,
btr_pcur_t *cursor, const char *file,
unsigned line, mtr_t *mtr);
# define btr_pcur_open_with_no_init(ix,t,md,l,cur,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,__FILE__,__LINE__,m)
#endif /* BTR_CUR_HASH_ADAPT */
/*****************************************************************//**
Opens a persistent cursor at either end of an index. */

View File

@ -438,11 +438,8 @@ btr_pcur_open_low(
ut_ad(!dict_index_is_spatial(index));
err = btr_cur_search_to_nth_level_func(
err = btr_cur_search_to_nth_level(
index, level, tuple, mode, latch_mode, btr_cursor,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr, autoinc);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
@ -462,34 +459,28 @@ btr_pcur_open_low(
return(err);
}
/**************************************************************//**
Opens an persistent cursor to an index tree without initializing the
cursor. */
/** Opens an persistent cursor to an index tree without initializing the
cursor.
@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
PAGE_CUR_GE, as the latter may end up on the previous page of
the record!
@param latch_mode BTR_SEARCH_LEAF, ...; NOTE that if ahi_latch then we might
not acquire a cursor page latch, but assume that the
ahi_latch protects the record!
@param cursor memory buffer for persistent cursor
@param file file name
@param line line where called
@param mtr mtr
@return DB_SUCCESS on success or error code otherwise. */
UNIV_INLINE
dberr_t
btr_pcur_open_with_no_init_func(
/*============================*/
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, ...;
NOTE that if the search is made using a unique
prefix of a record, mode should be
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if ahi_latch then we might not
acquire a cursor page latch, but assume
that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: adaptive hash index latch held
by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
dberr_t btr_pcur_open_with_no_init_func(dict_index_t *index,
const dtuple_t *tuple,
page_cur_mode_t mode, ulint latch_mode,
btr_pcur_t *cursor, const char *file,
unsigned line, mtr_t *mtr)
{
btr_cur_t* btr_cursor;
dberr_t err = DB_SUCCESS;
@ -501,11 +492,8 @@ btr_pcur_open_with_no_init_func(
btr_cursor = btr_pcur_get_btr_cur(cursor);
err = btr_cur_search_to_nth_level_func(
err = btr_cur_search_to_nth_level(
index, 0, tuple, mode, latch_mode, btr_cursor,
#ifdef BTR_CUR_HASH_ADAPT
ahi_latch,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;

View File

@ -80,7 +80,6 @@ btr_search_guess_on_hash(
ulint mode,
ulint latch_mode,
btr_cur_t* cursor,
rw_lock_t* ahi_latch,
mtr_t* mtr);
/** Move or delete hash entries for moved records, usually in a page split.

View File

@ -1137,7 +1137,7 @@ row_ins_foreign_check_on_constraint(
tmp_heap);
btr_pcur_open_with_no_init(clust_index, ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, 0, mtr);
cascade->pcur, mtr);
clust_rec = btr_pcur_get_rec(cascade->pcur);
clust_block = btr_pcur_get_block(cascade->pcur);
@ -2958,7 +2958,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
if (mode == BTR_MODIFY_LEAF && rtr_info.mbr_adj) {
mtr_commit(&mtr);
@ -2977,7 +2977,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_RTREE_INSERT,
search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
mode = BTR_MODIFY_TREE;
}
@ -2989,7 +2989,7 @@ row_ins_sec_index_entry_low(
err = btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
search_mode,
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
}
if (err != DB_SUCCESS) {
@ -3083,7 +3083,7 @@ row_ins_sec_index_entry_low(
index, 0, entry, PAGE_CUR_LE,
(search_mode
& ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),
&cursor, 0, __FILE__, __LINE__, &mtr);
&cursor, __FILE__, __LINE__, &mtr);
}
if (row_ins_must_modify_rec(&cursor)) {

View File

@ -3354,7 +3354,7 @@ row_log_apply_op_low(
has_index_lock
? BTR_MODIFY_TREE
: BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__,
&cursor, __FILE__, __LINE__,
&mtr);
ut_ad(dict_index_get_n_unique(index) > 0);
@ -3403,7 +3403,7 @@ row_log_apply_op_low(
index->set_modified(mtr);
btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0,
BTR_MODIFY_TREE, &cursor,
__FILE__, __LINE__, &mtr);
/* No other thread than the current one
@ -3506,7 +3506,7 @@ insert_the_rec:
index->set_modified(mtr);
btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0,
BTR_MODIFY_TREE, &cursor,
__FILE__, __LINE__, &mtr);
}

View File

@ -163,7 +163,7 @@ public:
btr_cur_search_to_nth_level(m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_LEAF, &ins_cur,
0, __FILE__, __LINE__,
__FILE__, __LINE__,
&mtr);
/* It need to update MBR in parent entry,
@ -179,7 +179,7 @@ public:
btr_cur_search_to_nth_level(
m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE, &ins_cur, 0,
BTR_MODIFY_TREE, &ins_cur,
__FILE__, __LINE__, &mtr);
}
@ -202,8 +202,7 @@ public:
m_index, 0, dtuple,
PAGE_CUR_RTREE_INSERT,
BTR_MODIFY_TREE,
&ins_cur, 0,
__FILE__, __LINE__, &mtr);
&ins_cur, __FILE__, __LINE__, &mtr);
error = btr_cur_pessimistic_insert(
flag, &ins_cur, &ins_offsets,

View File

@ -985,8 +985,7 @@ row_sel_get_clust_rec(
index = dict_table_get_first_index(plan->table);
btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
BTR_SEARCH_LEAF, &plan->clust_pcur,
0, mtr);
BTR_SEARCH_LEAF, &plan->clust_pcur, mtr);
clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
@ -1394,8 +1393,7 @@ row_sel_open_pcur(
/* Open pcur to the index */
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
BTR_SEARCH_LEAF, &plan->pcur,
NULL, mtr);
BTR_SEARCH_LEAF, &plan->pcur, mtr);
} else {
/* Open the cursor to the start or the end of the index
(FALSE: no init) */
@ -3369,7 +3367,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
PAGE_CUR_LE, BTR_SEARCH_LEAF,
prebuilt->clust_pcur, 0, mtr);
prebuilt->clust_pcur, mtr);
clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
@ -3952,15 +3950,12 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(dict_index_is_clust(index));
ut_ad(!prebuilt->templ_contains_blob);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);
BTR_SEARCH_LEAF, pcur, mtr);
rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) {
retry:
rw_lock_s_unlock(ahi_latch);
return(SEL_RETRY);
}
@ -3970,7 +3965,6 @@ retry:
if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) {
exhausted:
rw_lock_s_unlock(ahi_latch);
return(SEL_EXHAUSTED);
}
@ -3994,7 +3988,6 @@ exhausted:
*out_rec = rec;
rw_lock_s_unlock(ahi_latch);
return(SEL_FOUND);
}
#endif /* BTR_CUR_HASH_ADAPT */
@ -4728,8 +4721,7 @@ wait_table_again:
}
err = btr_pcur_open_with_no_init(index, search_tuple, mode,
BTR_SEARCH_LEAF,
pcur, 0, &mtr);
BTR_SEARCH_LEAF, pcur, &mtr);
if (err != DB_SUCCESS) {
rec = NULL;