Skip to content

Commit 687fd6b

Browse files
committed
MDEV-30648 btr_estimate_n_rows_in_range() accesses unfixed, unlatched page
The issue is caused by MDEV-30400 fix. There are two cursors in btr_estimate_n_rows_in_range() - p1 and p2, but both share the same mtr. Each cursor contains mtr savepoint for the previously fetched block to release it then the current block is fetched. Before MDEV-30400 the block was released with mtr_t::release_block_at_savepoint(), it just unfixed a block and released its page patch. In MDEV-30400 it was replaced with mtr_t::rollback_to_savepoint(), which does the same as the former mtr_t::release_block_at_savepoint(ulint begin, ulint end) but also erases the corresponding slots from mtr memo, what invalidates any stored mtr's memo savepoints, greater or equal to "begin". The idea of the fix is to get rid of savepoints at all in btr_estimate_n_rows_in_range() and btr_estimate_n_rows_in_range_on_level(). As mtr_t::rollback_to_savepoint() erases elements from mtr_t::m_memo, we know what element of mtr_t::m_memo can be deleted on the certain case, so there is no need to store savepoints. See also the following slides for details: https://docs.google.com/presentation/d/1RFYBo7EUhM22ab3GOYctv3j_3yC0vHtBY9auObZec8U Reviewed by: Marko Mäkelä
1 parent 694ce0d commit 687fd6b

File tree

1 file changed

+22
-26
lines changed

1 file changed

+22
-26
lines changed

storage/innobase/btr/btr0cur.cc

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4990,8 +4990,6 @@ class btr_est_cur_t
49904990
page_id_t m_page_id;
49914991
/** Current block */
49924992
buf_block_t *m_block;
4993-
/** mtr savepoint of the current block */
4994-
ulint m_savepoint;
49954993
/** Page search mode, can differ from m_mode for non-leaf pages, see c-tor
49964994
comments for details */
49974995
page_cur_mode_t m_page_mode;
@@ -5050,17 +5048,17 @@ class btr_est_cur_t
50505048
bool fetch_child(ulint level, mtr_t &mtr, const buf_block_t *right_parent)
50515049
{
50525050
buf_block_t *parent_block= m_block;
5053-
ulint parent_savepoint= m_savepoint;
50545051

50555052
m_block= btr_block_get(*index(), m_page_id.page_no(), RW_S_LATCH, !level,
50565053
&mtr, nullptr);
50575054
if (!m_block)
50585055
return false;
50595056

50605057
if (parent_block && parent_block != right_parent)
5061-
mtr.rollback_to_savepoint(parent_savepoint, parent_savepoint + 1);
5062-
5063-
m_savepoint= mtr.get_savepoint() - 1;
5058+
{
5059+
ut_ad(mtr.get_savepoint() >= 2);
5060+
mtr.rollback_to_savepoint(1, 2);
5061+
}
50645062

50655063
return level == ULINT_UNDEFINED ||
50665064
btr_page_get_level(m_block->page.frame) == level;
@@ -5122,10 +5120,10 @@ class btr_est_cur_t
51225120
return true;
51235121
}
51245122

5125-
/** Gets page id of the current record child.
5123+
/** Read page id of the current record child.
51265124
@param offsets offsets array.
51275125
@param heap heap for offsets array */
5128-
void get_child(rec_offs **offsets, mem_heap_t **heap)
5126+
void read_child_page_id(rec_offs **offsets, mem_heap_t **heap)
51295127
{
51305128
const rec_t *node_ptr= page_cur_get_rec(&m_page_cur);
51315129

@@ -5195,11 +5193,7 @@ class btr_est_cur_t
51955193
/** Copies block pointer and savepoint from another btr_est_cur_t in the case
51965194
if both left and right border cursors point to the same block.
51975195
@param o reference to the other btr_est_cur_t object. */
5198-
void set_block(const btr_est_cur_t &o)
5199-
{
5200-
m_block= o.m_block;
5201-
m_savepoint= o.m_savepoint;
5202-
}
5196+
void set_block(const btr_est_cur_t &o) { m_block= o.m_block; }
52035197

52045198
/** @return current record number. */
52055199
ulint nth_rec() const { return m_nth_rec; }
@@ -5238,7 +5232,6 @@ static ha_rows btr_estimate_n_rows_in_range_on_level(
52385232
pages before reaching right_page_no, then we estimate the average from the
52395233
pages scanned so far. */
52405234
static constexpr uint n_pages_read_limit= 9;
5241-
ulint savepoint= 0;
52425235
buf_block_t *block= nullptr;
52435236
const dict_index_t *index= left_cur.index();
52445237

@@ -5268,19 +5261,18 @@ static ha_rows btr_estimate_n_rows_in_range_on_level(
52685261
{
52695262
page_t *page;
52705263
buf_block_t *prev_block= block;
5271-
ulint prev_savepoint= savepoint;
5272-
5273-
savepoint= mtr.get_savepoint();
52745264

52755265
/* Fetch the page. */
52765266
block= btr_block_get(*index, page_id.page_no(), RW_S_LATCH, !level, &mtr,
52775267
nullptr);
52785268

52795269
if (prev_block)
52805270
{
5281-
mtr.rollback_to_savepoint(prev_savepoint, prev_savepoint + 1);
5282-
if (block)
5283-
savepoint--;
5271+
ulint savepoint = mtr.get_savepoint();
5272+
/* Index s-lock, p1, p2 latches, can also be p1 and p2 parent latch if
5273+
they are not diverged */
5274+
ut_ad(savepoint >= 3);
5275+
mtr.rollback_to_savepoint(savepoint - 2, savepoint - 1);
52845276
}
52855277

52865278
if (!block || btr_page_get_level(buf_block_get_frame(block)) != level)
@@ -5311,8 +5303,8 @@ static ha_rows btr_estimate_n_rows_in_range_on_level(
53115303

53125304
if (block)
53135305
{
5314-
ut_ad(block == mtr.at_savepoint(savepoint));
5315-
mtr.rollback_to_savepoint(savepoint, savepoint + 1);
5306+
ut_ad(block == mtr.at_savepoint(mtr.get_savepoint() - 1));
5307+
mtr.rollback_to_savepoint(mtr.get_savepoint() - 1);
53165308
}
53175309

53185310
return (n_rows);
@@ -5321,8 +5313,8 @@ static ha_rows btr_estimate_n_rows_in_range_on_level(
53215313

53225314
if (block)
53235315
{
5324-
ut_ad(block == mtr.at_savepoint(savepoint));
5325-
mtr.rollback_to_savepoint(savepoint, savepoint + 1);
5316+
ut_ad(block == mtr.at_savepoint(mtr.get_savepoint() - 1));
5317+
mtr.rollback_to_savepoint(mtr.get_savepoint() - 1);
53265318
}
53275319

53285320
is_n_rows_exact= false;
@@ -5516,8 +5508,12 @@ ha_rows btr_estimate_n_rows_in_range(dict_index_t *index,
55165508
{
55175509
ut_ad(height > 0);
55185510
height--;
5519-
p1.get_child(&offsets, &heap);
5520-
p2.get_child(&offsets, &heap);
5511+
ut_ad(mtr.memo_contains(p1.index()->lock, MTR_MEMO_S_LOCK));
5512+
ut_ad(mtr.memo_contains_flagged(p1.block(), MTR_MEMO_PAGE_S_FIX));
5513+
p1.read_child_page_id(&offsets, &heap);
5514+
ut_ad(mtr.memo_contains(p2.index()->lock, MTR_MEMO_S_LOCK));
5515+
ut_ad(mtr.memo_contains_flagged(p2.block(), MTR_MEMO_PAGE_S_FIX));
5516+
p2.read_child_page_id(&offsets, &heap);
55215517
goto search_loop;
55225518
}
55235519

0 commit comments

Comments
 (0)