MDEV-14952 Avoid repeated calls to btr_get_search_latch()

btr_cur_search_to_nth_level(), btr_search_guess_on_hash(),
btr_pcur_open_with_no_init_func(), row_sel_open_pcur():
Replace the parameter has_search_latch with the ahi_latch
(passed as NULL if the caller does not hold the latch).

btr_search_update_hash_node_on_insert(),
btr_search_update_hash_on_insert(),
btr_search_build_page_hash_index(): Add the parameter ahi_latch.

btr_search_x_lock(), btr_search_x_unlock(),
btr_search_s_lock(), btr_search_s_unlock(): Remove.
This commit is contained in:
Marko Mäkelä 2018-01-15 19:51:09 +02:00
parent 4beb699a36
commit 0664d633e4
9 changed files with 270 additions and 325 deletions

View File

@ -919,8 +919,7 @@ 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, immediately after the cursor. Thus, the cursor may end up on a user record,
or on a page infimum record. */ or on a page infimum record. */
dberr_t dberr_t
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level_func(
/*========================*/
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */ ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
@ -935,17 +934,16 @@ btr_cur_search_to_nth_level(
cursor->left_block is used to store a pointer cursor->left_block is used to store a pointer
to the left neighbor page, in the cases to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV; BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch NOTE that if ahi_latch, we might not have a
is != 0, we maybe do not have a latch set cursor page latch, we assume that ahi_latch
on the cursor page, we assume protects the record! */
the caller uses his search latch
to protect the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */ s- or x-latched, but see also above! */
ulint has_search_latch, #ifdef BTR_CUR_HASH_ADAPT
/*!< in: info on the latch mode the rw_lock_t* ahi_latch,
caller currently has on search system: /*!< in: currently held btr_search_latch
RW_S_LATCH, or 0 */ (in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */ unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
@ -1123,7 +1121,7 @@ btr_cur_search_to_nth_level(
&& mode != PAGE_CUR_LE_OR_EXTENDS && mode != PAGE_CUR_LE_OR_EXTENDS
# endif /* PAGE_CUR_LE_OR_EXTENDS */ # endif /* PAGE_CUR_LE_OR_EXTENDS */
&& !dict_index_is_spatial(index) && !dict_index_is_spatial(index)
/* If !has_search_latch, we do a dirty read of /* If !ahi_latch, we do a dirty read of
btr_search_enabled below, and btr_search_guess_on_hash() btr_search_enabled below, and btr_search_guess_on_hash()
will have to check it again. */ will have to check it again. */
&& btr_search_enabled && btr_search_enabled
@ -1131,7 +1129,7 @@ btr_cur_search_to_nth_level(
&& !(tuple->info_bits & REC_INFO_MIN_REC_FLAG) && !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)
&& btr_search_guess_on_hash(index, info, tuple, mode, && btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor, latch_mode, cursor,
has_search_latch, mtr)) { ahi_latch, mtr)) {
/* Search using the hash index succeeded */ /* Search using the hash index succeeded */
@ -1152,10 +1150,12 @@ btr_cur_search_to_nth_level(
/* If the hash search did not succeed, do binary search down the /* If the hash search did not succeed, do binary search down the
tree */ tree */
if (has_search_latch) { #ifdef BTR_CUR_HASH_ADAPT
if (ahi_latch) {
/* Release possible search latch to obey latching order */ /* Release possible search latch to obey latching order */
btr_search_s_unlock(index); 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 /* 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) */ know how to release it when we have latched leaf node(s) */
@ -2222,15 +2222,17 @@ func_exit:
ut_free(prev_tree_savepoints); ut_free(prev_tree_savepoints);
} }
if (has_search_latch) {
btr_search_s_lock(index);
}
if (mbr_adj) { if (mbr_adj) {
/* remember that we will need to adjust parent MBR */ /* remember that we will need to adjust parent MBR */
cursor->rtr_info->mbr_adj = true; 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); DBUG_RETURN(err);
} }
@ -3300,10 +3302,14 @@ fail_err:
ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW); ut_ad(entry->info_bits == REC_INFO_DEFAULT_ROW);
ut_ad(index->is_instant()); ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG); ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(cursor);
} else { } else {
btr_search_update_hash_on_insert(cursor); rw_lock_t* ahi_latch = btr_get_search_latch(index);
if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(
cursor, ahi_latch);
} else {
btr_search_update_hash_on_insert(cursor, ahi_latch);
}
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
@ -3509,7 +3515,8 @@ btr_cur_pessimistic_insert(
ut_ad((flags & ~BTR_KEEP_IBUF_BITMAP) ut_ad((flags & ~BTR_KEEP_IBUF_BITMAP)
== BTR_NO_LOCKING_FLAG); == BTR_NO_LOCKING_FLAG);
} else { } else {
btr_search_update_hash_on_insert(cursor); btr_search_update_hash_on_insert(
cursor, btr_get_search_latch(index));
} }
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) { if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) {

View File

@ -353,7 +353,11 @@ btr_pcur_restore_position_func(
} }
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
cursor, 0, file, line, mtr); cursor,
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
/* Restore the old search mode */ /* Restore the old search mode */
cursor->search_mode = old_mode; cursor->search_mode = old_mode;

View File

@ -48,7 +48,7 @@ Search system is protected by array of latches. */
char btr_search_enabled = true; char btr_search_enabled = true;
/** Number of adaptive hash index partition. */ /** Number of adaptive hash index partition. */
ulong btr_ahi_parts = 8; ulong btr_ahi_parts;
#ifdef UNIV_SEARCH_PERF_STAT #ifdef UNIV_SEARCH_PERF_STAT
/** Number of successful adaptive hash index lookups */ /** Number of successful adaptive hash index lookups */
@ -177,23 +177,6 @@ btr_search_get_n_fields(
return(btr_search_get_n_fields(cursor->n_fields, cursor->n_bytes)); return(btr_search_get_n_fields(cursor->n_fields, cursor->n_bytes));
} }
/********************************************************************//**
Builds a hash index on a page with the given parameters. If the page already
has a hash index with different parameters, the old hash index is removed.
If index is non-NULL, this function checks if n_fields and n_bytes are
sensible values, and does not build a hash index if not. */
static
void
btr_search_build_page_hash_index(
/*=============================*/
dict_index_t* index, /*!< in: index for which to build, or NULL if
not known */
buf_block_t* block, /*!< in: index page, s- or x-latched */
ulint n_fields,/*!< in: hash this many full fields */
ulint n_bytes,/*!< in: hash this many bytes from the next
field */
ibool left_side);/*!< in: hash for searches from left side? */
/** This function should be called before reserving any btr search mutex, if /** This function should be called before reserving any btr search mutex, if
the intended operation might add nodes to the search system hash table. the intended operation might add nodes to the search system hash table.
Because of the latching order, once we have reserved the btr search system Because of the latching order, once we have reserved the btr search system
@ -224,8 +207,9 @@ btr_search_check_free_space_in_heap(dict_index_t* index)
if (heap->free_block == NULL) { if (heap->free_block == NULL) {
buf_block_t* block = buf_block_alloc(NULL); buf_block_t* block = buf_block_alloc(NULL);
rw_lock_t* ahi_latch = btr_get_search_latch(index);
btr_search_x_lock(index); rw_lock_x_lock(ahi_latch);
if (btr_search_enabled if (btr_search_enabled
&& heap->free_block == NULL) { && heap->free_block == NULL) {
@ -234,7 +218,7 @@ btr_search_check_free_space_in_heap(dict_index_t* index)
buf_block_free(block); buf_block_free(block);
} }
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
} }
} }
@ -457,12 +441,10 @@ btr_search_info_get_ref_count(
ut_ad(info); ut_ad(info);
ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_S)); rw_lock_t* ahi_latch = btr_get_search_latch(index);
ut_ad(!rw_lock_own(btr_get_search_latch(index), RW_LOCK_X)); rw_lock_s_lock(ahi_latch);
btr_search_s_lock(index);
ret = info->ref_count; ret = info->ref_count;
btr_search_s_unlock(index); rw_lock_s_unlock(ahi_latch);
return(ret); return(ret);
} }
@ -723,61 +705,6 @@ btr_search_update_hash_ref(
} }
} }
/** Updates the search info.
@param[in,out] info search info
@param[in] cursor cursor which was just positioned */
void
btr_search_info_update_slow(
btr_search_t* info,
btr_cur_t* cursor)
{
buf_block_t* block;
ibool build_index;
ut_ad(!rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_S));
ut_ad(!rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X));
block = btr_cur_get_block(cursor);
/* NOTE that the following two function calls do NOT protect
info or block->n_fields etc. with any semaphore, to save CPU time!
We cannot assume the fields are consistent when we return from
those functions! */
btr_search_info_update_hash(info, cursor);
build_index = btr_search_update_block_hash_info(info, block, cursor);
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index);
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_hash_fail++;
#endif /* UNIV_SEARCH_PERF_STAT */
btr_search_x_lock(cursor->index);
btr_search_update_hash_ref(info, block, cursor);
btr_search_x_unlock(cursor->index);
}
if (build_index) {
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
btr_search_build_page_hash_index(cursor->index, block,
block->n_fields,
block->n_bytes,
block->left_side);
}
}
/** Checks if a guessed position for a tree cursor is right. Note that if /** Checks if a guessed position for a tree cursor is right. Note that if
mode is PAGE_CUR_LE, which is used in inserts, and the function returns mode is PAGE_CUR_LE, which is used in inserts, and the function returns
TRUE, then cursor->up_match and cursor->low_match both have sensible values. TRUE, then cursor->up_match and cursor->low_match both have sensible values.
@ -947,12 +874,11 @@ both have sensible values.
we assume the caller uses his search latch we assume the caller uses his search latch
to protect the record! to protect the record!
@param[out] cursor tree cursor @param[out] cursor tree cursor
@param[in] has_search_latch @param[in] ahi_latch the adaptive hash index latch being held,
latch mode the caller currently has on or NULL
search system: RW_S/X_LATCH or 0
@param[in] mtr mini transaction @param[in] mtr mini transaction
@return TRUE if succeeded */ @return whether the search succeeded */
ibool bool
btr_search_guess_on_hash( btr_search_guess_on_hash(
dict_index_t* index, dict_index_t* index,
btr_search_t* info, btr_search_t* info,
@ -960,7 +886,7 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
ulint has_search_latch, rw_lock_t* ahi_latch,
mtr_t* mtr) mtr_t* mtr)
{ {
const rec_t* rec; const rec_t* rec;
@ -970,6 +896,8 @@ btr_search_guess_on_hash(
btr_cur_t cursor2; btr_cur_t cursor2;
btr_pcur_t pcur; btr_pcur_t pcur;
#endif #endif
ut_ad(!ahi_latch || rw_lock_own(ahi_latch, RW_LOCK_S)
|| rw_lock_own(ahi_latch, RW_LOCK_X));
if (!btr_search_enabled) { if (!btr_search_enabled) {
return(FALSE); return(FALSE);
@ -977,6 +905,7 @@ btr_search_guess_on_hash(
ut_ad(index && info && tuple && cursor && mtr); ut_ad(index && info && tuple && cursor && mtr);
ut_ad(!dict_index_is_ibuf(index)); 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) ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF)); || (latch_mode == BTR_MODIFY_LEAF));
@ -1009,16 +938,16 @@ btr_search_guess_on_hash(
cursor->fold = fold; cursor->fold = fold;
cursor->flag = BTR_CUR_HASH; cursor->flag = BTR_CUR_HASH;
if (!has_search_latch) { rw_lock_t* use_latch = ahi_latch ? NULL : btr_get_search_latch(index);
btr_search_s_lock(index);
if (use_latch) {
rw_lock_s_lock(use_latch);
if (!btr_search_enabled) { if (!btr_search_enabled) {
btr_search_s_unlock(index); goto fail;
btr_search_failure(info, cursor);
return(FALSE);
} }
} else {
ut_ad(btr_search_enabled);
} }
ut_ad(rw_lock_own(btr_get_search_latch(index), RW_LOCK_S)); ut_ad(rw_lock_own(btr_get_search_latch(index), RW_LOCK_S));
@ -1027,9 +956,9 @@ btr_search_guess_on_hash(
btr_get_search_table(index), fold); btr_get_search_table(index), fold);
if (rec == NULL) { if (rec == NULL) {
if (use_latch) {
if (!has_search_latch) { fail:
btr_search_s_unlock(index); rw_lock_s_unlock(use_latch);
} }
btr_search_failure(info, cursor); btr_search_failure(info, cursor);
@ -1039,22 +968,15 @@ btr_search_guess_on_hash(
buf_block_t* block = buf_block_from_ahi(rec); buf_block_t* block = buf_block_from_ahi(rec);
if (!has_search_latch) { if (use_latch) {
if (!buf_page_get_known_nowait( if (!buf_page_get_known_nowait(
latch_mode, block, BUF_MAKE_YOUNG, latch_mode, block, BUF_MAKE_YOUNG,
__FILE__, __LINE__, mtr)) { __FILE__, __LINE__, mtr)) {
goto fail;
if (!has_search_latch) {
btr_search_s_unlock(index);
} }
btr_search_failure(info, cursor); rw_lock_s_unlock(use_latch);
return(FALSE);
}
btr_search_s_unlock(index);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
} }
@ -1063,7 +985,7 @@ btr_search_guess_on_hash(
ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH); ut_ad(buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH);
if (!has_search_latch) { if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr); btr_leaf_page_release(block, latch_mode, mtr);
} }
@ -1085,11 +1007,9 @@ btr_search_guess_on_hash(
record to determine if our guess for the cursor position is record to determine if our guess for the cursor position is
right. */ right. */
if (index_id != btr_page_get_index_id(block->frame) if (index_id != btr_page_get_index_id(block->frame)
|| !btr_search_check_guess(cursor, || !btr_search_check_guess(cursor, !!ahi_latch, tuple, mode)) {
has_search_latch,
tuple, mode)) {
if (!has_search_latch) { if (!ahi_latch) {
btr_leaf_page_release(block, latch_mode, mtr); btr_leaf_page_release(block, latch_mode, mtr);
} }
@ -1110,7 +1030,7 @@ btr_search_guess_on_hash(
info->last_hash_succ = FALSE; info->last_hash_succ = FALSE;
/* Currently, does not work if the following fails: */ /* Currently, does not work if the following fails: */
ut_ad(!has_search_latch); ut_ad(!ahi_latch);
btr_leaf_page_release(block, latch_mode, mtr); btr_leaf_page_release(block, latch_mode, mtr);
@ -1143,7 +1063,7 @@ btr_search_guess_on_hash(
#ifdef UNIV_SEARCH_PERF_STAT #ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_succ++; btr_search_n_succ++;
#endif #endif
if (!has_search_latch && buf_page_peek_if_too_old(&block->page)) { if (!ahi_latch && buf_page_peek_if_too_old(&block->page)) {
buf_page_make_young(&block->page); buf_page_make_young(&block->page);
} }
@ -1191,6 +1111,8 @@ retry:
/* This debug check uses a dirty read that could theoretically cause /* This debug check uses a dirty read that could theoretically cause
false positives while buf_pool_clear_hash_index() is executing. */ false positives while buf_pool_clear_hash_index() is executing. */
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
if (index == NULL) { if (index == NULL) {
return; return;
@ -1214,9 +1136,6 @@ retry:
% btr_ahi_parts; % btr_ahi_parts;
latch = btr_search_latches[ahi_slot]; latch = btr_search_latches[ahi_slot];
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
rw_lock_s_lock(latch); rw_lock_s_lock(latch);
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
@ -1419,6 +1338,7 @@ If index is non-NULL, this function checks if n_fields and n_bytes are
sensible, and does not build a hash index if not. sensible, and does not build a hash index if not.
@param[in,out] index index for which to build. @param[in,out] index index for which to build.
@param[in,out] block index page, s-/x- latched. @param[in,out] block index page, s-/x- latched.
@param[in,out] ahi_latch the adaptive search latch
@param[in] n_fields hash this many full fields @param[in] n_fields hash this many full fields
@param[in] n_bytes hash this many bytes of the next field @param[in] n_bytes hash this many bytes of the next field
@param[in] left_side hash for searches from left side */ @param[in] left_side hash for searches from left side */
@ -1427,12 +1347,11 @@ void
btr_search_build_page_hash_index( btr_search_build_page_hash_index(
dict_index_t* index, dict_index_t* index,
buf_block_t* block, buf_block_t* block,
rw_lock_t* ahi_latch,
ulint n_fields, ulint n_fields,
ulint n_bytes, ulint n_bytes,
ibool left_side) ibool left_side)
{ {
hash_table_t* table;
page_t* page;
const rec_t* rec; const rec_t* rec;
const rec_t* next_rec; const rec_t* next_rec;
ulint fold; ulint fold;
@ -1454,6 +1373,7 @@ btr_search_build_page_hash_index(
} }
rec_offs_init(offsets_); rec_offs_init(offsets_);
ut_ad(ahi_latch == btr_get_search_latch(index));
ut_ad(index); ut_ad(index);
ut_ad(block->page.id.space() == index->space); ut_ad(block->page.id.space() == index->space);
ut_a(!dict_index_is_ibuf(index)); ut_a(!dict_index_is_ibuf(index));
@ -1463,20 +1383,17 @@ btr_search_build_page_hash_index(
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S) ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S)
|| rw_lock_own(&(block->lock), RW_LOCK_X)); || rw_lock_own(&(block->lock), RW_LOCK_X));
btr_search_s_lock(index); rw_lock_s_lock(ahi_latch);
table = btr_get_search_table(index); const bool rebuild = block->index
page = buf_block_get_frame(block); && (block->curr_n_fields != n_fields
|| block->curr_n_bytes != n_bytes
|| block->curr_left_side != left_side);
if (block->index && ((block->curr_n_fields != n_fields) rw_lock_s_unlock(ahi_latch);
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
btr_search_s_unlock(index);
if (rebuild) {
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
} else {
btr_search_s_unlock(index);
} }
/* Check that the values for hash index build are sensible */ /* Check that the values for hash index build are sensible */
@ -1491,6 +1408,7 @@ btr_search_build_page_hash_index(
return; return;
} }
page_t* page = buf_block_get_frame(block);
n_recs = page_get_n_recs(page); n_recs = page_get_n_recs(page);
if (n_recs == 0) { if (n_recs == 0) {
@ -1573,7 +1491,8 @@ btr_search_build_page_hash_index(
btr_search_check_free_space_in_heap(index); btr_search_check_free_space_in_heap(index);
btr_search_x_lock(index); hash_table_t* table = btr_get_search_table(index);
rw_lock_x_lock(ahi_latch);
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto exit_func; goto exit_func;
@ -1611,7 +1530,7 @@ btr_search_build_page_hash_index(
MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached); MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
exit_func: exit_func:
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
ut_free(folds); ut_free(folds);
ut_free(recs); ut_free(recs);
@ -1620,6 +1539,60 @@ exit_func:
} }
} }
/** Updates the search info.
@param[in,out] info search info
@param[in,out] cursor cursor which was just positioned */
void
btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor)
{
rw_lock_t* ahi_latch = btr_get_search_latch(cursor->index);
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_S));
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_X));
buf_block_t* block = btr_cur_get_block(cursor);
/* NOTE that the following two function calls do NOT protect
info or block->n_fields etc. with any semaphore, to save CPU time!
We cannot assume the fields are consistent when we return from
those functions! */
btr_search_info_update_hash(info, cursor);
bool build_index = btr_search_update_block_hash_info(
info, block, cursor);
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index);
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
#ifdef UNIV_SEARCH_PERF_STAT
btr_search_n_hash_fail++;
#endif /* UNIV_SEARCH_PERF_STAT */
rw_lock_x_lock(ahi_latch);
btr_search_update_hash_ref(info, block, cursor);
rw_lock_x_unlock(ahi_latch);
}
if (build_index) {
/* Note that since we did not protect block->n_fields etc.
with any semaphore, the values can be inconsistent. We have
to check inside the function call that they make sense. */
btr_search_build_page_hash_index(cursor->index, block,
ahi_latch,
block->n_fields,
block->n_bytes,
block->left_side);
}
}
/** Move or delete hash entries for moved records, usually in a page split. /** Move or delete hash entries for moved records, usually in a page split.
If new_block is already hashed, then any hash index for block is dropped. If new_block is already hashed, then any hash index for block is dropped.
If new_block is not hashed, and block is hashed, then a new hash index is If new_block is not hashed, and block is hashed, then a new hash index is
@ -1638,19 +1611,27 @@ btr_search_move_or_delete_hash_entries(
return; return;
} }
dict_index_t* index = block->index;
if (!index) {
index = new_block->index;
} else {
ut_ad(!new_block->index || index == new_block->index);
}
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block); assert_block_ahi_valid(new_block);
rw_lock_t* ahi_latch = index ? btr_get_search_latch(index) : NULL;
if (new_block->index) { if (new_block->index) {
btr_search_drop_page_hash_index(block); btr_search_drop_page_hash_index(block);
return; return;
} }
dict_index_t* index = block->index;
if (!index) { if (!index) {
return; return;
} }
btr_search_s_lock(index);
rw_lock_s_lock(ahi_latch);
if (block->index) { if (block->index) {
ulint n_fields = block->curr_n_fields; ulint n_fields = block->curr_n_fields;
@ -1661,19 +1642,20 @@ btr_search_move_or_delete_hash_entries(
new_block->n_bytes = block->curr_n_bytes; new_block->n_bytes = block->curr_n_bytes;
new_block->left_side = left_side; new_block->left_side = left_side;
btr_search_s_unlock(index); rw_lock_s_unlock(ahi_latch);
ut_a(n_fields > 0 || n_bytes > 0); ut_a(n_fields > 0 || n_bytes > 0);
btr_search_build_page_hash_index( btr_search_build_page_hash_index(
index, new_block, n_fields, n_bytes, left_side); index, new_block, ahi_latch,
n_fields, n_bytes, left_side);
ut_ad(n_fields == block->curr_n_fields); ut_ad(n_fields == block->curr_n_fields);
ut_ad(n_bytes == block->curr_n_bytes); ut_ad(n_bytes == block->curr_n_bytes);
ut_ad(left_side == block->curr_left_side); ut_ad(left_side == block->curr_left_side);
return; return;
} }
btr_search_s_unlock(index); rw_lock_s_unlock(ahi_latch);
} }
/** Updates the page hash index when a single record is deleted from a page. /** Updates the page hash index when a single record is deleted from a page.
@ -1728,7 +1710,9 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
mem_heap_free(heap); mem_heap_free(heap);
} }
btr_search_x_lock(index); rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_x_lock(ahi_latch);
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
if (block->index) { if (block->index) {
@ -1744,21 +1728,25 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor)
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
} }
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
} }
/** Updates the page hash index when a single record is inserted on a page. /** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the place to insert @param[in] cursor cursor which was positioned to the place to insert
using btr_cur_search_, and the new record has been using btr_cur_search_, and the new record has been
inserted next to the cursor. */ inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */
void void
btr_search_update_hash_node_on_insert(btr_cur_t* cursor) btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
{ {
hash_table_t* table; hash_table_t* table;
buf_block_t* block; buf_block_t* block;
dict_index_t* index; dict_index_t* index;
rec_t* rec; rec_t* rec;
ut_ad(ahi_latch == btr_get_search_latch(cursor->index));
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
#ifdef MYSQL_INDEX_DISABLE_AHI #ifdef MYSQL_INDEX_DISABLE_AHI
if (cursor->index->disable_ahi) return; if (cursor->index->disable_ahi) return;
#endif #endif
@ -1781,8 +1769,7 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
ut_a(cursor->index == index); ut_a(cursor->index == index);
ut_a(!dict_index_is_ibuf(index)); ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(ahi_latch);
btr_search_x_lock(index);
if (!block->index) { if (!block->index) {
@ -1806,11 +1793,11 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor)
func_exit: func_exit:
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
} else { } else {
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
btr_search_update_hash_on_insert(cursor); btr_search_update_hash_on_insert(cursor, ahi_latch);
} }
} }
@ -1818,9 +1805,10 @@ func_exit:
@param[in,out] cursor cursor which was positioned to the @param[in,out] cursor cursor which was positioned to the
place to insert using btr_cur_search_..., place to insert using btr_cur_search_...,
and the new record has been inserted next and the new record has been inserted next
to the cursor */ to the cursor
@param[in] ahi_latch the adaptive hash index latch */
void void
btr_search_update_hash_on_insert(btr_cur_t* cursor) btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
{ {
hash_table_t* table; hash_table_t* table;
buf_block_t* block; buf_block_t* block;
@ -1834,13 +1822,16 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
ulint n_fields; ulint n_fields;
ulint n_bytes; ulint n_bytes;
ibool left_side; ibool left_side;
ibool locked = FALSE; bool locked = false;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_; ulint* offsets = offsets_;
rec_offs_init(offsets_); rec_offs_init(offsets_);
ut_ad(ahi_latch == btr_get_search_latch(cursor->index));
ut_ad(page_is_leaf(btr_cur_get_page(cursor))); ut_ad(page_is_leaf(btr_cur_get_page(cursor)));
ut_ad(!btr_search_own_any(RW_LOCK_S));
ut_ad(!btr_search_own_any(RW_LOCK_X));
#ifdef MYSQL_INDEX_DISABLE_AHI #ifdef MYSQL_INDEX_DISABLE_AHI
if (cursor->index->disable_ahi) return; if (cursor->index->disable_ahi) return;
#endif #endif
@ -1899,10 +1890,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id); fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
} else { } else {
if (left_side) { if (left_side) {
locked = true;
btr_search_x_lock(index); rw_lock_x_lock(ahi_latch);
locked = TRUE;
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto function_exit; goto function_exit;
@ -1917,10 +1906,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor)
if (fold != ins_fold) { if (fold != ins_fold) {
if (!locked) { if (!locked) {
locked = true;
btr_search_x_lock(index); rw_lock_x_lock(ahi_latch);
locked = TRUE;
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto function_exit; goto function_exit;
@ -1938,11 +1925,9 @@ check_next_rec:
if (page_rec_is_supremum(next_rec)) { if (page_rec_is_supremum(next_rec)) {
if (!left_side) { if (!left_side) {
if (!locked) { if (!locked) {
btr_search_x_lock(index); locked = true;
rw_lock_x_lock(ahi_latch);
locked = TRUE;
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto function_exit; goto function_exit;
@ -1958,10 +1943,8 @@ check_next_rec:
if (ins_fold != next_fold) { if (ins_fold != next_fold) {
if (!locked) { if (!locked) {
locked = true;
btr_search_x_lock(index); rw_lock_x_lock(ahi_latch);
locked = TRUE;
if (!btr_search_enabled) { if (!btr_search_enabled) {
goto function_exit; goto function_exit;
@ -1980,8 +1963,9 @@ function_exit:
mem_heap_free(heap); mem_heap_free(heap);
} }
if (locked) { if (locked) {
btr_search_x_unlock(index); rw_lock_x_unlock(ahi_latch);
} }
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_X));
} }
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -177,8 +177,7 @@ 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. 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. */ If mode is PAGE_CUR_GE, then up_match will a have a sensible value. */
dberr_t dberr_t
btr_cur_search_to_nth_level( btr_cur_search_to_nth_level_func(
/*========================*/
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
ulint level, /*!< in: the tree level of search */ ulint level, /*!< in: the tree level of search */
const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in const dtuple_t* tuple, /*!< in: data tuple; NOTE: n_fields_cmp in
@ -197,23 +196,29 @@ btr_cur_search_to_nth_level(
cursor->left_block is used to store a pointer cursor->left_block is used to store a pointer
to the left neighbor page, in the cases to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV; BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch NOTE that if ahi_latch, we might not have a
is != 0, we maybe do not have a latch set cursor page latch, we assume that ahi_latch
on the cursor page, we assume protects the record! */
the caller uses his search latch
to protect the record! */
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */ s- or x-latched, but see also above! */
ulint has_search_latch, #ifdef BTR_CUR_HASH_ADAPT
/*!< in: latch mode the caller rw_lock_t* ahi_latch,
currently has on search system: /*!< in: currently held btr_search_latch
RW_S_LATCH, or 0 */ (in RW_S_LATCH mode), or NULL */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */ unsigned line, /*!< in: line where called */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr, /*!< in/out: mini-transaction */
ib_uint64_t autoinc = 0); ib_uint64_t autoinc = 0);
/*!< in: PAGE_ROOT_AUTO_INC to be written /*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */ (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 */
/*****************************************************************//** /*****************************************************************//**
Opens a cursor at either end of an index. Opens a cursor at either end of an index.

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -136,20 +136,25 @@ btr_pcur_open_with_no_init_func(
may end up on the previous page of the may end up on the previous page of the
record! */ record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...; ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then NOTE that if ahi_latch then we might not
we maybe do not acquire a latch on the cursor acquire a cursor page latch, but assume
page, but assume that the caller uses his that the ahi_latch protects the record! */
btr search latch to protect the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ulint has_search_latch, #ifdef BTR_CUR_HASH_ADAPT
/*!< in: latch mode the caller rw_lock_t* ahi_latch,
currently has on search system: /*!< in: adaptive hash index latch held
RW_S_LATCH, or 0 */ by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */ unsigned line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \ #ifdef BTR_CUR_HASH_ADAPT
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m) # 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) \
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. */ Opens a persistent cursor at either end of an index. */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2017, MariaDB Corporation. Copyright (c) 2015, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -454,9 +454,12 @@ btr_pcur_open_low(
ut_ad(!dict_index_is_spatial(index)); ut_ad(!dict_index_is_spatial(index));
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level_func(
index, level, tuple, mode, latch_mode, index, level, tuple, mode, latch_mode, btr_cursor,
btr_cursor, 0, file, line, mtr, autoinc); #ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr, autoinc);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
ib::warn() << " Error code: " << err ib::warn() << " Error code: " << err
@ -491,15 +494,15 @@ btr_pcur_open_with_no_init_func(
may end up on the previous page of the may end up on the previous page of the
record! */ record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...; ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then NOTE that if ahi_latch then we might not
we maybe do not acquire a latch on the cursor acquire a cursor page latch, but assume
page, but assume that the caller uses his that the ahi_latch protects the record! */
btr search latch to protect the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ulint has_search_latch, #ifdef BTR_CUR_HASH_ADAPT
/*!< in: latch mode the caller rw_lock_t* ahi_latch,
currently has on search system: /*!< in: adaptive hash index latch held
RW_S_LATCH, or 0 */ by the caller, or NULL if none */
#endif /* BTR_CUR_HASH_ADAPT */
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
unsigned line, /*!< in: line where called */ unsigned line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
@ -514,9 +517,12 @@ btr_pcur_open_with_no_init_func(
btr_cursor = btr_pcur_get_btr_cur(cursor); btr_cursor = btr_pcur_get_btr_cur(cursor);
err = btr_cur_search_to_nth_level( err = btr_cur_search_to_nth_level_func(
index, 0, tuple, mode, latch_mode, btr_cursor, index, 0, tuple, mode, latch_mode, btr_cursor,
has_search_latch, file, line, mtr); #ifdef BTR_CUR_HASH_ADAPT
ahi_latch,
#endif /* BTR_CUR_HASH_ADAPT */
file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED; cursor->pos_state = BTR_PCUR_IS_POSITIONED;

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -91,12 +91,11 @@ both have sensible values.
we assume the caller uses his search latch we assume the caller uses his search latch
to protect the record! to protect the record!
@param[out] cursor tree cursor @param[out] cursor tree cursor
@param[in] has_search_latch @param[in] ahi_latch the adaptive hash index latch being held,
latch mode the caller currently has on or NULL
search system: RW_S/X_LATCH or 0
@param[in] mtr mini transaction @param[in] mtr mini transaction
@return TRUE if succeeded */ @return whether the search succeeded */
ibool bool
btr_search_guess_on_hash( btr_search_guess_on_hash(
dict_index_t* index, dict_index_t* index,
btr_search_t* info, btr_search_t* info,
@ -104,7 +103,7 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
ulint has_search_latch, rw_lock_t* ahi_latch,
mtr_t* mtr); mtr_t* mtr);
/** Move or delete hash entries for moved records, usually in a page split. /** Move or delete hash entries for moved records, usually in a page split.
@ -140,17 +139,19 @@ btr_search_drop_page_hash_when_freed(
/** Updates the page hash index when a single record is inserted on a page. /** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the place to insert @param[in] cursor cursor which was positioned to the place to insert
using btr_cur_search_, and the new record has been using btr_cur_search_, and the new record has been
inserted next to the cursor. */ inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */
void void
btr_search_update_hash_node_on_insert(btr_cur_t* cursor); btr_search_update_hash_node_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch);
/** Updates the page hash index when a single record is inserted on a page. /** Updates the page hash index when a single record is inserted on a page.
@param[in] cursor cursor which was positioned to the @param[in,out] cursor cursor which was positioned to the
place to insert using btr_cur_search_..., place to insert using btr_cur_search_...,
and the new record has been inserted next and the new record has been inserted next
to the cursor */ to the cursor
@param[in] ahi_latch the adaptive hash index latch */
void void
btr_search_update_hash_on_insert(btr_cur_t* cursor); btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch);
/** Updates the page hash index when a single record is deleted from a page. /** Updates the page hash index when a single record is deleted from a page.
@param[in] cursor cursor which was positioned on the record to delete @param[in] cursor cursor which was positioned on the record to delete
@ -163,18 +164,6 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor);
bool bool
btr_search_validate(); btr_search_validate();
/** X-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_lock(const dict_index_t* index);
/** X-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_unlock(const dict_index_t* index);
/** Lock all search latches in exclusive mode. */ /** Lock all search latches in exclusive mode. */
UNIV_INLINE UNIV_INLINE
void void
@ -185,18 +174,6 @@ UNIV_INLINE
void void
btr_search_x_unlock_all(); btr_search_x_unlock_all();
/** S-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_lock(const dict_index_t* index);
/** S-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_unlock(const dict_index_t* index);
/** Lock all search latches in shared mode. */ /** Lock all search latches in shared mode. */
UNIV_INLINE UNIV_INLINE
void void
@ -243,15 +220,11 @@ btr_get_search_table(const dict_index_t* index);
#else /* BTR_CUR_HASH_ADAPT */ #else /* BTR_CUR_HASH_ADAPT */
# define btr_search_sys_create(size) # define btr_search_sys_create(size)
# define btr_search_drop_page_hash_index(block) # define btr_search_drop_page_hash_index(block)
# define btr_search_s_lock(index)
# define btr_search_s_unlock(index)
# define btr_search_s_lock_all(index) # define btr_search_s_lock_all(index)
# define btr_search_s_unlock_all(index) # define btr_search_s_unlock_all(index)
# define btr_search_x_lock(index)
# define btr_search_x_unlock(index)
# define btr_search_info_update(index, cursor) # define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block) # define btr_search_move_or_delete_hash_entries(new_block, block)
# define btr_search_update_hash_on_insert(cursor) # define btr_search_update_hash_on_insert(cursor, ahi_latch)
# define btr_search_update_hash_on_delete(cursor) # define btr_search_update_hash_on_delete(cursor)
# define btr_search_sys_resize(hash_size) # define btr_search_sys_resize(hash_size)
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */

View File

@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -45,13 +46,11 @@ btr_search_info_create(mem_heap_t* heap)
} }
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/*********************************************************************//** /** Updates the search info.
Updates the search info. */ @param[in,out] info search info
@param[in,out] cursor cursor which was just positioned */
void void
btr_search_info_update_slow( btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor);
/*========================*/
btr_search_t* info, /*!< in/out: search info */
btr_cur_t* cursor);/*!< in: cursor which was just positioned */
/*********************************************************************//** /*********************************************************************//**
Updates the search info. */ Updates the search info. */
@ -87,24 +86,6 @@ btr_search_info_update(
btr_search_info_update_slow(info, cursor); btr_search_info_update_slow(info, cursor);
} }
/** X-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_lock(const dict_index_t* index)
{
rw_lock_x_lock(btr_get_search_latch(index));
}
/** X-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_x_unlock(const dict_index_t* index)
{
rw_lock_x_unlock(btr_get_search_latch(index));
}
/** Lock all search latches in exclusive mode. */ /** Lock all search latches in exclusive mode. */
UNIV_INLINE UNIV_INLINE
void void
@ -125,24 +106,6 @@ btr_search_x_unlock_all()
} }
} }
/** S-Lock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_lock(const dict_index_t* index)
{
rw_lock_s_lock(btr_get_search_latch(index));
}
/** S-Unlock the search latch (corresponding to given index)
@param[in] index index handler */
UNIV_INLINE
void
btr_search_s_unlock(const dict_index_t* index)
{
rw_lock_s_unlock(btr_get_search_latch(index));
}
/** Lock all search latches in shared mode. */ /** Lock all search latches in shared mode. */
UNIV_INLINE UNIV_INLINE
void void

View File

@ -1273,23 +1273,18 @@ void
row_sel_open_pcur( row_sel_open_pcur(
/*==============*/ /*==============*/
plan_t* plan, /*!< in: table plan */ plan_t* plan, /*!< in: table plan */
ibool search_latch_locked, #ifdef BTR_CUR_HASH_ADAPT
/*!< in: TRUE if the thread currently rw_lock_t* ahi_latch,
has the search latch locked in /*!< in: the adaptive hash index latch */
s-mode */ #endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
dict_index_t* index; dict_index_t* index;
func_node_t* cond; func_node_t* cond;
que_node_t* exp; que_node_t* exp;
ulint n_fields; ulint n_fields;
ulint has_search_latch = 0; /* RW_S_LATCH or 0 */
ulint i; ulint i;
if (search_latch_locked) {
has_search_latch = RW_S_LATCH;
}
index = plan->index; index = plan->index;
/* Calculate the value of the search tuple: the exact match columns /* Calculate the value of the search tuple: the exact match columns
@ -1325,7 +1320,7 @@ row_sel_open_pcur(
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
BTR_SEARCH_LEAF, &plan->pcur, BTR_SEARCH_LEAF, &plan->pcur,
has_search_latch, mtr); ahi_latch, mtr);
} else { } else {
/* Open the cursor to the start or the end of the index /* Open the cursor to the start or the end of the index
(FALSE: no init) */ (FALSE: no init) */
@ -1473,7 +1468,7 @@ row_sel_try_search_shortcut(
rw_lock_t* ahi_latch = btr_get_search_latch(index); rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch); rw_lock_s_lock(ahi_latch);
row_sel_open_pcur(plan, TRUE, mtr); row_sel_open_pcur(plan, ahi_latch, mtr);
const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); const rec_t* rec = btr_pcur_get_rec(&(plan->pcur));
@ -1659,8 +1654,11 @@ table_loop:
if (!plan->pcur_is_open) { if (!plan->pcur_is_open) {
/* Evaluate the expressions to build the search tuple and /* Evaluate the expressions to build the search tuple and
open the cursor */ open the cursor */
row_sel_open_pcur(plan,
row_sel_open_pcur(plan, FALSE, &mtr); #ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
&mtr);
cursor_just_opened = TRUE; cursor_just_opened = TRUE;
@ -3841,7 +3839,7 @@ row_sel_try_search_shortcut_for_mysql(
rw_lock_t* ahi_latch = btr_get_search_latch(index); rw_lock_t* ahi_latch = btr_get_search_latch(index);
rw_lock_s_lock(ahi_latch); rw_lock_s_lock(ahi_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, RW_S_LATCH, mtr); BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec) || rec_is_default_row(rec, index)) { if (!page_rec_is_user_rec(rec) || rec_is_default_row(rec, index)) {