Bug #103391 buf_get_LRU_mutex can be optimized for flushing from FLUSH_LIST
Submitted: 21 Apr 2021 4:24 Modified: 14 May 2021 13:03
Reporter: zhai weixiang (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:8.0.24 OS:Any
Assigned to: CPU Architecture:Any

[21 Apr 2021 4:24] zhai weixiang
Description:
In function buf_get_LRU_mutex, if the flushing is from flush_list, it may acquire lru_mutex and then release it immediately, actually we can skip acquire/release lru mutex in such case.

How to repeat:
read the code

Suggested fix:
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index c79377c..b423331 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -5212,24 +5212,21 @@ static bool buf_get_LRU_mutex(buf_page_t *bpage) noexcept {
   auto buf_pool = buf_pool_from_bpage(bpage);
   const auto flush_type = buf_page_get_flush_type(bpage);
 
-  mutex_enter(&buf_pool->LRU_list_mutex);
-
-  auto block_mutex = buf_page_get_mutex(bpage);
-  mutex_enter(block_mutex);
-
-  if (
+  bool will_hold_mutex = (
 #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
       /* To keep consistency at buf_LRU_insert_zip_clean() */
       buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY ||
 #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-      flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_SINGLE_PAGE) {
+      flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_SINGLE_PAGE);
 
-    return true;
+  if (will_hold_mutex) {
+    mutex_enter(&buf_pool->LRU_list_mutex);
   }
 
-  mutex_exit(&buf_pool->LRU_list_mutex);
+  auto block_mutex = buf_page_get_mutex(bpage);
+  mutex_enter(block_mutex);
 
-  return false;
+  return will_hold_mutex;
 }
[21 Apr 2021 7:19] MySQL Verification Team
Hello Zhai,

Thank you for the report and feedback.

regards,
Umesh
[14 May 2021 13:03] Daniel Price
Posted by developer:
 
Fixed as of the upcoming 8.0.26 release, and here's the proposed changelog entry from the documentation team:

The buf_get_LRU_mutex() function was optimized to avoid acquiring the LRU
mutex unnecessarily when flushing from the flush list.