• Marko Mäkelä's avatar
    MDEV-29383 Assertion mysql_mutex_assert_owner(&log_sys.flush_order_mutex) failed in mtr_t::commit() · 0fbcb0a2
    Marko Mäkelä authored
    In commit 0b47c126 (MDEV-13542)
    a few calls to mtr_t::memo_push() were moved before a write latch
    on the page was acquired. This introduced a race condition:
    
    1. is_block_dirtied() returned false to mtr_t::memo_push()
    2. buf_page_t::write_complete() was executed, the block marked clean,
    and a page latch released
    3. The page latch was acquired by the caller of mtr_t::memo_push(),
    and mtr_t::m_made_dirty was not set even though the block is in
    a clean state.
    
    The impact of this race condition is that crash recovery and backups
    may fail.
    
    btr_cur_latch_leaves(), btr_store_big_rec_extern_fields(),
    btr_free_externally_stored_field(), trx_purge_free_segment():
    Acquire the page latch before invoking mtr_t::memo_push().
    This fixes the regression caused by MDEV-13542.
    
    Side note: It would suffice to set mtr_t::m_made_dirty at the time
    we set the MTR_MEMO_MODIFY flag for a block. Currently that flag is
    unnecessarily set if a mini-transaction acquires a page latch on
    a page that is in a clean state, and will not actually modify the block.
    This may cause unnecessary acquisitions of log_sys.flush_order_mutex
    on mtr_t::commit().
    
    mtr_t::free(): If the block had been exclusively latched in this
    mini-transaction, set the m_made_dirty flag so that the flush order mutex
    will be acquired during mtr_t::commit(). This should have been part of
    commit 4179f93d (MDEV-18976).
    It was necessary to change mtr_t::free() so that
    WriteOPT_PAGE_CHECKSUM::operator() would be able to avoid writing
    checksums for freed pages.
    0fbcb0a2
btr0cur.cc 235 KB