Skip to content

Commit c410f7a

Browse files
committed
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 aaef2e1 (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.
1 parent 30b917d commit c410f7a

File tree

1 file changed

+12
-6
lines changed

1 file changed

+12
-6
lines changed

Diff for: storage/innobase/trx/trx0purge.cc

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2017, 2021, MariaDB Corporation.
4+
Copyright (c) 2017, 2022, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
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()
705705
{
706706
auto block= reinterpret_cast<buf_block_t*>(bpage);
707707
ut_ad(buf_pool.is_uncompressed(block));
708-
bpage->lock.x_lock();
708+
if (!bpage->lock.x_lock_try())
709+
{
710+
/* Let buf_pool_t::release_freed_page() proceed. */
711+
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
712+
std::this_thread::yield();
713+
mysql_mutex_lock(&buf_pool.flush_list_mutex);
714+
rescan:
715+
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
716+
continue;
717+
}
709718
buf_pool.flush_hp.set(prev);
710719
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
711720

@@ -728,11 +737,8 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
728737
}
729738

730739
if (prev != buf_pool.flush_hp.get())
731-
{
732740
/* Rescan, because we may have lost the position. */
733-
bpage= UT_LIST_GET_LAST(buf_pool.flush_list);
734-
continue;
735-
}
741+
goto rescan;
736742
}
737743

738744
bpage= prev;

0 commit comments

Comments
 (0)