diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:41:48 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:41:48 +0200 |
commit | f9f2f37495e70128142ea56544b40854f6b2afe5 (patch) | |
tree | 45c17cf39c7bc3f0c029a56a10b93ebcd9d928a0 | |
parent | 6fed6de93f120b5e311b79892e7865639e9613a4 (diff) | |
parent | bb328a2a274b0b5cc024f298fcac70b3f0fb75aa (diff) | |
download | mariadb-git-f9f2f37495e70128142ea56544b40854f6b2afe5.tar.gz |
MDEV-24188: Merge 10.2 into 10.3
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 52 | ||||
-rw-r--r-- | storage/innobase/include/dyn0buf.h | 18 | ||||
-rw-r--r-- | storage/innobase/include/mtr0mtr.h | 7 | ||||
-rw-r--r-- | storage/innobase/include/sync0rw.h | 2 | ||||
-rw-r--r-- | storage/innobase/mtr/mtr0mtr.cc | 72 | ||||
-rw-r--r-- | storage/innobase/sync/sync0rw.cc | 2 |
6 files changed, 96 insertions, 57 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 748ca4ed404..a6fedaed3c2 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5573,6 +5573,7 @@ loop: && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { ut_d(block->page.file_page_was_freed = FALSE); buf_page_state page_state = buf_block_get_state(block); + bool have_x_latch = false; #ifdef BTR_CUR_HASH_ADAPT const dict_index_t *drop_hash_entry= NULL; #endif @@ -5625,26 +5626,26 @@ loop: free_block = NULL; break; case BUF_BLOCK_FILE_PAGE: - buf_block_fix(block); - const int32_t num_fix_count = - mtr->get_fix_count(block) + 1; - buf_page_mutex_enter(block); - while (buf_block_get_io_fix(block) != BUF_IO_NONE - || (num_fix_count - != block->page.buf_fix_count)) { - buf_page_mutex_exit(block); - buf_pool_mutex_exit(buf_pool); - rw_lock_x_unlock(hash_lock); - - os_thread_yield(); - - buf_pool_mutex_enter(buf_pool); - rw_lock_x_lock(hash_lock); + have_x_latch = mtr->have_x_latch(*block); + if (!have_x_latch) { + buf_block_fix(block); buf_page_mutex_enter(block); + while (buf_block_get_io_fix(block) + != BUF_IO_NONE + || block->page.buf_fix_count != 1) { + buf_page_mutex_exit(block); + buf_pool_mutex_exit(buf_pool); + rw_lock_x_unlock(hash_lock); + + os_thread_sleep(1000); + + buf_pool_mutex_enter(buf_pool); + rw_lock_x_lock(hash_lock); + buf_page_mutex_enter(block); + } + rw_lock_x_lock(&block->lock); + buf_page_mutex_exit(block); } - - rw_lock_x_lock(&block->lock); - buf_page_mutex_exit(block); #ifdef BTR_CUR_HASH_ADAPT drop_hash_entry = block->index; #endif @@ -5663,16 +5664,17 @@ loop: } #endif /* BTR_CUR_HASH_ADAPT */ + if (!have_x_latch) { #ifdef UNIV_DEBUG - if (!fsp_is_system_temporary(page_id.space())) { - rw_lock_s_lock_nowait( - &block->debug_latch, - __FILE__, __LINE__); - } + if (!fsp_is_system_temporary(page_id.space())) { + rw_lock_s_lock_nowait( + &block->debug_latch, + __FILE__, __LINE__); + } #endif /* UNIV_DEBUG */ - mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX); - + mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX); + } return block; } diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h index be263e04e15..bd883eb796c 100644 --- a/storage/innobase/include/dyn0buf.h +++ b/storage/innobase/include/dyn0buf.h @@ -331,6 +331,24 @@ public: } /** + Iterate over each block and call the functor. + @return false if iteration was terminated. */ + template <typename Functor> + bool for_each_block(const Functor& functor) const + { + for (typename list_t::iterator it = m_list.begin(), + end = m_list.end(); + it != end; ++it) { + + if (!functor(&*it)) { + return false; + } + } + + return(true); + } + + /** Iterate over all the blocks in reverse and call the iterator @return false if iteration was terminated. */ template <typename Functor> diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 31da089f74b..1ddfda05186 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -437,10 +437,9 @@ struct mtr_t { static inline bool is_block_dirtied(const buf_block_t* block) MY_ATTRIBUTE((warn_unused_result)); - /** Get the buffer fix count for the block added by this mtr. - @param[in] block block to be checked - @return number of buffer count added by this mtr */ - int32_t get_fix_count(const buf_block_t *block); + /** Check if we are holding a block latch in exclusive mode + @param block buffer pool block to search for */ + bool have_x_latch(const buf_block_t& block) const; private: /** Prepare to write the mini-transaction log to the redo log buffer. @return number of bytes to write in finish_write() */ diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index 34619f9b5d8..84e8800a447 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -508,7 +508,7 @@ the pass value == 0. */ bool rw_lock_own( /*========*/ - rw_lock_t* lock, /*!< in: rw-lock */ + const rw_lock_t*lock, /*!< in: rw-lock */ ulint lock_type) /*!< in: lock type: RW_LOCK_S, RW_LOCK_X */ MY_ATTRIBUTE((warn_unused_result)); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index ef6dc58e749..2f22e8e0c16 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -308,24 +308,6 @@ struct DebugCheck { }; #endif -/** Find buffer fix count of the given block acquired by the -mini-transaction */ -struct FindBlock -{ - int32_t num_fix; - const buf_block_t *const block; - - FindBlock(const buf_block_t *block_buf): num_fix(0), block(block_buf) {} - - bool operator()(const mtr_memo_slot_t* slot) - { - if (slot->object == block) - ut_d(if (slot->type != MTR_MEMO_MODIFY)) - num_fix++; - return true; - } -}; - /** Release a resource acquired by the mini-transaction. */ struct ReleaseBlocks { /** Release specific object */ @@ -754,12 +736,48 @@ inline lsn_t mtr_t::finish_write(ulint len) return start_lsn; } -int32_t mtr_t::get_fix_count(const buf_block_t *block) +/** Find out whether a block was X-latched by the mini-transaction */ +struct FindBlockX { - Iterate<FindBlock> iteration((FindBlock(block))); - if (m_memo.for_each_block(iteration)) - return iteration.functor.num_fix; - return 0; + const buf_block_t █ + + FindBlockX(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; + } +}; + +#ifdef UNIV_DEBUG +/** Assert that the block is not present in the mini-transaction */ +struct FindNoBlock +{ + const buf_block_t █ + + FindNoBlock(const buf_block_t &block): block(block) {} + + /** @return whether the block was not found */ + bool operator()(const mtr_memo_slot_t *slot) const + { + return slot->object != █ + } +}; +#endif /* UNIV_DEBUG */ + +bool mtr_t::have_x_latch(const buf_block_t &block) const +{ + if (m_memo.for_each_block(CIterate<FindBlockX>(FindBlockX(block)))) + { + ut_ad(m_memo.for_each_block(CIterate<FindNoBlock>(FindNoBlock(block)))); + ut_ad(!memo_contains_flagged(&block, + MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX | + MTR_MEMO_BUF_FIX | MTR_MEMO_MODIFY)); + return false; + } + ut_ad(rw_lock_own(&block.lock, RW_LOCK_X)); + return true; } #ifdef UNIV_DEBUG @@ -776,15 +794,17 @@ mtr_t::memo_contains( return(false); } + const rw_lock_t *lock = static_cast<const rw_lock_t*>(object); + switch (type) { case MTR_MEMO_X_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_X)); + ut_ad(rw_lock_own(lock, RW_LOCK_X)); break; case MTR_MEMO_SX_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_SX)); + ut_ad(rw_lock_own(lock, RW_LOCK_SX)); break; case MTR_MEMO_S_LOCK: - ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_S)); + ut_ad(rw_lock_own(lock, RW_LOCK_S)); break; } diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index d71bc9cda90..8ebfd27e7aa 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -1000,7 +1000,7 @@ the pass value == 0. bool rw_lock_own( /*========*/ - rw_lock_t* lock, /*!< in: rw-lock */ + const rw_lock_t*lock, /*!< in: rw-lock */ ulint lock_type) /*!< in: lock type: RW_LOCK_S, RW_LOCK_X */ { |