diff options
Diffstat (limited to 'storage/innobase/btr')
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 165 | ||||
-rw-r--r-- | storage/innobase/btr/btr0bulk.cc | 2 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 10 |
3 files changed, 33 insertions, 144 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 5338fef551b..674046f0026 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -725,159 +725,54 @@ btr_page_free_for_ibuf( mtr)); } -/**************************************************************//** -Frees a file page used in an index tree. Can be used also to (BLOB) -external storage pages. */ -void -btr_page_free_low( -/*==============*/ - dict_index_t* index, /*!< in: index tree */ - buf_block_t* block, /*!< in: block to be freed, x-latched */ - ulint level, /*!< in: page level (ULINT_UNDEFINED=BLOB) */ - bool blob, /*!< in: blob page */ - mtr_t* mtr) /*!< in: mtr */ +/** Free an index page. +@param[in,out] index index tree +@param[in,out] block block to be freed +@param[in,out] mtr mini-transaction +@param[in] blob whether this is freeing a BLOB page */ +void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, + bool blob) { - fseg_header_t* seg_header; - page_t* root; - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!block->index || !blob); + ut_ad(!block->index || page_is_leaf(block->frame)); +#endif + ut_ad(index->table->space_id == block->page.id.space()); + /* The root page is freed by btr_free_root(). */ + ut_ad(block->page.id.page_no() != index->page); + ut_ad(mtr->is_named_space(index->table->space)); + /* The page gets invalid for optimistic searches: increment the frame modify clock */ buf_block_modify_clock_inc(block); - if (blob) { - ut_a(level == 0); - } - - bool scrub = srv_immediate_scrub_data_uncompressed; - /* scrub page */ - if (scrub && blob) { - /* blob page: scrub entire page */ - // TODO(jonaso): scrub only what is actually needed - page_t* page = buf_block_get_frame(block); - memset(page + PAGE_HEADER, 0, - srv_page_size - PAGE_HEADER); -#ifdef UNIV_DEBUG_SCRUBBING - fprintf(stderr, - "btr_page_free_low: scrub blob page %lu/%lu\n", - buf_block_get_space(block), - buf_block_get_page_no(block)); -#endif /* UNIV_DEBUG_SCRUBBING */ - } else if (scrub) { - /* scrub records on page */ - - /* TODO(jonaso): in theory we could clear full page - * but, since page still remains in buffer pool, and - * gets flushed etc. Lots of routines validates consistency - * of it. And in order to remain structurally consistent - * we clear each record by it own - * - * NOTE: The TODO below mentions removing page from buffer pool - * and removing redo entries, once that is done, clearing full - * pages should be possible - */ - uint cnt = 0; - ulint bytes = 0; - page_t* page = buf_block_get_frame(block); - mem_heap_t* heap = NULL; - ulint* offsets = NULL; - rec_t* rec = page_rec_get_next(page_get_infimum_rec(page)); - while (!page_rec_is_supremum(rec)) { - offsets = rec_get_offsets(rec, index, offsets, - page_is_leaf(page), - ULINT_UNDEFINED, - &heap); - ulint size = rec_offs_data_size(offsets); - memset(rec, 0, size); - rec = page_rec_get_next(rec); - cnt++; - bytes += size; - } -#ifdef UNIV_DEBUG_SCRUBBING - fprintf(stderr, - "btr_page_free_low: scrub %lu/%lu - " - "%u records " ULINTPF " bytes\n", - buf_block_get_space(block), - buf_block_get_page_no(block), - cnt, bytes); -#endif /* UNIV_DEBUG_SCRUBBING */ - if (heap) { - mem_heap_free(heap); - } - } - -#ifdef UNIV_DEBUG_SCRUBBING - if (scrub == false) { - fprintf(stderr, - "btr_page_free_low %lu/%lu blob: %u\n", - buf_block_get_space(block), - buf_block_get_page_no(block), - blob); - } -#endif /* UNIV_DEBUG_SCRUBBING */ - if (dict_index_is_ibuf(index)) { - btr_page_free_for_ibuf(index, block, mtr); - return; } - root = btr_root_get(index, mtr); - - if (level == 0 || level == ULINT_UNDEFINED) { - seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - } else { - seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; - } - -#ifdef UNIV_GIS_DEBUG - if (dict_index_is_spatial(index)) { - fprintf(stderr, "GIS_DIAG: Freed %ld\n", - (long) block->page.id.page_no()); - } -#endif - - if (scrub) { - /** - * Reset page type so that scrub thread won't try to scrub it - */ - mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE, - FIL_PAGE_TYPE_ALLOCATED, MLOG_2BYTES, mtr); - } - + /* TODO: Discard any operations for block from mtr->log. + The page will be freed, so previous changes to it by this + mini-transaction should not matter. */ + page_t* root = btr_root_get(index, mtr); + fseg_header_t* seg_header = &root[blob || page_is_leaf(block->frame) + ? PAGE_HEADER + PAGE_BTR_SEG_LEAF + : PAGE_HEADER + PAGE_BTR_SEG_TOP]; fseg_free_page(seg_header, - block->page.id.space(), - block->page.id.page_no(), - level != ULINT_UNDEFINED, mtr); + index->table->space, block->page.id.page_no(), + block->index != NULL, mtr); /* The page was marked free in the allocation bitmap, but it - should remain buffer-fixed until mtr_commit(mtr) or until it + should remain exclusively latched until mtr_t::commit() or until it is explicitly freed from the mini-transaction. */ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - /* TODO: Discard any operations on the page from the redo log - and remove the block from the flush list and the buffer pool. - This would free up buffer pool earlier and reduce writes to - both the tablespace and the redo log. */ -} -/**************************************************************//** -Frees a file page used in an index tree. NOTE: cannot free field external -storage pages because the page must contain info on its level. */ -void -btr_page_free( -/*==========*/ - dict_index_t* index, /*!< in: index tree */ - buf_block_t* block, /*!< in: block to be freed, x-latched */ - mtr_t* mtr) /*!< in: mtr */ -{ - const page_t* page = buf_block_get_frame(block); - ulint level = btr_page_get_level(page); - - ut_ad(fil_page_index_page_check(block->frame)); - ut_ad(level != ULINT_UNDEFINED); - btr_page_free_low(index, block, level, false, mtr); + /* MDEV-15528 FIXME: Zero out the page after the redo log for + this mini-transaction has been durably written. + This must be done unconditionally if + srv_immediate_scrub_data_uncompressed is set. */ } /**************************************************************//** diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index e9b64ebdef3..6a9b71987c5 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -1033,7 +1033,7 @@ BtrBulk::finish(dberr_t err) root_page_bulk.copyIn(first_rec); /* Remove last page. */ - btr_page_free_low(m_index, last_block, m_root_level, false, &mtr); + btr_page_free(m_index, last_block, &mtr); /* Do not flush the last page. */ last_block->page.flush_observer = NULL; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 0b61e340f81..1ba0febd415 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -8145,8 +8145,7 @@ btr_free_externally_stored_field( } next_page_no = mach_read_from_4(page + FIL_PAGE_NEXT); - btr_page_free_low(index, ext_block, 0, - true, &mtr); + btr_page_free(index, ext_block, &mtr, true); if (page_zip != NULL) { mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO, @@ -8172,12 +8171,7 @@ btr_free_externally_stored_field( next_page_no = mach_read_from_4( page + FIL_PAGE_DATA + BTR_BLOB_HDR_NEXT_PAGE_NO); - - /* We must supply the page level (= 0) as an argument - because we did not store it on the page (we save the - space overhead from an index page header. */ - btr_page_free_low(index, ext_block, 0, - true, &mtr); + btr_page_free(index, ext_block, &mtr, true); mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO, next_page_no, |