diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:45:28 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:45:28 +0200 |
commit | 749ecedfece22d5bdb27a5f682d430e1aa6ec194 (patch) | |
tree | 1afe5554a6dc3060204da84eca4f5029e71745b0 | |
parent | b63dc3f3703af888c564521d9a22c661940c02d1 (diff) | |
parent | f9f2f37495e70128142ea56544b40854f6b2afe5 (diff) | |
download | mariadb-git-749ecedfece22d5bdb27a5f682d430e1aa6ec194.tar.gz |
MDEV-24188: Merge 10.3 into 10.4
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 35 | ||||
-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, 89 insertions, 47 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 967747c4a38..1462c847e09 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5535,6 +5535,7 @@ loop: && buf_page_in_file(&block->page) && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { ut_d(block->page.file_page_was_freed = FALSE); + bool have_x_latch = false; #ifdef BTR_CUR_HASH_ADAPT const dict_index_t *drop_hash_entry= nullptr; #endif @@ -5587,22 +5588,24 @@ loop: free_block = nullptr; break; case BUF_BLOCK_FILE_PAGE: - buf_block_buf_fix_inc(block, __FILE__, __LINE__); - const uint32_t num_fix_count= mtr->get_fix_count(block) - + 1; - while (buf_block_get_io_fix(block) != BUF_IO_NONE - || (num_fix_count - != block->page.buf_fix_count)) { - buf_pool_mutex_exit(buf_pool); - rw_lock_x_unlock(hash_lock); - - os_thread_yield(); + have_x_latch = mtr->have_x_latch(*block); + if (!have_x_latch) { + buf_block_buf_fix_inc(block, + __FILE__, __LINE__); + while (buf_block_get_io_fix(block) + != BUF_IO_NONE + || block->page.buf_fix_count != 1) { + 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_pool_mutex_enter(buf_pool); - rw_lock_x_lock(hash_lock); + rw_lock_x_lock(&block->lock); } - - rw_lock_x_lock(&block->lock); #ifdef BTR_CUR_HASH_ADAPT drop_hash_entry = block->index; #endif @@ -5622,7 +5625,9 @@ loop: } #endif /* BTR_CUR_HASH_ADAPT */ - mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX); + if (!have_x_latch) { + 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 a7d0af02986..b5915c934a1 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -426,10 +426,9 @@ struct mtr_t { static inline bool is_block_dirtied(const buf_block_t* block) MY_ATTRIBUTE((warn_unused_result)); - /** Determine the added buffer fix count of a block. - @param block block to be checked - @return number of buffer count added by this mtr */ - uint32_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 acb569d40e8..948a5442c53 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 5ca74659813..3ed9856a58a 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 */ @@ -753,12 +735,48 @@ inline lsn_t mtr_t::finish_write(ulint len) return start_lsn; } -uint32_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 @@ -775,15 +793,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 fea94cc05f9..9f9453e20b5 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -984,7 +984,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 */ { |