From 4a5be2e94e749c26121395d2a4509dc60a856c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 7 May 2020 17:57:03 +0300 Subject: [PATCH] MDEV-22495 Assertion ...status != buf_page_t::FREED in ibuf_read_merge_pages() ibuf_read_merge_pages(): Request a possibly freed page. The change buffer is discarded lazily for freed pages either by this function or when buf_page_create() reuses a page. buf_page_get_low(): Relax a debug assertion. Do not attempt change buffer merge on freed pages. ibuf_merge_or_delete_for_page(): Assert that the page state is NORMAL. INIT_ON_FLUSH is not possible, because in that case buf_page_create() should have removed any buffered changes for the page. buf_page_get_gen(): Apply buffered changes also in the case when we can avoid reading the page based on buffered redo log records. This addresses a hard-to-reproduce scenario that was broken in commit 6697135c6d03935118c3dfa1c97faea7fa76afa6. --- storage/innobase/buf/buf0buf.cc | 24 ++++++++++++++++++++++-- storage/innobase/ibuf/ibuf0ibuf.cc | 7 ++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 118083db5a8..66955daa7e7 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3298,6 +3298,7 @@ buf_page_get_low( || (rw_latch == RW_NO_LATCH)); ut_ad(!allow_ibuf_merge || mode == BUF_GET + || mode == BUF_GET_POSSIBLY_FREED || mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH); @@ -3907,7 +3908,8 @@ evict_from_pool: return NULL; } - if (allow_ibuf_merge + if (fix_block->page.status != buf_page_t::FREED + && allow_ibuf_merge && fil_page_get_type(fix_block->frame) == FIL_PAGE_INDEX && page_is_leaf(fix_block->frame)) { rw_lock_x_lock_inline(&fix_block->lock, 0, file, line); @@ -3974,9 +3976,27 @@ buf_page_get_gen( { block->fix(); ut_ad(rw_lock_s_lock_nowait(block->debug_latch, file, line)); - block= buf_page_mtr_lock(block, rw_latch, mtr, file, line); if (err) *err= DB_SUCCESS; + const bool must_merge= allow_ibuf_merge && + ibuf_page_exists(page_id, block->zip_size()); + if (block->page.status == buf_page_t::FREED) + ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL); + else if (must_merge && fil_page_get_type(block->frame) == FIL_PAGE_INDEX && + page_is_leaf(block->frame)) + { + rw_lock_x_lock_inline(&block->lock, 0, file, line); + block->page.ibuf_exist= false; + ibuf_merge_or_delete_for_page(block, page_id, block->zip_size(), true); + + if (rw_latch == RW_X_LATCH) + { + mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); + return block; + } + rw_lock_x_unlock(&block->lock); + } + block= buf_page_mtr_lock(block, rw_latch, mtr, file, line); return block; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 442768e6a2c..790305c86d2 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -2325,8 +2325,8 @@ tablespace_deleted: mtr.start(); dberr_t err; buf_page_get_gen(page_id_t(space_id, page_nos[i]), - zip_size, - RW_X_LATCH, NULL, BUF_GET, + zip_size, RW_X_LATCH, nullptr, + BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err, true); mtr.commit(); if (err == DB_TABLESPACE_DELETED) { @@ -4221,8 +4221,9 @@ ibuf_merge_or_delete_for_page( ulint mops[IBUF_OP_COUNT]; ulint dops[IBUF_OP_COUNT]; - ut_ad(block == NULL || page_id == block->page.id); + ut_ad(!block || page_id == block->page.id); ut_ad(!block || buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(!block || block->page.status == buf_page_t::NORMAL); if (trx_sys_hdr_page(page_id) || fsp_is_system_temporary(page_id.space())) {