summaryrefslogtreecommitdiff
path: root/storage/innobase/ibuf/ibuf0ibuf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/ibuf/ibuf0ibuf.cc')
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc707
1 files changed, 349 insertions, 358 deletions
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 6b006625bcc..b646f703142 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -325,23 +325,18 @@ ibuf_header_page_get(
/** Acquire the change buffer root page.
@param[in,out] mtr mini-transaction
@return change buffer root page, SX-latched */
-static buf_block_t *ibuf_tree_root_get(mtr_t *mtr)
+static buf_block_t *ibuf_tree_root_get(mtr_t *mtr, dberr_t *err= nullptr)
{
- buf_block_t* block;
-
- ut_ad(ibuf_inside(mtr));
- mysql_mutex_assert_owner(&ibuf_mutex);
+ ut_ad(ibuf_inside(mtr));
+ mysql_mutex_assert_owner(&ibuf_mutex);
- mtr_sx_lock_index(ibuf.index, mtr);
+ mtr_sx_lock_index(ibuf.index, mtr);
- /* only segment list access is exclusive each other */
- block = buf_page_get(
- page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- 0, RW_SX_LATCH, mtr);
-
- ut_ad(ibuf.empty == page_is_empty(block->page.frame));
-
- return block;
+ buf_block_t *block=
+ buf_page_get_gen(page_id_t{IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO},
+ 0, RW_SX_LATCH, nullptr, BUF_GET, mtr, err);
+ ut_ad(!block || ibuf.empty == page_is_empty(block->page.frame));
+ return block;
}
/******************************************************************//**
@@ -393,7 +388,6 @@ ibuf_init_at_db_start(void)
/*=======================*/
{
page_t* root;
- ulint n_used;
ut_ad(!ibuf.index);
mtr_t mtr;
@@ -401,13 +395,15 @@ ibuf_init_at_db_start(void)
compile_time_assert(IBUF_SPACE_ID == TRX_SYS_SPACE);
compile_time_assert(IBUF_SPACE_ID == 0);
mtr.x_lock_space(fil_system.sys_space);
- buf_block_t* header_page = buf_page_get(
+ dberr_t err;
+ buf_block_t* header_page = buf_page_get_gen(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
- 0, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, nullptr, BUF_GET, &mtr, &err);
if (!header_page) {
+err_exit:
mtr.commit();
- return DB_DECRYPTION_FAILED;
+ return err;
}
/* At startup we intialize ibuf to have a maximum of
@@ -426,20 +422,20 @@ ibuf_init_at_db_start(void)
fseg_n_reserved_pages(*header_page,
IBUF_HEADER + IBUF_TREE_SEG_HEADER
- + header_page->page.frame, &n_used, &mtr);
-
- ut_ad(n_used >= 2);
-
- ibuf.seg_size = n_used;
-
- {
- buf_block_t* block;
-
- block = buf_page_get(
- page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- 0, RW_X_LATCH, &mtr);
+ + header_page->page.frame, &ibuf.seg_size, &mtr);
+ do {
+ DBUG_EXECUTE_IF("intermittent_read_failure", continue;);
+ ut_ad(ibuf.seg_size >= 2);
+ } while (0);
+
+ if (buf_block_t* block =
+ buf_page_get_gen(page_id_t(IBUF_SPACE_ID,
+ FSP_IBUF_TREE_ROOT_PAGE_NO),
+ 0, RW_X_LATCH, nullptr, BUF_GET, &mtr, &err)) {
root = buf_block_get_frame(block);
+ } else {
+ goto err_exit;
}
ibuf_size_update(root);
@@ -662,9 +658,9 @@ ibuf_bitmap_get_map_page(
ulint zip_size,
mtr_t* mtr)
{
- return buf_page_get_gen(
- ibuf_bitmap_page_no_calc(page_id, zip_size),
- zip_size, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, mtr);
+ return buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, zip_size),
+ zip_size, RW_X_LATCH, nullptr,
+ BUF_GET_POSSIBLY_FREED, mtr);
}
/************************************************************************//**
@@ -717,42 +713,36 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */
ulint val) /*!< in: value to set: < 4 */
{
- if (!page_is_leaf(block->page.frame)) {
- return;
- }
-
- mtr_t mtr;
- mtr.start();
- const page_id_t id(block->page.id());
-
- const fil_space_t* space = mtr.set_named_space_id(id.space());
+ if (!page_is_leaf(block->page.frame))
+ return;
- buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(id,
- block->zip_size(),
- &mtr);
+ mtr_t mtr;
+ mtr.start();
+ const page_id_t id(block->page.id());
+ const fil_space_t *space= mtr.set_named_space_id(id.space());
- if (space->purpose != FIL_TYPE_TABLESPACE) {
- mtr.set_log_mode(MTR_LOG_NO_REDO);
- }
+ if (buf_block_t *bitmap_page=
+ ibuf_bitmap_get_map_page(id, block->zip_size(), &mtr))
+ {
+ if (space->purpose != FIL_TYPE_TABLESPACE)
+ mtr.set_log_mode(MTR_LOG_NO_REDO);
#ifdef UNIV_IBUF_DEBUG
- if (max_val != ULINT_UNDEFINED) {
- ulint old_val;
-
- old_val = ibuf_bitmap_page_get_bits(
- bitmap_page, id,
- IBUF_BITMAP_FREE, &mtr);
- ut_a(old_val <= max_val);
- }
-
- ut_a(val <= ibuf_index_page_calc_free(block));
+ if (max_val != ULINT_UNDEFINED)
+ {
+ ulint old_val= ibuf_bitmap_page_get_bits(bitmap_page, id,
+ IBUF_BITMAP_FREE, &mtr);
+ ut_a(old_val <= max_val);
+ }
+
+ ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */
- ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
- bitmap_page, id, block->physical_size(),
- val, &mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>
+ (bitmap_page, id, block->physical_size(), val, &mtr);
+ }
- mtr.commit();
+ mtr.commit();
}
/************************************************************************//**
@@ -934,14 +924,12 @@ ibuf_page_low(
not be modified by any other thread. Nobody should be
calling ibuf_add_free_page() or ibuf_remove_free_page()
while the page is linked to the insert buffer b-tree. */
- dberr_t err = DB_SUCCESS;
-
buf_block_t* block = buf_page_get_gen(
ibuf_bitmap_page_no_calc(page_id, zip_size),
- zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
- &local_mtr, &err);
+ zip_size, RW_NO_LATCH, nullptr, BUF_GET, &local_mtr);
- ret = ibuf_bitmap_page_get_bits_low(
+ ret = block
+ && ibuf_bitmap_page_get_bits_low(
block->page.frame, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
@@ -955,11 +943,12 @@ ibuf_page_low(
mtr_start(mtr);
}
- ret = ibuf_bitmap_page_get_bits(ibuf_bitmap_get_map_page(
- page_id, zip_size,
- mtr)->page.frame,
- page_id, zip_size,
- IBUF_BITMAP_IBUF, mtr);
+ buf_block_t *block = ibuf_bitmap_get_map_page(page_id, zip_size,
+ mtr);
+ ret = block
+ && ibuf_bitmap_page_get_bits(block->page.frame,
+ page_id, zip_size,
+ IBUF_BITMAP_IBUF, mtr);
if (mtr == &local_mtr) {
mtr_commit(mtr);
@@ -1781,6 +1770,10 @@ static bool ibuf_add_free_page()
order */
mtr.x_lock_space(fil_system.sys_space);
header_page = ibuf_header_page_get(&mtr);
+ if (!header_page) {
+ mtr.commit();
+ return false;
+ }
/* Allocate a new page: NOTE that if the page has been a part of a
non-clustered index which has subsequently been dropped, then the
@@ -1792,11 +1785,12 @@ static bool ibuf_add_free_page()
of a deadlock. This is the reason why we created a special ibuf
header page apart from the ibuf tree. */
- block = fseg_alloc_free_page(
+ dberr_t err;
+ block = fseg_alloc_free_page_general(
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
- &mtr);
+ false, &mtr, &mtr, &err);
- if (block == NULL) {
+ if (!block) {
mtr.commit();
return false;
}
@@ -1807,15 +1801,24 @@ static bool ibuf_add_free_page()
mtr.write<2>(*block, block->page.frame + FIL_PAGE_TYPE,
FIL_PAGE_IBUF_FREE_LIST);
+ buf_block_t* ibuf_root = ibuf_tree_root_get(&mtr);
+ if (UNIV_UNLIKELY(!ibuf_root)) {
+corrupted:
+ /* Do not bother to try to free the allocated block, because
+ the change buffer is seriously corrupted already. */
+ mysql_mutex_unlock(&ibuf_mutex);
+ ibuf_mtr_commit(&mtr);
+ return false;
+ }
/* Add the page to the free list and update the ibuf size data */
- flst_add_last(ibuf_tree_root_get(&mtr),
- PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
-
- ibuf.seg_size++;
- ibuf.free_list_len++;
+ err = flst_add_last(ibuf_root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
+ &mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ goto corrupted;
+ }
/* Set the bit indicating that this page is now an ibuf tree page
(level 2 page) */
@@ -1823,23 +1826,24 @@ static bool ibuf_add_free_page()
const page_id_t page_id(block->page.id());
buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
+ if (UNIV_UNLIKELY(!bitmap_page)) {
+ goto corrupted;
+ }
+
+ ibuf.seg_size++;
+ ibuf.free_list_len++;
+
mysql_mutex_unlock(&ibuf_mutex);
ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(bitmap_page, page_id,
- srv_page_size, true,
- &mtr);
-
+ srv_page_size, true, &mtr);
ibuf_mtr_commit(&mtr);
-
return true;
}
/*********************************************************************//**
Removes a page from the free list and frees it to the fsp system. */
-static
-void
-ibuf_remove_free_page(void)
-/*=======================*/
+static void ibuf_remove_free_page()
{
mtr_t mtr;
mtr_t mtr2;
@@ -1859,8 +1863,8 @@ ibuf_remove_free_page(void)
mysql_mutex_lock(&ibuf_pessimistic_insert_mutex);
mysql_mutex_lock(&ibuf_mutex);
- if (!ibuf_data_too_much_free()) {
-
+ if (!header_page || !ibuf_data_too_much_free()) {
+early_exit:
mysql_mutex_unlock(&ibuf_mutex);
mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
@@ -1873,10 +1877,16 @@ ibuf_remove_free_page(void)
buf_block_t* root = ibuf_tree_root_get(&mtr2);
+ if (UNIV_UNLIKELY(!root)) {
+ ibuf_mtr_commit(&mtr2);
+ goto early_exit;
+ }
+
mysql_mutex_unlock(&ibuf_mutex);
- uint32_t page_no = flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
- + root->page.frame).page;
+ const uint32_t page_no = flst_get_last(PAGE_HEADER
+ + PAGE_BTR_IBUF_FREE_LIST
+ + root->page.frame).page;
/* NOTE that we must release the latch on the ibuf tree root
because in fseg_free_page we access level 1 pages, and the root
@@ -1892,43 +1902,60 @@ ibuf_remove_free_page(void)
page from it. */
compile_time_assert(IBUF_SPACE_ID == 0);
- fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
- fil_system.sys_space, page_no, &mtr);
+ const page_id_t page_id{IBUF_SPACE_ID, page_no};
+ buf_block_t* bitmap_page = nullptr;
+ dberr_t err = fseg_free_page(
+ header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
+ fil_system.sys_space, page_no, &mtr);
- const page_id_t page_id(IBUF_SPACE_ID, page_no);
+ if (err != DB_SUCCESS) {
+ goto func_exit;
+ }
ibuf_enter(&mtr);
mysql_mutex_lock(&ibuf_mutex);
- root = ibuf_tree_root_get(&mtr);
+ root = ibuf_tree_root_get(&mtr, &err);
+ if (UNIV_UNLIKELY(!root)) {
+ mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
+ goto func_exit;
+ }
ut_ad(page_no == flst_get_last(PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST
+ root->page.frame).page);
- buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
-
/* Remove the page from the free list and update the ibuf size data */
-
- flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
+ if (buf_block_t* block =
+ buf_page_get_gen(page_id, 0, RW_X_LATCH, nullptr, BUF_GET,
+ &mtr, &err)) {
+ err = flst_remove(root, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ block,
+ PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
+ &mtr);
+ }
mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
- ibuf.seg_size--;
- ibuf.free_list_len--;
-
- /* Set the bit indicating that this page is no more an ibuf tree page
- (level 2 page) */
-
- buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
+ if (err == DB_SUCCESS) {
+ ibuf.seg_size--;
+ ibuf.free_list_len--;
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
+ }
+func_exit:
mysql_mutex_unlock(&ibuf_mutex);
- ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(
- bitmap_page, page_id, srv_page_size, false, &mtr);
+ if (bitmap_page) {
+ /* Set the bit indicating that this page is no more an
+ ibuf tree page (level 2 page) */
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_IBUF>(
+ bitmap_page, page_id, srv_page_size, false, &mtr);
+ }
- buf_page_free(fil_system.sys_space, page_no, &mtr);
+ if (err == DB_SUCCESS) {
+ buf_page_free(fil_system.sys_space, page_no, &mtr);
+ }
ibuf_mtr_commit(&mtr);
}
@@ -2264,13 +2291,17 @@ tablespace_deleted:
if (UNIV_LIKELY(page_nos[i] < size)) {
mtr.start();
dberr_t err;
+ buf_block_t *b =
buf_page_get_gen(page_id_t(space_id, page_nos[i]),
zip_size, RW_X_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED,
&mtr, &err, true);
mtr.commit();
- if (err == DB_TABLESPACE_DELETED) {
+ if (b) {
+ } else if (err == DB_TABLESPACE_DELETED) {
goto tablespace_deleted;
+ } else {
+ continue;
}
}
#ifndef DBUG_OFF
@@ -2303,8 +2334,11 @@ work_around:
loop:
btr_pcur_t pcur;
ibuf_mtr_start(&mtr);
- btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
- &pcur, &mtr);
+ if (btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF, &pcur, &mtr)
+ != DB_SUCCESS) {
+ goto done;
+ }
if (!btr_pcur_is_on_user_rec(&pcur)) {
ut_ad(btr_pcur_is_after_last_on_page(&pcur));
goto done;
@@ -2371,12 +2405,18 @@ ibuf_merge_pages(
/* Open a cursor to a randomly chosen leaf of the tree, at a random
position within the leaf */
- bool available;
+ pcur.pos_state = BTR_PCUR_IS_POSITIONED;
+ pcur.old_stored = false;
+ pcur.trx_if_known = NULL;
+ pcur.search_mode = PAGE_CUR_G;
+ pcur.latch_mode = BTR_SEARCH_LEAF;
- available = btr_pcur_open_at_rnd_pos(ibuf.index, BTR_SEARCH_LEAF,
- &pcur, &mtr);
- /* No one should make this index unavailable when server is running */
- ut_a(available);
+ btr_pcur_init(&pcur);
+
+ if (!btr_cur_open_at_rnd_pos(ibuf.index, BTR_SEARCH_LEAF,
+ btr_pcur_get_btr_cur(&pcur), &mtr)) {
+ return 0;
+ }
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf.index));
@@ -2425,19 +2465,19 @@ ibuf_merge_space(
/* Position the cursor on the first matching record. */
- btr_pcur_open(
- ibuf.index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur,
- &mtr);
+ dberr_t err = btr_pcur_open(ibuf.index, tuple, PAGE_CUR_GE,
+ BTR_SEARCH_LEAF, &pcur, &mtr);
+ ut_ad(err != DB_SUCCESS || page_validate(btr_pcur_get_page(&pcur),
+ ibuf.index));
mem_heap_free(heap);
- ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf.index));
-
ulint sum_sizes = 0;
uint32_t pages[IBUF_MAX_N_PAGES_MERGED];
uint32_t spaces[IBUF_MAX_N_PAGES_MERGED];
- if (page_is_empty(btr_pcur_get_page(&pcur))) {
+ if (err != DB_SUCCESS) {
+ } else if (page_is_empty(btr_pcur_get_page(&pcur))) {
/* If a B-tree page is empty, it must be the root page
and the whole B-tree must be empty. InnoDB does not
allow empty B-tree pages other than the root. */
@@ -2800,23 +2840,22 @@ ibuf_get_volume_buffered(
goto count_later;
}
- {
- buf_block_t* block;
-
- block = buf_page_get(
- page_id_t(IBUF_SPACE_ID, prev_page_no),
- 0, RW_X_LATCH, mtr);
-
+ if (buf_block_t* block =
+ buf_page_get(page_id_t(IBUF_SPACE_ID, prev_page_no),
+ 0, RW_X_LATCH, mtr)) {
prev_page = buf_block_get_frame(block);
ut_ad(page_validate(prev_page, ibuf.index));
+ } else {
+ return srv_page_size;
}
-#ifdef UNIV_BTR_DEBUG
static_assert(FIL_PAGE_NEXT % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(prev_page + FIL_PAGE_NEXT,
- page + FIL_PAGE_OFFSET, 4));
-#endif /* UNIV_BTR_DEBUG */
+
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(prev_page + FIL_PAGE_NEXT,
+ page + FIL_PAGE_OFFSET, 4))) {
+ return 0;
+ }
rec = page_get_supremum_rec(prev_page);
rec = page_rec_get_prev_const(rec);
@@ -2873,23 +2912,22 @@ count_later:
return(volume);
}
- {
- buf_block_t* block;
-
- block = buf_page_get(
- page_id_t(IBUF_SPACE_ID, next_page_no),
- 0, RW_X_LATCH, mtr);
-
+ if (buf_block_t* block =
+ buf_page_get(page_id_t(IBUF_SPACE_ID, next_page_no),
+ 0, RW_X_LATCH, mtr)) {
next_page = buf_block_get_frame(block);
ut_ad(page_validate(next_page, ibuf.index));
+ } else {
+ return srv_page_size;
}
-#ifdef UNIV_BTR_DEBUG
static_assert(FIL_PAGE_PREV % 4 == 0, "alignment");
static_assert(FIL_PAGE_OFFSET % 4 == 0, "alignment");
- ut_a(!memcmp_aligned<4>(next_page + FIL_PAGE_PREV,
- page + FIL_PAGE_OFFSET, 4));
-#endif /* UNIV_BTR_DEBUG */
+
+ if (UNIV_UNLIKELY(memcmp_aligned<4>(next_page + FIL_PAGE_PREV,
+ page + FIL_PAGE_OFFSET, 4))) {
+ return 0;
+ }
rec = page_get_infimum_rec(next_page);
rec = page_rec_get_next_const(rec);
@@ -2923,7 +2961,6 @@ void
ibuf_update_max_tablespace_id(void)
/*===============================*/
{
- uint32_t max_space_id;
const rec_t* rec;
const byte* field;
ulint len;
@@ -2934,26 +2971,27 @@ ibuf_update_max_tablespace_id(void)
ibuf_mtr_start(&mtr);
- btr_pcur_open_at_index_side(
- false, ibuf.index, BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
+ if (btr_pcur_open_at_index_side(false, ibuf.index, BTR_SEARCH_LEAF,
+ &pcur, true, 0, &mtr) != DB_SUCCESS) {
+func_exit:
+ ibuf_mtr_commit(&mtr);
+ return;
+ }
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf.index));
- btr_pcur_move_to_prev(&pcur, &mtr);
-
- if (btr_pcur_is_before_first_on_page(&pcur)) {
- /* The tree is empty */
+ if (!btr_pcur_move_to_prev(&pcur, &mtr)
+ || btr_pcur_is_before_first_on_page(&pcur)) {
+ goto func_exit;
+ }
- max_space_id = 0;
- } else {
- rec = btr_pcur_get_rec(&pcur);
+ rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
+ field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_SPACE, &len);
- ut_a(len == 4);
+ ut_a(len == 4);
- max_space_id = mach_read_from_4(field);
- }
+ const uint32_t max_space_id = mach_read_from_4(field);
ibuf_mtr_commit(&mtr);
@@ -3148,7 +3186,7 @@ ibuf_insert_low(
lint min_n_recs;
rec_t* ins_rec;
buf_block_t* bitmap_page;
- buf_block_t* block;
+ buf_block_t* block = NULL;
page_t* root;
dberr_t err;
ibool do_merge;
@@ -3230,7 +3268,29 @@ ibuf_insert_low(
ibuf_mtr_start(&mtr);
- btr_pcur_open(ibuf.index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
+ err = btr_pcur_open(ibuf.index, ibuf_entry, PAGE_CUR_LE, mode, &pcur,
+ &mtr);
+ if (err != DB_SUCCESS) {
+func_exit:
+ ibuf_mtr_commit(&mtr);
+ ut_free(pcur.old_rec_buf);
+ mem_heap_free(heap);
+
+ if (err == DB_SUCCESS
+ && BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
+ == BTR_MODIFY_TREE) {
+ ibuf_contract_after_insert(entry_size);
+ }
+
+ if (do_merge) {
+#ifdef UNIV_IBUF_DEBUG
+ ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
+#endif
+ ibuf_read_merge_pages(space_ids, page_nos, n_stored);
+ }
+ return err;
+ }
+
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf.index));
/* Find out the volume of already buffered inserts for the same index
@@ -3289,7 +3349,7 @@ fail_exit:
/* We check if the index page is suitable for buffered entries */
- if (buf_pool.page_hash_contains(
+ if (!bitmap_page || buf_pool.page_hash_contains(
page_id, buf_pool.page_hash.cell_get(page_id.fold()))) {
commit_exit:
ibuf_mtr_commit(&bitmap_mtr);
@@ -3388,8 +3448,14 @@ commit_exit:
because a pessimistic insert releases the tree x-latch,
which would cause the sx-latching of the root after that to
break the latching order. */
-
- root = ibuf_tree_root_get(&mtr)->page.frame;
+ if (buf_block_t* ibuf_root = ibuf_tree_root_get(&mtr)) {
+ root = ibuf_root->page.frame;
+ } else {
+ err = DB_CORRUPTION;
+ mysql_mutex_unlock(&ibuf_pessimistic_insert_mutex);
+ mysql_mutex_unlock(&ibuf_mutex);
+ goto ibuf_insert_done;
+ }
err = btr_cur_optimistic_insert(
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
@@ -3414,6 +3480,7 @@ commit_exit:
ut_ad(block->page.id().space() == IBUF_SPACE_ID);
}
+ibuf_insert_done:
if (offsets_heap) {
mem_heap_free(offsets_heap);
}
@@ -3424,24 +3491,7 @@ commit_exit:
thr_get_trx(thr)->id, &mtr);
}
-func_exit:
- ibuf_mtr_commit(&mtr);
- ut_free(pcur.old_rec_buf);
- mem_heap_free(heap);
-
- if (err == DB_SUCCESS
- && BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
- ibuf_contract_after_insert(entry_size);
- }
-
- if (do_merge) {
-#ifdef UNIV_IBUF_DEBUG
- ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
-#endif
- ibuf_read_merge_pages(space_ids, page_nos, n_stored);
- }
-
- return(err);
+ goto func_exit;
}
/** Buffer an operation in the change buffer, instead of applying it
@@ -3578,12 +3628,13 @@ skip_watch:
DBUG_RETURN(err == DB_SUCCESS);
}
+MY_ATTRIBUTE((nonnull, warn_unused_result))
/********************************************************************//**
During merge, inserts to an index page a secondary index entry extracted
from the insert buffer.
-@return newly inserted record */
-static MY_ATTRIBUTE((nonnull))
-rec_t*
+@return error code */
+static
+dberr_t
ibuf_insert_to_index_page_low(
/*==========================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */
@@ -3596,66 +3647,31 @@ ibuf_insert_to_index_page_low(
page_cur_t* page_cur)/*!< in/out: cursor positioned on the record
after which to insert the buffered entry */
{
- rec_t* rec;
- DBUG_ENTER("ibuf_insert_to_index_page_low");
-
- rec = page_cur_tuple_insert(page_cur, entry, index,
- offsets, &heap, 0, mtr);
- if (rec != NULL) {
- DBUG_RETURN(rec);
- }
-
- /* Page reorganization or recompression should already have
- been attempted by page_cur_tuple_insert(). Besides, per
- ibuf_index_page_calc_free_zip() the page should not have been
- recompressed or reorganized. */
- ut_ad(!is_buf_block_get_page_zip(block));
+ if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
+ return DB_SUCCESS;
- /* If the record did not fit, reorganize */
+ /* Page reorganization or recompression should already have been
+ attempted by page_cur_tuple_insert(). Besides, per
+ ibuf_index_page_calc_free_zip() the page should not have been
+ recompressed or reorganized. */
+ ut_ad(!is_buf_block_get_page_zip(block));
- btr_page_reorganize(page_cur, index, mtr);
-
- /* This time the record must fit */
-
- rec = page_cur_tuple_insert(page_cur, entry, index,
- offsets, &heap, 0, mtr);
- if (rec != NULL) {
- DBUG_RETURN(rec);
- }
+ /* If the record did not fit, reorganize */
+ if (dberr_t err= btr_page_reorganize(page_cur, index, mtr))
+ return err;
- ib::error() << "Insert buffer insert fails; page free "
- << page_get_max_insert_size(block->page.frame, 1)
- << ", dtuple size "
- << rec_get_converted_size(index, entry, 0);
+ /* This time the record must fit */
+ if (page_cur_tuple_insert(page_cur, entry, index, offsets, &heap, 0, mtr))
+ return DB_SUCCESS;
- fputs("InnoDB: Cannot insert index record ", stderr);
- dtuple_print(stderr, entry);
- fputs("\nInnoDB: The table where this index record belongs\n"
- "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n"
- "InnoDB: that table.\n", stderr);
-
- if (buf_block_t *bitmap_page = ibuf_bitmap_get_map_page(
- block->page.id(), block->zip_size(), mtr)) {
-
- ib::error() << "page " << block->page.id() << ", size "
- << block->physical_size() << ", bitmap bits "
- << ibuf_bitmap_page_get_bits(
- bitmap_page->page.frame,
- block->page.id(), block->zip_size(),
- IBUF_BITMAP_FREE, mtr);
- }
-
- ib::error() << BUG_REPORT_MSG;
-
- ut_ad(0);
- DBUG_RETURN(NULL);
+ return DB_CORRUPTION;
}
/************************************************************************
During merge, inserts to an index page a secondary index entry extracted
from the insert buffer. */
static
-void
+dberr_t
ibuf_insert_to_index_page(
/*======================*/
const dtuple_t* entry, /*!< in: buffered entry to insert */
@@ -3671,8 +3687,6 @@ ibuf_insert_to_index_page(
rec_offs* offsets;
mem_heap_t* heap;
- DBUG_ENTER("ibuf_insert_to_index_page");
-
DBUG_PRINT("ibuf", ("page " UINT32PF ":" UINT32PF,
block->page.id().space(),
block->page.id().page_no()));
@@ -3691,37 +3705,20 @@ ibuf_insert_to_index_page(
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
!= (ibool)!!page_is_comp(page))) {
- ib::warn() << "Trying to insert a record from the insert"
- " buffer to an index page but the 'compact' flag does"
- " not match!";
- goto dump;
+ return DB_CORRUPTION;
}
rec = page_rec_get_next(page_get_infimum_rec(page));
if (page_rec_is_supremum(rec)) {
- ib::warn() << "Trying to insert a record from the insert"
- " buffer to an index page but the index page"
- " is empty!";
- goto dump;
+ return DB_CORRUPTION;
}
if (!rec_n_fields_is_sane(index, rec, entry)) {
- ib::warn() << "Trying to insert a record from the insert"
- " buffer to an index page but the number of fields"
- " does not match!";
- rec_print(stderr, rec, index);
-dump:
- dtuple_print(stderr, entry);
- ut_ad(0);
-
- ib::warn() << "The table where this index record belongs"
- " is now probably corrupt. Please run CHECK TABLE on"
- " your tables. " << BUG_REPORT_MSG;
-
- DBUG_VOID_RETURN;
+ return DB_CORRUPTION;
}
+ dberr_t err = DB_SUCCESS;
low_match = page_cur_search(block, index, entry, &page_cur);
heap = mem_heap_create(
@@ -3806,21 +3803,16 @@ dump:
page_cur_delete_rec(&page_cur, index, offsets, mtr);
page_cur_move_to_prev(&page_cur);
- rec = ibuf_insert_to_index_page_low(entry, block, index,
- &offsets, heap, mtr,
- &page_cur);
-
- ut_ad(!cmp_dtuple_rec(entry, rec, index, offsets));
} else {
offsets = NULL;
- ibuf_insert_to_index_page_low(entry, block, index,
- &offsets, heap, mtr,
- &page_cur);
- }
+ }
+
+ err = ibuf_insert_to_index_page_low(entry, block, index,
+ &offsets, heap, mtr, &page_cur);
updated_in_place:
mem_heap_free(heap);
- DBUG_VOID_RETURN;
+ return err;
}
/****************************************************************//**
@@ -4025,7 +4017,6 @@ static MY_ATTRIBUTE((warn_unused_result, nonnull))
bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
const dtuple_t* search_tuple, mtr_t* mtr)
{
- page_t* root;
dberr_t err;
ut_ad(ibuf_inside(mtr));
@@ -4035,13 +4026,16 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
ut_ad(ibuf_rec_get_space(mtr, btr_pcur_get_rec(pcur))
== page_id.space());
- if (btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur),
- BTR_CREATE_FLAG, mtr)) {
+ switch (btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur),
+ BTR_CREATE_FLAG, mtr)) {
+ case DB_FAIL:
+ break;
+ case DB_SUCCESS:
if (page_is_empty(btr_pcur_get_page(pcur))) {
/* If a B-tree page is empty, it must be the root page
and the whole B-tree must be empty. InnoDB does not
allow empty B-tree pages other than the root. */
- root = btr_pcur_get_page(pcur);
+ ut_d(const page_t* root = btr_pcur_get_page(pcur));
ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
ut_ad(page_get_page_no(root)
@@ -4052,7 +4046,8 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
ut_ad(!ibuf.empty);
ibuf.empty = true;
}
-
+ /* fall through */
+ default:
return(FALSE);
}
@@ -4078,16 +4073,20 @@ bool ibuf_delete_rec(const page_id_t page_id, btr_pcur_t* pcur,
goto func_exit;
}
- root = ibuf_tree_root_get(mtr)->page.frame;
+ if (buf_block_t* ibuf_root = ibuf_tree_root_get(mtr)) {
+ btr_cur_pessimistic_delete(&err, TRUE,
+ btr_pcur_get_btr_cur(pcur),
+ BTR_CREATE_FLAG, false, mtr);
+ ut_a(err == DB_SUCCESS);
- btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
- BTR_CREATE_FLAG, false, mtr);
- ut_a(err == DB_SUCCESS);
+ ibuf_size_update(ibuf_root->page.frame);
+ mysql_mutex_unlock(&ibuf_mutex);
- ibuf_size_update(root);
- mysql_mutex_unlock(&ibuf_mutex);
+ ibuf.empty = page_is_empty(ibuf_root->page.frame);
+ } else {
+ mysql_mutex_unlock(&ibuf_mutex);
+ }
- ibuf.empty = page_is_empty(root);
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
func_exit:
@@ -4157,25 +4156,16 @@ exist entries for such a page if the page belonged to an index which
subsequently was dropped.
@param block X-latched page to try to apply changes to, or NULL to discard
@param page_id page identifier
-@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
-void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
- ulint zip_size)
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return error code */
+dberr_t ibuf_merge_or_delete_for_page(buf_block_t *block,
+ const page_id_t page_id,
+ ulint zip_size)
{
if (trx_sys_hdr_page(page_id)) {
- return;
+ return DB_SUCCESS;
}
- btr_pcur_t pcur;
-#ifdef UNIV_IBUF_DEBUG
- ulint volume = 0;
-#endif /* UNIV_IBUF_DEBUG */
- bool corruption_noticed = false;
- mtr_t mtr;
-
- /* Counts for merged & discarded operations. */
- ulint mops[IBUF_OP_COUNT];
- ulint dops[IBUF_OP_COUNT];
-
ut_ad(!block || page_id == block->page.id());
ut_ad(!block || block->page.frame);
ut_ad(!block || !block->page.is_ibuf_exist());
@@ -4187,13 +4177,20 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
if (ibuf_fixed_addr_page(page_id, physical_size)
|| fsp_descr_page(page_id, physical_size)) {
- return;
+ return DB_SUCCESS;
}
+ btr_pcur_t pcur;
+#ifdef UNIV_IBUF_DEBUG
+ ulint volume = 0;
+#endif /* UNIV_IBUF_DEBUG */
+ dberr_t err = DB_SUCCESS;
+ mtr_t mtr;
+
fil_space_t* space = fil_space_t::get(page_id.space());
if (UNIV_UNLIKELY(!space)) {
- block = NULL;
+ block = nullptr;
} else {
ulint bitmap_bits = 0;
@@ -4212,8 +4209,9 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
ibuf_mtr_commit(&mtr);
- if (bitmap_bits && fseg_page_is_free(
- space, page_id.page_no())) {
+ if (bitmap_bits
+ && DB_SUCCESS
+ == fseg_page_is_allocated(space, page_id.page_no())) {
ibuf_mtr_start(&mtr);
mtr.set_named_space(space);
ibuf_reset_bitmap(block, page_id, zip_size, &mtr);
@@ -4224,40 +4222,33 @@ void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
if (!bitmap_bits) {
/* No changes are buffered for this page. */
space->release();
- return;
+ return DB_SUCCESS;
}
}
- mem_heap_t* heap = mem_heap_create(512);
-
- const dtuple_t* search_tuple = ibuf_search_tuple_build(
- page_id.space(), page_id.page_no(), heap);
-
- if (block != NULL) {
+ if (!block) {
+ } else if (!fil_page_index_page_check(block->page.frame)
+ || !page_is_leaf(block->page.frame)) {
+ space->set_corrupted();
+ err = DB_CORRUPTION;
+ block = nullptr;
+ } else {
/* Move the ownership of the x-latch on the page to this OS
thread, so that we can acquire a second x-latch on it. This
is needed for the insert operations to the index page to pass
the debug checks. */
block->page.lock.claim_ownership();
+ }
- if (!fil_page_index_page_check(block->page.frame)
- || !page_is_leaf(block->page.frame)) {
+ mem_heap_t* heap = mem_heap_create(512);
- corruption_noticed = true;
+ const dtuple_t* search_tuple = ibuf_search_tuple_build(
+ page_id.space(), page_id.page_no(), heap);
- ib::error() << "Corruption in the tablespace. Bitmap"
- " shows insert buffer records to page "
- << page_id << " though the page type is "
- << fil_page_get_type(block->page.frame)
- << ", which is not an index leaf page. We try"
- " to resolve the problem by skipping the"
- " insert buffer merge for this page. Please"
- " run CHECK TABLE on your tables to determine"
- " if they are corrupt after this.";
- ut_ad(0);
- }
- }
+ /* Counts for merged & discarded operations. */
+ ulint mops[IBUF_OP_COUNT];
+ ulint dops[IBUF_OP_COUNT];
memset(mops, 0, sizeof(mops));
memset(dops, 0, sizeof(dops));
@@ -4267,9 +4258,12 @@ loop:
/* Position pcur in the insert buffer at the first entry for this
index page */
- btr_pcur_open_on_user_rec(
- ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
- &pcur, &mtr);
+ if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF, &pcur, &mtr)
+ != DB_SUCCESS) {
+ err = DB_CORRUPTION;
+ goto reset_bit;
+ }
if (block) {
block->page.fix();
@@ -4304,7 +4298,7 @@ loop:
goto reset_bit;
}
- if (corruption_noticed) {
+ if (err) {
fputs("InnoDB: Discarding record\n ", stderr);
rec_print_old(stderr, rec);
fputs("\nInnoDB: from the insert buffer!\n\n", stderr);
@@ -4439,6 +4433,8 @@ reset_bit:
ibuf.n_merges++;
ibuf_add_ops(ibuf.n_merged_ops, mops);
ibuf_add_ops(ibuf.n_discarded_ops, dops);
+
+ return err;
}
/** Delete all change buffer entries for a tablespace,
@@ -4468,9 +4464,11 @@ loop:
/* Position pcur in the insert buffer at the first entry for the
space */
- btr_pcur_open_on_user_rec(
- ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
- &pcur, &mtr);
+ if (btr_pcur_open_on_user_rec(ibuf.index, search_tuple, PAGE_CUR_GE,
+ BTR_MODIFY_LEAF, &pcur, &mtr)
+ != DB_SUCCESS) {
+ goto leave_loop;
+ }
if (!btr_pcur_is_on_user_rec(&pcur)) {
ut_ad(btr_pcur_is_after_last_on_page(&pcur));
@@ -4532,8 +4530,8 @@ ibuf_is_empty(void)
ut_d(mysql_mutex_lock(&ibuf_mutex));
const buf_block_t* root = ibuf_tree_root_get(&mtr);
- bool is_empty = page_is_empty(root->page.frame);
- ut_a(is_empty == ibuf.empty);
+ bool is_empty = root && page_is_empty(root->page.frame);
+ ut_ad(!root || is_empty == ibuf.empty);
ut_d(mysql_mutex_unlock(&ibuf_mutex));
ibuf_mtr_commit(&mtr);
@@ -4610,6 +4608,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
page_id_t(space->id, page_no), zip_size, &mtr);
if (!bitmap_page) {
mysql_mutex_unlock(&ibuf_mutex);
+ ibuf_exit(&mtr);
mtr.commit();
return DB_CORRUPTION;
}
@@ -4698,29 +4697,21 @@ ibuf_set_bitmap_for_bulk_load(
buf_block_t* block,
bool reset)
{
- mtr_t mtr;
- ulint free_val;
-
- ut_a(page_is_leaf(buf_block_get_frame(block)));
-
- free_val = ibuf_index_page_calc_free(block);
-
- mtr.start();
- fil_space_t* space = mtr.set_named_space_id(block->page.id().space());
-
- buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(block->page.id(),
- space->zip_size(),
- &mtr);
-
- free_val = reset ? 0 : ibuf_index_page_calc_free(block);
- /* FIXME: update the bitmap byte only once! */
- ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>(
- bitmap_page, block->page.id(), block->physical_size(),
- free_val, &mtr);
-
- ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
- bitmap_page, block->page.id(), block->physical_size(),
- false, &mtr);
-
- mtr.commit();
+ mtr_t mtr;
+
+ ut_a(page_is_leaf(block->page.frame));
+ mtr.start();
+ fil_space_t *space= mtr.set_named_space_id(block->page.id().space());
+
+ if (buf_block_t *bitmap_page=
+ ibuf_bitmap_get_map_page(block->page.id(), space->zip_size(), &mtr))
+ {
+ ulint free_val= reset ? 0 : ibuf_index_page_calc_free(block);
+ /* FIXME: update the bitmap byte only once! */
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_FREE>
+ (bitmap_page, block->page.id(), block->physical_size(), free_val, &mtr);
+ ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>
+ (bitmap_page, block->page.id(), block->physical_size(), false, &mtr);
+ }
+ mtr.commit();
}