diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 0896d9c79a1f3..6109f7fb35824 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -269,7 +269,10 @@ class purge_sys_t /** A wrapper around ReadView::low_limit_no(). */ trx_id_t low_limit_no() const { - /* MDEV-22718 FIXME: We are not holding latch here! */ + /* Other callers than purge_coordinator_callback() must be holding + purge_sys.latch here. The purge coordinator task may call this + without holding any latch, because it is the only thread that may + modify purge_sys.view. */ return view.low_limit_no(); } /** A wrapper around trx_sys_t::clone_oldest_view(). */ diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index c0fafe1ec6b5e..b5d00d9624f10 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -110,7 +110,7 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() ut_ad(purge_sys.rseg->space->id == TRX_SYS_SPACE || srv_is_undo_tablespace(purge_sys.rseg->space->id)); - trx_id_t last_trx_no, tail_trx_no; + trx_id_t last_trx_no; { #ifdef SUX_LOCK_GENERIC purge_sys.rseg->latch.rd_lock(SRW_LOCK_CALL); @@ -119,9 +119,7 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() {purge_sys.rseg->latch}; #endif last_trx_no = purge_sys.rseg->last_trx_no(); - tail_trx_no = purge_sys.tail.trx_no; - purge_sys.tail.trx_no = last_trx_no; purge_sys.hdr_offset = purge_sys.rseg->last_offset(); purge_sys.hdr_page_no = purge_sys.rseg->last_page_no; @@ -130,11 +128,13 @@ TRANSACTIONAL_INLINE inline bool TrxUndoRsegsIterator::set_next() #endif } - /* Only the purge coordinator task will access - purge_sys.rseg_iter or purge_sys.hdr_page_no. */ + /* Only the purge coordinator task will access this object + purge_sys.rseg_iter, or any of purge_sys.hdr_page_no, + purge_sys.tail, purge_sys.head, or modify purge_sys.view. */ ut_ad(last_trx_no == m_rsegs.trx_no); ut_a(purge_sys.hdr_page_no != FIL_NULL); - ut_a(tail_trx_no <= last_trx_no); + ut_a(purge_sys.tail.trx_no <= last_trx_no); + purge_sys.tail.trx_no = last_trx_no; return(true); }