• Marko Mäkelä's avatar
    MDEV-30638 Deadlock between INSERT and InnoDB non-persistent statistics update · 201cfc33
    Marko Mäkelä authored
    This is a partial revert of
    commit 8b6a308e (MDEV-29883)
    and a follow-up to the
    merge commit 394fc71f (MDEV-24569).
    
    The latching order related to any operation that accesses the allocation
    metadata of an InnoDB index tree is as follows:
    
    1. Acquire dict_index_t::lock in non-shared mode.
    2. Acquire the index root page latch in non-shared mode.
    3. Possibly acquire further index page latches. Unless an exclusive
    dict_index_t::lock is held, this must follow the root-to-leaf,
    left-to-right order.
    4. Acquire a *non-shared* fil_space_t::latch.
    5. Acquire latches on the allocation metadata pages.
    6. Possibly allocate and write some pages, or free some pages.
    
    btr_get_size_and_reserved(), dict_stats_update_transient_for_index(),
    dict_stats_analyze_index(): Acquire an exclusive fil_space_t::latch
    in order to avoid a deadlock in fseg_n_reserved_pages() in case of
    concurrent access to multiple indexes sharing the same "inode page".
    
    fseg_page_is_allocated(): Acquire an exclusive fil_space_t::latch
    in order to avoid deadlocks. All callers are holding latches
    on a buffer pool page, or an index, or both.
    Before commit edbde4a1 (MDEV-24167)
    a third mode was available that would not conflict with the shared
    fil_space_t::latch acquired by ha_innobase::info_low(),
    i_s_sys_tablespaces_fill_table(),
    or i_s_tablespaces_encryption_fill_table().
    Because those calls should be rather rare, it makes sense to use
    the simple rw_lock with only shared and exclusive modes.
    
    fil_crypt_get_page_throttle(): Avoid invoking fseg_page_is_allocated()
    on an allocation bitmap page (which can never be freed), to avoid
    acquiring a shared latch on top of an exclusive one.
    
    mtr_t::s_lock_space(), MTR_MEMO_SPACE_S_LOCK: Remove.
    201cfc33
mtr0mtr.cc 35.7 KB