Commit 2db5f1b2 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-32049 Deadlock due to log_free_check() in trx_purge_truncate_history()

The function log_free_check() is not supposed to be invoked while
the caller is holding any InnoDB synchronization objects, such as
buffer page latches, tablespace latches, index tree latches, or
in this case, rseg->mutex (rseg->latch in 10.6 or later).

A hang was reported in 10.6 where several threads were waiting for
an rseg->latch that had been exclusively acquired in
trx_purge_truncate_history(), which invoked log_free_check() inside
trx_purge_truncate_rseg_history(). Because the threads that were
waiting for the rseg->latch were holding exclusive latches on some
index pages, log_free_check() was unable to advance the checkpoint
because those index pages could not be written out.

trx_purge_truncate_history(): Invoke log_free_check() before
acquiring the rseg->mutex and invoking trx_purge_free_segment().

trx_purge_free_segment(): Do not invoke log_free_check() in order
to avoid a deadlock.
parent 3c86765e
...@@ -346,7 +346,6 @@ static ...@@ -346,7 +346,6 @@ static
void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr)
{ {
mtr.commit(); mtr.commit();
log_free_check();
mtr.start(); mtr.start();
ut_ad(mutex_own(&rseg->mutex)); ut_ad(mutex_own(&rseg->mutex));
...@@ -376,7 +375,6 @@ void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) ...@@ -376,7 +375,6 @@ void trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr)
This does not matter 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. */ innodb_undo_log_truncate=ON will be able to reclaim the space. */
log_free_check();
mtr.start(); mtr.start();
ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__)); ut_ad(rw_lock_s_lock_nowait(block->debug_latch, __FILE__, __LINE__));
rw_lock_x_lock(&block->lock); rw_lock_x_lock(&block->lock);
...@@ -545,6 +543,7 @@ void trx_purge_truncate_history() ...@@ -545,6 +543,7 @@ void trx_purge_truncate_history()
{ {
ut_ad(rseg->id == i); ut_ad(rseg->id == i);
ut_ad(rseg->is_persistent()); ut_ad(rseg->is_persistent());
log_free_check();
mutex_enter(&rseg->mutex); mutex_enter(&rseg->mutex);
trx_purge_truncate_rseg_history(*rseg, head, trx_purge_truncate_rseg_history(*rseg, head,
!rseg->trx_ref_count && !rseg->trx_ref_count &&
......
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