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

MDEV-27414 Server may hang when innodb_undo_log_truncate=ON

trx_purge_truncate_history(): Avoid a deadlock with
buf_pool_t::release_freed_page(). Page latches are not supposed
to be waited for while holding a mutex like buf_pool.mutex or
buf_pool.flush_list_mutex.

This regression was caused by
commit aaef2e1d (MDEV-27058).
Before that, trx_purge_truncate_history() would buffer-fix the block,
release buf_pool.flush_list_mutex, and then wait for the
exclusive page latch.

This bug led to occasional failures of the test
innodb.undo_truncate_recover.
parent 30b917d3
/*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2021, MariaDB Corporation.
Copyright (c) 2017, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -705,7 +705,16 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
{
auto block= reinterpret_cast<buf_block_t*>(bpage);
ut_ad(buf_pool.is_uncompressed(block));
bpage->lock.x_lock();
if (!bpage->lock.x_lock_try())
{
/* Let buf_pool_t::release_freed_page() proceed. */
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
std::this_thread::yield();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
rescan:
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
continue;
}
buf_pool.flush_hp.set(prev);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
......@@ -728,11 +737,8 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
}
if (prev != buf_pool.flush_hp.get())
{
/* Rescan, because we may have lost the position. */
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
continue;
}
goto rescan;
}
bpage= prev;
......
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