summaryrefslogtreecommitdiffstats
path: root/storage/innobase/btr
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:33:02 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:33:02 +0000
commit4fa488fb0159c629483b7994aa84e73926b132b9 (patch)
tree182a19db69cdcb92be54cc6a5b0b9bfab28f80fd /storage/innobase/btr
parentAdding debian version 1:10.11.6-2. (diff)
downloadmariadb-4fa488fb0159c629483b7994aa84e73926b132b9.tar.xz
mariadb-4fa488fb0159c629483b7994aa84e73926b132b9.zip
Merging upstream version 1:10.11.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/innobase/btr')
-rw-r--r--storage/innobase/btr/btr0btr.cc36
-rw-r--r--storage/innobase/btr/btr0bulk.cc24
-rw-r--r--storage/innobase/btr/btr0cur.cc77
-rw-r--r--storage/innobase/btr/btr0pcur.cc17
-rw-r--r--storage/innobase/btr/btr0sea.cc1
5 files changed, 101 insertions, 54 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 08be1991..705ff035 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -216,10 +216,11 @@ ATTRIBUTE_COLD void btr_decryption_failed(const dict_index_t &index)
@param[in] merge whether change buffer merge should be attempted
@param[in,out] mtr mini-transaction
@param[out] err error code
+@param[out] first set if this is a first-time access to the page
@return block */
buf_block_t *btr_block_get(const dict_index_t &index,
uint32_t page, rw_lock_type_t mode, bool merge,
- mtr_t *mtr, dberr_t *err)
+ mtr_t *mtr, dberr_t *err, bool *first)
{
ut_ad(mode != RW_NO_LATCH);
dberr_t local_err;
@@ -242,6 +243,8 @@ buf_block_t *btr_block_get(const dict_index_t &index,
*err= DB_PAGE_CORRUPTED;
block= nullptr;
}
+ else if (!buf_page_make_young_if_needed(&block->page) && first)
+ *first= true;
}
else if (*err == DB_DECRYPTION_FAILED)
btr_decryption_failed(index);
@@ -302,6 +305,8 @@ btr_root_block_get(
*err= DB_CORRUPTION;
block= nullptr;
}
+ else
+ buf_page_make_young_if_needed(&block->page);
}
else if (*err == DB_DECRYPTION_FAILED)
btr_decryption_failed(*index);
@@ -553,8 +558,11 @@ btr_page_alloc_for_ibuf(
root->page.frame)),
0, RW_X_LATCH, nullptr, BUF_GET, mtr, err);
if (new_block)
+ {
+ buf_page_make_young_if_needed(&new_block->page);
*err= flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, new_block,
PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
+ }
ut_d(if (*err == DB_SUCCESS)
flst_validate(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr));
return new_block;
@@ -873,7 +881,8 @@ static rec_offs *btr_page_get_parent(rec_offs *offsets, mem_heap_t *heap,
/************************************************************//**
Returns the upper level node pointer to a page. It is assumed that mtr holds
an x-latch on the tree.
-@return rec_get_offsets() of the node pointer record */
+@return rec_get_offsets() of the node pointer record
+@retval nullptr on corruption */
static
rec_offs*
btr_page_get_father_block(
@@ -1351,6 +1360,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
if (buf_block_t *root= buf_page_get(page_id_t(space->id, index->page),
space->zip_size(), RW_SX_LATCH, &mtr))
{
+ buf_page_make_young_if_needed(&root->page);
mtr.set_named_space(space);
page_set_autoinc(root, autoinc, &mtr, reset);
}
@@ -2542,6 +2552,11 @@ btr_attach_half_pages(
offsets = btr_page_get_father_block(nullptr, heap, mtr,
&cursor);
+ if (UNIV_UNLIKELY(!offsets)) {
+ mem_heap_free(heap);
+ return DB_CORRUPTION;
+ }
+
/* Replace the address of the old child node (= page) with the
address of the new lower half */
@@ -3478,6 +3493,14 @@ btr_lift_page_up(
offsets = btr_page_get_father_block(offsets, heap,
mtr, &cursor);
}
+
+ if (UNIV_UNLIKELY(!offsets)) {
+parent_corrupted:
+ mem_heap_free(heap);
+ *err = DB_CORRUPTION;
+ return nullptr;
+ }
+
father_block = btr_cur_get_block(&cursor);
father_page_zip = buf_block_get_page_zip(father_block);
@@ -3502,6 +3525,10 @@ btr_lift_page_up(
&cursor);
}
+ if (UNIV_UNLIKELY(!offsets)) {
+ goto parent_corrupted;
+ }
+
blocks[n_blocks++] = b = btr_cur_get_block(&cursor);
}
@@ -3717,6 +3744,11 @@ btr_compress(
NULL, heap, mtr, &father_cursor);
}
+ if (UNIV_UNLIKELY(!offsets)) {
+ err = DB_CORRUPTION;
+ goto func_exit;
+ }
+
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) {
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 013cd131..5bf68c58 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -52,6 +52,7 @@ PageBulk::init()
if (m_page_no == FIL_NULL) {
mtr_t alloc_mtr;
+ dberr_t err= DB_SUCCESS;
/* We commit redo log for allocation by a separate mtr,
because we don't guarantee pages are committed following
@@ -60,28 +61,15 @@ PageBulk::init()
alloc_mtr.start();
m_index->set_modified(alloc_mtr);
- uint32_t n_reserved;
- dberr_t err = fsp_reserve_free_extents(
- &n_reserved, m_index->table->space, 1, FSP_NORMAL,
- &alloc_mtr);
- if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
-oom:
- alloc_mtr.commit();
- m_mtr.commit();
- return err;
- }
-
/* Allocate a new page. */
new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level,
&alloc_mtr, &m_mtr, &err);
+ alloc_mtr.commit();
if (!new_block) {
- goto oom;
+ m_mtr.commit();
+ return err;
}
- m_index->table->space->release_free_extents(n_reserved);
-
- alloc_mtr.commit();
-
new_page = buf_block_get_frame(new_block);
m_page_no = new_block->page.id().page_no();
@@ -969,10 +957,10 @@ BtrBulk::pageCommit(
/** Log free check */
inline void BtrBulk::logFreeCheck()
{
- if (log_sys.check_flush_or_checkpoint()) {
+ if (log_sys.check_for_checkpoint()) {
release();
- log_check_margins();
+ log_free_check();
latch();
}
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index e736f338..46afb73b 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -1156,6 +1156,19 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
mtr_s_lock_index(index(), mtr);
}
+ dberr_t err;
+
+ if (!index()->table->space)
+ {
+ corrupted:
+ ut_ad("corrupted" == 0); // FIXME: remove this
+ err= DB_CORRUPTION;
+ func_exit:
+ if (UNIV_LIKELY_NULL(heap))
+ mem_heap_free(heap);
+ return err;
+ }
+
const ulint zip_size= index()->table->space->zip_size();
/* Start with the root page. */
@@ -1169,7 +1182,6 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
low_bytes= 0;
ulint buf_mode= BUF_GET;
search_loop:
- dberr_t err;
auto block_savepoint= mtr->get_savepoint();
buf_block_t *block=
buf_page_get_gen(page_id, zip_size, rw_latch, guess, buf_mode, mtr,
@@ -1181,10 +1193,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
btr_decryption_failed(*index());
/* fall through */
default:
- func_exit:
- if (UNIV_LIKELY_NULL(heap))
- mem_heap_free(heap);
- return err;
+ goto func_exit;
case DB_SUCCESS:
/* This must be a search to perform an insert, delete mark, or delete;
try using the change buffer */
@@ -1251,16 +1260,11 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
btr_page_get_index_id(block->page.frame) != index()->id ||
fil_page_get_type(block->page.frame) == FIL_PAGE_RTREE ||
!fil_page_index_page_check(block->page.frame))
- {
- corrupted:
- ut_ad("corrupted" == 0); // FIXME: remove this
- err= DB_CORRUPTION;
- goto func_exit;
- }
+ goto corrupted;
page_cur.block= block;
ut_ad(block == mtr->at_savepoint(block_savepoint));
- ut_ad(rw_latch != RW_NO_LATCH);
+ const bool not_first_access{buf_page_make_young_if_needed(&block->page)};
#ifdef UNIV_ZIP_DEBUG
if (const page_zip_des_t *page_zip= buf_block_get_page_zip(block))
ut_a(page_zip_validate(page_zip, block->page.frame, index()));
@@ -1539,6 +1543,9 @@ release_tree:
case BTR_SEARCH_PREV: /* btr_pcur_move_to_prev() */
ut_ad(rw_latch == RW_S_LATCH || rw_latch == RW_X_LATCH);
+ if (!not_first_access)
+ buf_read_ahead_linear(page_id, zip_size, false);
+
if (page_has_prev(block->page.frame) &&
page_rec_is_first(page_cur.rec, block->page.frame))
{
@@ -1578,6 +1585,8 @@ release_tree:
buf_mode= btr_op == BTR_DELETE_OP
? BUF_GET_IF_IN_POOL_OR_WATCH
: BUF_GET_IF_IN_POOL;
+ else if (!not_first_access)
+ buf_read_ahead_linear(page_id, zip_size, false);
break;
case BTR_MODIFY_TREE:
ut_ad(rw_latch == RW_X_LATCH);
@@ -1611,6 +1620,14 @@ ATTRIBUTE_COLD void mtr_t::index_lock_upgrade()
slot.type= MTR_MEMO_X_LOCK;
}
+/** Mark a non-leaf page "least recently used", but avoid invoking
+buf_page_t::set_accessed(), because we do not want linear read-ahead */
+static void btr_cur_nonleaf_make_young(buf_page_t *bpage)
+{
+ if (UNIV_UNLIKELY(buf_page_peek_if_too_old(bpage)))
+ buf_page_make_young(bpage);
+}
+
ATTRIBUTE_COLD
dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
page_cur_mode_t mode, mtr_t *mtr)
@@ -1713,6 +1730,8 @@ dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
if (height != btr_page_get_level(block->page.frame))
goto corrupted;
+ btr_cur_nonleaf_make_young(&block->page);
+
#ifdef UNIV_ZIP_DEBUG
const page_zip_des_t *page_zip= buf_block_get_page_zip(block);
ut_a(!page_zip || page_zip_validate(page_zip, block->page.frame, index()));
@@ -1799,6 +1818,8 @@ search_loop:
btr_decryption_failed(*index);
goto func_exit;
}
+ else
+ btr_cur_nonleaf_make_young(&block->page);
#ifdef UNIV_ZIP_DEBUG
if (const page_zip_des_t *page_zip= buf_block_get_page_zip(block))
@@ -1934,18 +1955,15 @@ index_locked:
ut_ad(n_blocks < BTR_MAX_LEVELS);
ut_ad(savepoint + n_blocks == mtr->get_savepoint());
+ bool first_access= false;
buf_block_t* block=
btr_block_get(*index, page,
height ? upper_rw_latch : root_leaf_rw_latch,
- !height, mtr, &err);
+ !height, mtr, &err, &first_access);
ut_ad(!block == (err != DB_SUCCESS));
if (!block)
- {
- if (err == DB_DECRYPTION_FAILED)
- btr_decryption_failed(*index);
break;
- }
if (first)
page_cur_set_before_first(block, &page_cur);
@@ -2029,10 +2047,16 @@ index_locked:
offsets= rec_get_offsets(page_cur.rec, index, offsets, 0, ULINT_UNDEFINED,
&heap);
+ page= btr_node_ptr_get_child_page_no(page_cur.rec, offsets);
ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH);
- if (latch_mode != BTR_MODIFY_TREE);
+ if (latch_mode != BTR_MODIFY_TREE)
+ {
+ if (!height && first && first_access)
+ buf_read_ahead_linear(page_id_t(block->page.id().space(), page),
+ block->page.zip_size(), false);
+ }
else if (btr_cur_need_opposite_intention(block->page, index->is_clust(),
lock_intention,
node_ptr_max_size, compress_limit,
@@ -2070,7 +2094,6 @@ index_locked:
}
/* Go to the child node */
- page= btr_node_ptr_get_child_page_no(page_cur.rec, offsets);
n_blocks++;
}
@@ -3837,22 +3860,14 @@ btr_cur_pess_upd_restore_supremum(
const page_id_t block_id{block->page.id()};
const page_id_t prev_id(block_id.space(), prev_page_no);
- dberr_t err;
buf_block_t* prev_block
- = buf_page_get_gen(prev_id, 0, RW_NO_LATCH, nullptr,
- BUF_PEEK_IF_IN_POOL, mtr, &err);
- /* Since we already held an x-latch on prev_block, it must
- be available and not be corrupted unless the buffer pool got
- corrupted somehow. */
+ = mtr->get_already_latched(prev_id, MTR_MEMO_PAGE_X_FIX);
if (UNIV_UNLIKELY(!prev_block)) {
- return err;
+ return DB_CORRUPTION;
}
ut_ad(!memcmp_aligned<4>(prev_block->page.frame + FIL_PAGE_NEXT,
block->page.frame + FIL_PAGE_OFFSET, 4));
- /* We must already have an x-latch on prev_block! */
- ut_ad(mtr->memo_contains_flagged(prev_block, MTR_MEMO_PAGE_X_FIX));
-
lock_rec_reset_and_inherit_gap_locks(*prev_block, block_id,
PAGE_HEAP_NO_SUPREMUM,
page_rec_get_heap_no(rec));
@@ -6660,6 +6675,10 @@ btr_copy_blob_prefix(
mtr.commit();
return copied_len;
}
+ if (!buf_page_make_young_if_needed(&block->page)) {
+ buf_read_ahead_linear(id, 0, false);
+ }
+
page = buf_block_get_frame(block);
blob_header = page + offset;
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 54dd15ac..2131fb94 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -25,9 +25,10 @@ Created 2/23/1996 Heikki Tuuri
*******************************************************/
#include "btr0pcur.h"
-#include "ut0byte.h"
+#include "buf0rea.h"
#include "rem0cmp.h"
#include "trx0trx.h"
+#include "ibuf0ibuf.h"
/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
@@ -261,13 +262,15 @@ static bool btr_pcur_optimistic_latch_leaves(buf_block_t *block,
buf_page_get_gen(page_id_t(id.space(), left_page_no), zip_size,
mode, nullptr, BUF_GET_POSSIBLY_FREED, mtr);
- if (left_block &&
- btr_page_get_next(left_block->page.frame) != id.page_no())
+ if (!left_block);
+ else if (btr_page_get_next(left_block->page.frame) != id.page_no())
{
release_left_block:
mtr->release_last_page();
return false;
}
+ else
+ buf_page_make_young_if_needed(&left_block->page);
}
if (buf_page_optimistic_get(mode, block, pcur->modify_clock, mtr))
@@ -539,10 +542,11 @@ btr_pcur_move_to_next_page(
}
dberr_t err;
+ bool first_access = false;
buf_block_t* next_block = btr_block_get(
*cursor->index(), next_page_no,
rw_lock_type_t(cursor->latch_mode & (RW_X_LATCH | RW_S_LATCH)),
- page_is_leaf(page), mtr, &err);
+ page_is_leaf(page), mtr, &err, &first_access);
if (UNIV_UNLIKELY(!next_block)) {
return err;
@@ -561,6 +565,11 @@ btr_pcur_move_to_next_page(
const auto s = mtr->get_savepoint();
mtr->rollback_to_savepoint(s - 2, s - 1);
+ if (first_access) {
+ buf_read_ahead_linear(next_block->page.id(),
+ next_block->zip_size(),
+ ibuf_inside(mtr));
+ }
return DB_SUCCESS;
}
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 8435047c..1c5928c4 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -1143,7 +1143,6 @@ block_and_ahi_release_and_fail:
}
block->page.fix();
- block->page.set_accessed();
buf_page_make_young_if_needed(&block->page);
static_assert(ulint{MTR_MEMO_PAGE_S_FIX} == ulint{BTR_SEARCH_LEAF},
"");