diff --git a/mysql-8.0.19/storage/innobase/buf/buf0buf.cc b/mysql-8.0.19/storage/innobase/buf/buf0buf.cc index 5dd85f1d6..338cdeb82 100644 --- a/mysql-8.0.19/storage/innobase/buf/buf0buf.cc +++ b/mysql-8.0.19/storage/innobase/buf/buf0buf.cc @@ -3371,7 +3371,7 @@ static bool buf_debug_execute_is_force_flush() { /** Wait for the block to be read in. @param[in] block The block to check */ -static void buf_wait_for_read(buf_block_t *block) { +static bool buf_wait_for_read(buf_block_t *block) { /* Note: We are using the block->lock to check for IO state (and a dirty read). @@ -3383,7 +3383,11 @@ static void buf_wait_for_read(buf_block_t *block) { if (buf_block_get_io_fix_unlocked(block) == BUF_IO_READ) { /* Wait until the read operation completes */ for (;;) { - if (buf_block_get_io_fix_unlocked(block) == BUF_IO_READ) { + if (block->page.state == BUF_BLOCK_MEMORY) { + buf_block_unfix(block); + os_thread_sleep(40); + return true; + } else if (buf_block_get_io_fix_unlocked(block) == BUF_IO_READ) { /* Wait by temporaly s-latch */ if (rw_lock_s_lock_low(&block->lock, 0, __FILE__, __LINE__)) { rw_lock_s_unlock(&block->lock); @@ -3397,6 +3401,7 @@ static void buf_wait_for_read(buf_block_t *block) { } } } + return false; } template @@ -4125,7 +4130,10 @@ buf_block_t *Buf_fetch::single_page() { /* We have to wait here because the IO_READ state was set under the protection of the hash_lock and not the block->mutex and block->lock. */ - buf_wait_for_read(block); + if (buf_wait_for_read(block)) { + block = NULL; + continue; + } /* Mark block as dirty if requested by caller. If not requested (false) then we avoid updating the dirty state of the block and retain the @@ -5094,6 +5102,22 @@ void buf_read_page_handle_error(buf_page_t *bpage) { mutex_enter(buf_page_get_mutex(bpage)); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); + + enum buf_page_state page_state = buf_page_get_state(bpage); + + /** just used to stop buf_wait_for_read. + during this period ,this thread own x-hash_lock, + and no new thread can get the bpage from page_hash, + so it is safe to set bpage->state = BUF_BLOCK_MEMORY + */ + buf_page_set_state(bpage, BUF_BLOCK_MEMORY); + + while (bpage->buf_fix_count) { + os_thread_sleep(20); + } + + buf_page_set_state(bpage, page_state); + ut_ad(bpage->buf_fix_count == 0); /* Set BUF_IO_NONE before we remove the block from LRU list */