diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:12:29 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-11-13 20:16:39 +0200 |
commit | bb328a2a274b0b5cc024f298fcac70b3f0fb75aa (patch) | |
tree | cfce8af41648225f8a6a0ac344b75f3bb4c8b3ed /storage/innobase/buf | |
parent | 190e8a4c2aeb417b405756b193e135c542d46b34 (diff) | |
download | mariadb-git-bb328a2a274b0b5cc024f298fcac70b3f0fb75aa.tar.gz |
MDEV-24188 Hang in buf_page_create() after reusing a previously freed page
The fix of MDEV-23456 (commit b1009ae5c16697d5eef443cc6a60a74301148c73)
introduced a livelock between page flushing and a thread that is
executing buf_page_create().
buf_page_create(): If the current mini-transaction is holding
an exclusive latch on the page, do not attempt to acquire another
one, and do not care about any I/O fix.
mtr_t::have_x_latch(): Replaces mtr_t::get_fix_count().
dyn_buf_t::for_each_block(const Functor&) const: A new variant.
rw_lock_own(): Add a const qualifier.
Reviewed by: Thirunarayanan Balathandayuthapani
Diffstat (limited to 'storage/innobase/buf')
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index a54d98adee0..9f3d743ada1 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5511,6 +5511,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 @@ -5563,26 +5564,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 @@ -5601,16 +5602,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; } |