From 8ba5e8510471acc9911ce8a1ef3dd385ac1be7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 29 Aug 2022 15:14:59 +0300 Subject: MDEV-27983: InnoDB hangs after loading a ROW_FORMAT=COMPRESSED page If multiple threads invoke buf_page_get_low() on a ROW_FORMAT=COMPRESSED page that does not reside in the buffer pool, then one of the threads will end up acquiring an exclusive page latch (the "if" statement right before the new wait_for_unzip: label) and other threads will end up waiting for a shared latch while holding a buffer-fix. The exclusive latch holder would then wait for the buffer-fixes to be released while the buffer-fix holders are waiting for the shared latch. buf_page_get_low(): Prevent the hang that was introduced in commit 9436c778c3adba7c29dab5649668433d71e086f2 (MDEV-27058), by releasing the buffer-fix, sleeping some time, and retrying the page lookup. --- storage/innobase/buf/buf0buf.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index eaf0f955a1f..0d0978c0c1d 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2529,6 +2529,9 @@ ignore_block: return nullptr; } + if (state != buf_page_t::READ_FIX + 1 && !block->page.frame) { + goto wait_for_unzip; + } /* A read-fix is released after block->page.lock in buf_page_t::read_complete() or buf_pool_t::corrupted_evict(), or @@ -2559,7 +2562,7 @@ ignore_block: mysql_mutex_lock(&buf_pool.mutex); block->unfix(); - if (!buf_LRU_free_page(&block->page, true)) { + if (!buf_LRU_free_page(&block->page, true)) { ut_ad(0); } @@ -2577,6 +2580,7 @@ ignore_block: if (UNIV_UNLIKELY(!block->page.frame)) { if (!block->page.lock.x_lock_try()) { +wait_for_unzip: /* The page is being read or written, or another thread is executing buf_zip_decompress() in buf_page_get_low() on it. */ -- cgit v1.2.1