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

MDEV-32757 innodb_undo_log_truncate=ON is not crash safe

trx_purge_truncate_history(): Do not prematurely mark dirty pages
as clean. This will be done in mtr_t::commit_shrink() as part of
Shrink::operator()(mtr_memo_slot_t*). Also, register each dirty page
only once in the mini-transaction.

fsp_page_create(): Adjust and simplify the page creation during
undo tablespace truncation. We can directly reuse pages that are
already in buf_pool.page_hash.

This fixes a regression that was caused by
commit f5794e1d (MDEV-26445).

Tested by: Matthias Leich
Reviewed by: Thirunarayanan Balathandayuthapani
parent 15bb8acf
...@@ -1054,7 +1054,7 @@ static ...@@ -1054,7 +1054,7 @@ static
buf_block_t* buf_block_t*
fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr) fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr)
{ {
buf_block_t *block, *free_block; buf_block_t *block;
if (UNIV_UNLIKELY(space->is_being_truncated)) if (UNIV_UNLIKELY(space->is_being_truncated))
{ {
...@@ -1063,26 +1063,48 @@ fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr) ...@@ -1063,26 +1063,48 @@ fsp_page_create(fil_space_t *space, page_no_t offset, mtr_t *mtr)
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
block= reinterpret_cast<buf_block_t*> block= reinterpret_cast<buf_block_t*>
(buf_pool.page_hash_get_low(page_id, fold)); (buf_pool.page_hash_get_low(page_id, fold));
if (block && block->page.oldest_modification() <= 1) if (!block)
block= nullptr; {
mysql_mutex_unlock(&buf_pool.mutex);
goto create;
}
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_unlock(&buf_pool.mutex);
if (block) ut_ad(block->page.state() == BUF_BLOCK_FILE_PAGE);
ut_ad(!block->page.ibuf_exist);
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index);
#endif
if (mtr->have_x_latch(*block))
{ {
buf_block_buf_fix_dec(block);
ut_ad(block->page.buf_fix_count() >= 1); ut_ad(block->page.buf_fix_count() >= 1);
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
ut_ad(mtr->have_x_latch(*block)); }
free_block= block; else
goto got_free_block; {
rw_lock_x_lock(&block->lock);
if (UNIV_UNLIKELY(block->page.id() != page_id))
{
buf_block_buf_fix_dec(block);
rw_lock_x_unlock(&block->lock);
goto create;
}
mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
} }
} }
else
free_block= buf_LRU_get_free_block(false); {
got_free_block: create:
block= buf_page_create(space, static_cast<uint32_t>(offset), buf_block_t *free_block= buf_LRU_get_free_block(false);
space->zip_size(), mtr, free_block); block= buf_page_create(space, static_cast<uint32_t>(offset),
if (UNIV_UNLIKELY(block != free_block)) space->zip_size(), mtr, free_block);
buf_pool.free_block(free_block); if (UNIV_UNLIKELY(block != free_block))
buf_pool.free_block(free_block);
}
fsp_init_file_page(space, block, mtr); fsp_init_file_page(space, block, mtr);
return block; return block;
......
...@@ -659,13 +659,12 @@ void trx_purge_truncate_history() ...@@ -659,13 +659,12 @@ void trx_purge_truncate_history()
buf_page_t *prev= UT_LIST_GET_PREV(list, bpage); buf_page_t *prev= UT_LIST_GET_PREV(list, bpage);
if (bpage->id().space() == space.id && if (bpage->oldest_modification() > 2 &&
bpage->oldest_modification() != 1) bpage->id().space() == space.id)
{ {
ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE); ut_ad(bpage->state() == BUF_BLOCK_FILE_PAGE);
auto block= reinterpret_cast<buf_block_t*>(bpage); auto block= reinterpret_cast<buf_block_t*>(bpage);
block->fix(); buf_block_buf_fix_inc(block, __FILE__, __LINE__);
ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__));
buf_pool.flush_hp.set(prev); buf_pool.flush_hp.set(prev);
mysql_mutex_unlock(&buf_pool.flush_list_mutex); mysql_mutex_unlock(&buf_pool.flush_list_mutex);
...@@ -676,15 +675,13 @@ void trx_purge_truncate_history() ...@@ -676,15 +675,13 @@ void trx_purge_truncate_history()
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
ut_ad(bpage->io_fix() == BUF_IO_NONE); ut_ad(bpage->io_fix() == BUF_IO_NONE);
if (bpage->oldest_modification() > 1) if (bpage->oldest_modification() > 2 &&
{ !mtr.have_x_latch(*reinterpret_cast<buf_block_t*>(bpage)))
bpage->clear_oldest_modification(false);
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
}
else else
{ {
buf_block_buf_fix_dec(block);
rw_lock_x_unlock(&block->lock); rw_lock_x_unlock(&block->lock);
block->unfix();
} }
if (prev != buf_pool.flush_hp.get()) if (prev != buf_pool.flush_hp.get())
......
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