Commit 9fac857f authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-34283 A misplaced btr_cur_need_opposite_intention() check may fail to prevent hangs

btr_cur_t::search_leaf(): Invoke btr_cur_need_opposite_intention() after
positioning page_cur.rec so that the record will be in the intended page.
This is something that was broken in
commit f2096478 or
commit de4030e4 or related changes.

btr_cur_need_opposite_intention(): Add a debug assertion that would
catch the misuse.

The "next line of defence" that should have caught this bug in debug builds
are assertions that mtr_t::m_memo contains MTR_MEMO_X_LOCK for the
dict_index_t::lock. When btr_cur_need_opposite_intention() holds,
we should escalate to acquiring an exclusive index->lock in
btr_cur_t::pessimistic_search_leaf().

Reviewed by: Debarun Banerjee
parent bc366092
...@@ -756,6 +756,7 @@ static bool btr_cur_need_opposite_intention(const buf_page_t &bpage, ...@@ -756,6 +756,7 @@ static bool btr_cur_need_opposite_intention(const buf_page_t &bpage,
ulint compress_limit, ulint compress_limit,
const rec_t *rec) const rec_t *rec)
{ {
ut_ad(bpage.frame == page_align(rec));
if (UNIV_LIKELY_NULL(bpage.zip.data) && if (UNIV_LIKELY_NULL(bpage.zip.data) &&
!page_zip_available(&bpage.zip, is_clust, node_ptr_max_size, 1)) !page_zip_available(&bpage.zip, is_clust, node_ptr_max_size, 1))
return true; return true;
...@@ -1437,11 +1438,6 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, ...@@ -1437,11 +1438,6 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
!btr_block_get(*index(), btr_page_get_next(block->page.frame), !btr_block_get(*index(), btr_page_get_next(block->page.frame),
RW_X_LATCH, false, mtr, &err)) RW_X_LATCH, false, mtr, &err))
goto func_exit; goto func_exit;
if (btr_cur_need_opposite_intention(block->page, index()->is_clust(),
lock_intention,
node_ptr_max_size, compress_limit,
page_cur.rec))
goto need_opposite_intention;
} }
reached_latched_leaf: reached_latched_leaf:
...@@ -1463,6 +1459,13 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode, ...@@ -1463,6 +1459,13 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
ut_ad(up_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE); ut_ad(up_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE);
ut_ad(low_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE); ut_ad(low_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE);
if (latch_mode == BTR_MODIFY_TREE &&
btr_cur_need_opposite_intention(block->page, index()->is_clust(),
lock_intention,
node_ptr_max_size, compress_limit,
page_cur.rec))
goto need_opposite_intention;
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
/* We do a dirty read of btr_search_enabled here. We will /* We do a dirty read of btr_search_enabled here. We will
properly check btr_search_enabled again in properly check btr_search_enabled again in
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment