summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-04-21 11:05:44 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2023-04-28 16:27:04 +0300
commitbc63505506665ce067528722fcee3f828b840756 (patch)
tree056450386103bc0eea188c558fdbf661b339a06c
parent84bb01b1d6eea76172f217d57bc9b611514a0815 (diff)
downloadmariadb-git-bb-10.5.19-undo_truncate.tar.gz
MDEV-30753 fixup: Unsafe buffer page restorationbb-10.5.19-undo_truncate
trx_purge_free_segment(): The buffer-fix only prevents a block from being freed completely from the buffer pool, but it will not prevent the block from being evicted. Recheck the page identifier after acquiring an exclusive page latch. If it has changed, backtrack and invoke buf_page_get_gen() to look up the page normally.
-rw-r--r--storage/innobase/trx/trx0purge.cc15
1 files changed, 13 insertions, 2 deletions
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index 38438108480..b22a85f4646 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -367,19 +367,30 @@ void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr)
block->frame, &mtr))
{
block->fix();
+ const page_id_t id{block->page.id()};
mtr.commit();
/* NOTE: If the server is killed after the log that was produced
up to this point was written, and before the log from the mtr.commit()
in our caller is written, then the pages belonging to the
undo log will become unaccessible garbage.
- This does not matters when using multiple innodb_undo_tablespaces;
+ This does not matter when using multiple innodb_undo_tablespaces;
innodb_undo_log_truncate=ON will be able to reclaim the space. */
log_free_check();
mtr.start();
ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__));
rw_lock_x_lock(&block->lock);
- mtr_memo_push(&mtr, block, MTR_MEMO_PAGE_X_FIX);
+ if (UNIV_UNLIKELY(block->page.id() != id))
+ {
+ block->unfix();
+ rw_lock_x_unlock(&block->lock);
+ ut_d(rw_lock_s_unlock(block->debug_latch));
+ block= buf_page_get(id, 0, RW_X_LATCH, &mtr);
+ if (!block)
+ return;
+ }
+ else
+ mtr_memo_push(&mtr, block, MTR_MEMO_PAGE_X_FIX);
}
while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +