Bug #75235 Optimize ibuf merge when reading a page from disk
Submitted: 16 Dec 2014 11:46 Modified: 16 Dec 2014 18:58
Reporter: Naga Satyanarayana Bodapati Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:5.7.6 OS:Any
Assigned to: CPU Architecture:Any

[16 Dec 2014 11:46] Naga Satyanarayana Bodapati
Description:
When ever a page is read from disk, we check if there are pending ibuf entries and merge them.
i.e. in buf_page_io_complete()

               /* If space is being truncated then avoid ibuf operation.
                During re-init we have already freed ibuf entries. */
                if (uncompressed
                    && !recv_no_ibuf_operations
                    && !Tablespace::is_undo_tablespace(bpage->id.space())
                    && !srv_is_tablespace_truncated(bpage->id.space())) {
                        ibuf_merge_or_delete_for_page(
                                (buf_block_t*) bpage, bpage->id,
                                &bpage->size, TRUE);
                }

We acquire RW_X_LATCH on the IBUF bitmap page, process the bitmap and skip for the IBUF merge
for BLOB pages, clustered index pages, etc.

We could optimise this by checking the page type very early since we just read the page from disk.

Also we could skip ibuf merge check for temporary tablespace since IBUF is disabled for temproary tables.

How to repeat:
Read code

Suggested fix:
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index b0e95e2..2230731 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -5543,11 +5543,16 @@ corrupt:
 		}
 
 		/* If space is being truncated then avoid ibuf operation.
-		During re-init we have already freed ibuf entries. */
+		During re-init we have already freed ibuf entries.
+		Change buffer is applicable only for B-tree secondary
+		leaf pages in non-temporary tablespace. */
 		if (uncompressed
 		    && !recv_no_ibuf_operations
 		    && !Tablespace::is_undo_tablespace(bpage->id.space())
-		    && !srv_is_tablespace_truncated(bpage->id.space())) {
+		    && bpage->id.space() != srv_tmp_space.space_id()
+		    && !srv_is_tablespace_truncated(bpage->id.space())
+		    && fil_page_get_type(frame) == FIL_PAGE_INDEX
+		    && page_is_leaf(frame)) {
 
 			ibuf_merge_or_delete_for_page(
 				(buf_block_t*) bpage, bpage->id,
[16 Dec 2014 18:07] Daniel Price
Posted by developer:
 
Bug#20220909 - OPTIMIZE IBUF MERGE WHEN READING A PAGE FROM DISK
    
    Problem:
    --------
    For every page we read, we check if there are pending ibuf entries.
    We acquire RW_X_LATCH on the IBUF page, check if there is ibuf
    entry for the page. Change buffer is applicable only on for B-tree
    secondary leaf pages in non-temporary tablespace. So for other page
    types, we unnecessarily acquire & release latch on IBUF page (page 1).
    
    Fix:
    ---
    We can skip the ibuf merge early without acquiring & releasing the latch
    on IBUF page.
    
    We will use the page_type, page_level & the tablespace type from the
    page which is read from disk to skip the ibuf merge.
[16 Dec 2014 18:58] Daniel Price
Posted by developer:
 
Fixed as of the upcoming 5.7.6 release, and here's the changelog entry:

When a page is read from disk, there is a check for pending insert buffer
entries which involves acquiring a latch on the insert buffer page. If
pending entries are found, they are merged. Because the change buffer is
only applicable to B-tree secondary leaf pages in non-temporary
tablespaces, insert buffer merge is not necessary for all page types.
Using page_type, page_level, and tablespace type information from the page
that is read from disk, insert buffer merge is now skipped for
non-applicable page types.
[30 Aug 2016 9:58] Laurynas Biveinis
It might be beneficial to backport this to 5.6 for correctness too, see bug 82798