Commit b5e43a1d authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-32552 Write-ahead logging is broken for freed pages

buf_page_free(): Flag the freed page as modified if it is found in
the buffer pool.

buf_flush_page(): If the page has been freed, ensure that the log
for it has been durably written, before removing the page
from buf_pool.flush_list.

FindBlockX: Find also MTR_MEMO_PAGE_X_MODIFY in order to avoid an
occasional failure of innodb.innodb_defrag_concurrent, which involves
freeing and reallocating pages in the same mini-transaction.

This fixes a regression that was introduced in
commit a35b4ae8 (MDEV-15528).

This logic was tested by commenting out the $shutdown_timeout line
from a test and running the following:

./mtr --rr innodb.scrub
rr replay var/log/mysqld.1.rr/mariadbd-0

A breakpoint in the modified buf_flush_page() was hit, and the
FIL_PAGE_LSN of that page had been last modified during the
mtr_t::commit() of a mini-transaction where buf_page_free()
had been executed on that page.
parent 85751ed8
...@@ -2324,6 +2324,7 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr, ...@@ -2324,6 +2324,7 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr,
mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
rw_lock_x_lock_inline(&block->lock, 0, file, line); rw_lock_x_lock_inline(&block->lock, 0, file, line);
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
mtr->set_modified(*block);
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
if (block->index) if (block->index)
......
...@@ -875,7 +875,18 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space) ...@@ -875,7 +875,18 @@ static bool buf_flush_page(buf_page_t *bpage, bool lru, fil_space_t *space)
page_t *frame= bpage->zip.data; page_t *frame= bpage->zip.data;
if (status == buf_page_t::FREED) if (status == buf_page_t::FREED)
{
if (UNIV_LIKELY(space->purpose == FIL_TYPE_TABLESPACE))
{
const lsn_t lsn= mach_read_from_8(my_assume_aligned<8>
(FIL_PAGE_LSN + (frame ? frame
: block->frame)));
ut_ad(lsn >= oldest_modification);
if (lsn > log_sys.get_flushed_lsn())
log_write_up_to(lsn, true);
}
buf_pool.release_freed_page(&block->page); buf_pool.release_freed_page(&block->page);
}
else else
{ {
space->reacquire(); space->reacquire();
......
...@@ -1027,7 +1027,8 @@ struct FindBlockX ...@@ -1027,7 +1027,8 @@ struct FindBlockX
/** @return whether the block was not found x-latched */ /** @return whether the block was not found x-latched */
bool operator()(const mtr_memo_slot_t *slot) const bool operator()(const mtr_memo_slot_t *slot) const
{ {
return slot->object != &block || slot->type != MTR_MEMO_PAGE_X_FIX; return slot->object != &block ||
(slot->type | MTR_MEMO_MODIFY) != MTR_MEMO_PAGE_X_MODIFY;
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment