diff options
-rw-r--r-- | mysql-test/suite/atomic/disabled.def | 13 | ||||
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 52 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 7 | ||||
-rw-r--r-- | storage/innobase/btr/btr0sea.cc | 39 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 12 | ||||
-rw-r--r-- | storage/innobase/include/btr0sea.h | 17 | ||||
-rw-r--r-- | storage/innobase/include/mtr0mtr.h | 13 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 27 | ||||
-rw-r--r-- | storage/innobase/mtr/mtr0mtr.cc | 36 |
9 files changed, 162 insertions, 54 deletions
diff --git a/mysql-test/suite/atomic/disabled.def b/mysql-test/suite/atomic/disabled.def deleted file mode 100644 index 6d8defe344a..00000000000 --- a/mysql-test/suite/atomic/disabled.def +++ /dev/null @@ -1,13 +0,0 @@ -############################################################################## -# -# List the test cases that are to be disabled temporarily. -# -# Separate the test case name and the comment with ':'. -# -# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment> -# -# Do not use any TAB characters for whitespace. -# -############################################################################## - -rename_trigger : MDEV-29282 atomic.rename_trigger fails occasionly diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 7334a2e1757..9ce96f66e64 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -513,9 +513,28 @@ btr_page_alloc_low( page should be initialized. */ dberr_t* err) /*!< out: error code */ { - buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, err); + const auto savepoint= mtr->get_savepoint(); + buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, err); if (UNIV_UNLIKELY(!root)) return root; + + if (mtr->have_u_or_x_latch(*root)) + { +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!root->index || !root->index->freed()); +#endif + mtr->release_block_at_savepoint(savepoint, root); + } + else + { + mtr->u_lock_register(savepoint); + root->page.lock.u_lock(); +#ifdef BTR_CUR_HASH_ADAPT + if (root->index) + mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX); +#endif + } + fseg_header_t *seg_header= root->page.frame + (level ? PAGE_HEADER + PAGE_BTR_SEG_TOP : PAGE_HEADER + PAGE_BTR_SEG_LEAF); return fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction, @@ -584,8 +603,8 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, bool blob, bool space_latched) { ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX)); -#ifdef BTR_CUR_HASH_ADAPT - if (block->index && !block->index->freed()) +#if defined BTR_CUR_HASH_ADAPT && defined UNIV_DEBUG + if (btr_search_check_marked_free_index(block)) { ut_ad(!blob); ut_ad(page_is_leaf(block->page.frame)); @@ -610,11 +629,30 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr, fil_space_t *space= index->table->space; dberr_t err; - if (page_t* root = btr_root_get(index, mtr, &err)) + + const auto savepoint= mtr->get_savepoint(); + if (buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, &err)) { - err= fseg_free_page(&root[blob || page_is_leaf(block->page.frame) - ? PAGE_HEADER + PAGE_BTR_SEG_LEAF - : PAGE_HEADER + PAGE_BTR_SEG_TOP], + if (mtr->have_u_or_x_latch(*root)) + { +#ifdef BTR_CUR_HASH_ADAPT + ut_ad(!root->index || !root->index->freed()); +#endif + mtr->release_block_at_savepoint(savepoint, root); + } + else + { + mtr->u_lock_register(savepoint); + root->page.lock.u_lock(); +#ifdef BTR_CUR_HASH_ADAPT + if (root->index) + mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX); +#endif + } + err= fseg_free_page(&root->page.frame[blob || + page_is_leaf(block->page.frame) + ? PAGE_HEADER + PAGE_BTR_SEG_LEAF + : PAGE_HEADER + PAGE_BTR_SEG_TOP], space, page, mtr, space_latched); } if (err == DB_SUCCESS) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 7a9480cdf4e..4272c760f8d 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -283,7 +283,7 @@ latch_block: block->page.fix(); block->page.lock.x_lock(); #ifdef BTR_CUR_HASH_ADAPT - ut_ad(!block->index || !block->index->freed()); + ut_ad(!btr_search_check_marked_free_index(block)); #endif if (UNIV_LIKELY_NULL(rtr_info)) { @@ -7024,7 +7024,8 @@ btr_store_big_rec_extern_fields( rec_block->page.fix(); rec_block->page.lock.x_lock(); #ifdef BTR_CUR_HASH_ADAPT - ut_ad(!rec_block->index || !rec_block->index->freed()); + ut_ad(!btr_search_check_marked_free_index( + rec_block)); #endif uint32_t hint_prev = prev_page_no; @@ -7401,7 +7402,7 @@ skip_free: block->fix(); block->page.lock.x_lock(); #ifdef BTR_CUR_HASH_ADAPT - ut_ad(!block->index || !block->index->freed()); + ut_ad(!btr_search_check_marked_free_index(block)); #endif const page_t* page = buf_block_get_frame(ext_block); diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 137a8b10d9f..4fb3cfd5f68 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1279,8 +1279,11 @@ fail_and_release_page: index page for which we know that block->buf_fix_count == 0 or it is an index page which has already been removed from the buf_pool.page_hash - i.e.: it is in state BUF_BLOCK_REMOVE_HASH */ -void btr_search_drop_page_hash_index(buf_block_t* block) + i.e.: it is in state BUF_BLOCK_REMOVE_HASH +@param[in] garbage_collect drop ahi only if the index is marked + as freed */ +void btr_search_drop_page_hash_index(buf_block_t* block, + bool garbage_collect) { ulint n_fields; ulint n_bytes; @@ -1316,13 +1319,21 @@ retry: auto part = btr_search_sys.get_part(index_id, block->page.id().space()); + part->latch.rd_lock(SRW_LOCK_CALL); + dict_index_t* index = block->index; bool is_freed = index && index->freed(); if (is_freed) { + part->latch.rd_unlock(); part->latch.wr_lock(SRW_LOCK_CALL); - } else { - part->latch.rd_lock(SRW_LOCK_CALL); + if (index != block->index) { + part->latch.wr_unlock(); + goto retry; + } + } else if (garbage_collect) { + part->latch.rd_unlock(); + return; } assert_block_ahi_valid(block); @@ -1797,12 +1808,13 @@ drop_exit: return; } + ahi_latch->rd_lock(SRW_LOCK_CALL); + if (index->freed()) { + ahi_latch->rd_unlock(); goto drop_exit; } - ahi_latch->rd_lock(SRW_LOCK_CALL); - if (block->index) { uint16_t n_fields = block->curr_n_fields; uint16_t n_bytes = block->curr_n_bytes; @@ -2394,5 +2406,20 @@ btr_search_validate() return(true); } +#ifdef UNIV_DEBUG +bool btr_search_check_marked_free_index(const buf_block_t *block) +{ + if (!block->index) + return false; + + btr_search_s_lock_all(); + + bool is_freed = block->index && block->index->freed(); + + btr_search_s_unlock_all(); + + return is_freed; +} +#endif #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 42055246a12..c26bbda9473 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2761,11 +2761,7 @@ re_evict: && state < buf_page_t::WRITE_FIX)); #ifdef BTR_CUR_HASH_ADAPT - if (dict_index_t* index = block->index) { - if (index->freed()) { - btr_search_drop_page_hash_index(block); - } - } + btr_search_drop_page_hash_index(block, true); #endif /* BTR_CUR_HASH_ADAPT */ dberr_t e; @@ -2823,10 +2819,8 @@ get_latch: } get_latch_valid: #ifdef BTR_CUR_HASH_ADAPT - if (dict_index_t* index = block->index) { - if (index->freed()) { - mtr_t::defer_drop_ahi(block, fix_type); - } + if (block->index) { + mtr_t::defer_drop_ahi(block, fix_type); } #endif /* BTR_CUR_HASH_ADAPT */ mtr->memo_push(block, fix_type); diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 106582286a9..c66e412c27c 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -100,8 +100,11 @@ btr_search_move_or_delete_hash_entries( index page for which we know that block->buf_fix_count == 0 or it is an index page which has already been removed from the buf_pool.page_hash - i.e.: it is in state BUF_BLOCK_REMOVE_HASH */ -void btr_search_drop_page_hash_index(buf_block_t* block); + i.e.: it is in state BUF_BLOCK_REMOVE_HASH +@param[in] garbage_collect drop ahi only if the index is marked + as freed */ +void btr_search_drop_page_hash_index(buf_block_t* block, + bool garbage_collect= false); /** Drop possible adaptive hash index entries when a page is evicted from the buffer pool or freed in a file, or the index is being dropped. @@ -146,16 +149,24 @@ static inline void btr_search_s_lock_all(); /** Unlock all search latches from shared mode. */ static inline void btr_search_s_unlock_all(); +#ifdef UNIV_DEBUG +/** @return if the index is marked as freed */ +bool btr_search_check_marked_free_index(const buf_block_t *block); +#endif /* UNIV_DEBUG */ + #else /* BTR_CUR_HASH_ADAPT */ # define btr_search_sys_create() # define btr_search_sys_free() -# define btr_search_drop_page_hash_index(block) +# define btr_search_drop_page_hash_index(block,garbage_collect) # define btr_search_s_lock_all(index) # define btr_search_s_unlock_all(index) # define btr_search_info_update(index, cursor) # define btr_search_move_or_delete_hash_entries(new_block, block) # define btr_search_update_hash_on_insert(cursor, ahi_latch) # define btr_search_update_hash_on_delete(cursor) +#ifdef UNIV_DEBUG +# define btr_search_check_marked_free_index(block) +#endif /* UNIV_DEBUG */ #endif /* BTR_CUR_HASH_ADAPT */ #ifdef BTR_CUR_ADAPT diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 8a3fe59ac59..edf583aa466 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -177,6 +177,10 @@ struct mtr_t { @param block buffer pool block to search for */ bool have_x_latch(const buf_block_t &block) const; + /** Check if we are holding a block latch in S or U mode + @param block buffer pool block to search for */ + bool have_u_or_x_latch(const buf_block_t &block) const; + /** Copy the tablespaces associated with the mini-transaction (needed for generating FILE_MODIFY records) @param[in] mtr mini-transaction that may modify @@ -336,6 +340,15 @@ public: @param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */ void page_lock(buf_block_t *block, ulint rw_latch); + /** Register a page latch on a buffer-fixed block was buffer-fixed. + @param latch latch type */ + void u_lock_register(ulint savepoint) + { + mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint); + ut_ad(slot->type == MTR_MEMO_BUF_FIX); + slot->type= MTR_MEMO_PAGE_SX_FIX; + } + /** Upgrade U locks on a block to X */ void page_lock_upgrade(const buf_block_t &block); /** Upgrade X lock to X */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 9b6f778b859..ff0858a2a70 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -829,7 +829,29 @@ processed: fil_space_t *space= fil_space_t::create(it->first, flags, FIL_TYPE_TABLESPACE, crypt_data); ut_ad(space); - space->add(name.c_str(), OS_FILE_CLOSED, size, false, false); + const char* filename= name.c_str(); + if (srv_operation == SRV_OPERATION_RESTORE) + { + const char* tbl_name = strrchr(filename, '/'); +#ifdef _WIN32 + if (const char *last = strrchr(filename, '\\')) + { + if (last > tbl_name) + tbl_name = last; + } +#endif + if (tbl_name) + { + while (--tbl_name > filename +#ifdef _WIN32 + && *tbl_name != '\\' +#endif + && *tbl_name != '/'); + if (tbl_name > filename) + filename = tbl_name + 1; + } + } + space->add(filename, OS_FILE_CLOSED, size, false, false); space->recv_size= it->second.size; space->size_in_header= size; return space; @@ -1227,9 +1249,6 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, d->deleted = true; goto got_deleted; } - if (ftype == FILE_RENAME) { - d->file_name= fname.name; - } goto reload; } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 594982f07c2..c4236883632 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1220,6 +1220,21 @@ struct FindBlockX } }; +/** Find out whether a block was not X or U latched by the mini-transaction */ +struct FindBlockUX +{ + const buf_block_t █ + + FindBlockUX(const buf_block_t &block): block(block) {} + + /** @return whether the block was not found x-latched */ + bool operator()(const mtr_memo_slot_t *slot) const + { + return slot->object != &block || + !(slot->type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); + } +}; + #ifdef UNIV_DEBUG /** Assert that the block is not present in the mini-transaction */ struct FindNoBlock @@ -1250,6 +1265,14 @@ bool mtr_t::have_x_latch(const buf_block_t &block) const return true; } +bool mtr_t::have_u_or_x_latch(const buf_block_t &block) const +{ + if (m_memo.for_each_block(CIterate<FindBlockUX>(FindBlockUX(block)))) + return false; + ut_ad(block.page.lock.have_u_or_x()); + return true; +} + /** Check if we are holding exclusive tablespace latch @param space tablespace to search for @param shared whether to look for shared latch, instead of exclusive @@ -1282,18 +1305,14 @@ void mtr_t::defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type) /* Temporarily release our S-latch. */ block->page.lock.s_unlock(); block->page.lock.x_lock(); - if (dict_index_t *index= block->index) - if (index->freed()) - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, true); block->page.lock.x_unlock(); block->page.lock.s_lock(); ut_ad(!block->page.is_read_fixed()); break; case MTR_MEMO_PAGE_SX_FIX: block->page.lock.u_x_upgrade(); - if (dict_index_t *index= block->index) - if (index->freed()) - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, true); block->page.lock.x_u_downgrade(); break; case MTR_MEMO_PAGE_X_FIX: @@ -1383,9 +1402,8 @@ void mtr_t::page_lock(buf_block_t *block, ulint rw_latch) } #ifdef BTR_CUR_HASH_ADAPT - if (dict_index_t *index= block->index) - if (index->freed()) - defer_drop_ahi(block, fix_type); + if (block->index) + defer_drop_ahi(block, fix_type); #endif /* BTR_CUR_HASH_ADAPT */ done: |