• sjaakola's avatar
    MDEV-23328 Server hang due to Galera lock conflict resolution · db50ea3a
    sjaakola authored
    Mutex order violation when wsrep bf thread kills a conflicting trx,
    the stack is
    
              wsrep_thd_LOCK()
              wsrep_kill_victim()
              lock_rec_other_has_conflicting()
              lock_clust_rec_read_check_and_lock()
              row_search_mvcc()
              ha_innobase::index_read()
              ha_innobase::rnd_pos()
              handler::ha_rnd_pos()
              handler::rnd_pos_by_record()
              handler::ha_rnd_pos_by_record()
              Rows_log_event::find_row()
              Update_rows_log_event::do_exec_row()
              Rows_log_event::do_apply_event()
              Log_event::apply_event()
              wsrep_apply_events()
    
    and mutexes are taken in the order
    
              lock_sys->mutex -> victim_trx->mutex -> victim_thread->LOCK_thd_data
    
    When a normal KILL statement is executed, the stack is
    
              innobase_kill_query()
              kill_handlerton()
              plugin_foreach_with_mask()
              ha_kill_query()
              THD::awake()
              kill_one_thread()
    
            and mutexes are
    
              victim_thread->LOCK_thd_data -> lock_sys->mutex -> victim_trx->mutex
    
    This patch is the plan D variant for fixing potetial mutex locking
    order exercised by BF aborting and KILL command execution.
    
    In this approach, KILL command is replicated as TOI operation.
    This guarantees total isolation for the KILL command execution
    in the first node: there is no concurrent replication applying
    and no concurrent DDL executing. Therefore there is no risk of
    BF aborting to happen in parallel with KILL command execution
    either. Potential mutex deadlocks between the different mutex
    access paths with KILL command execution and BF aborting cannot
    therefore happen.
    
    TOI replication is used, in this approach,  purely as means
    to provide isolated KILL command execution in the first node.
    KILL command should not (and must not) be applied in secondary
    nodes. In this patch, we make this sure by skipping KILL
    execution in secondary nodes, in applying phase, where we
    bail out if applier thread is trying to execute KILL command.
    This is effective, but skipping the applying of KILL command
    could happen much earlier as well.
    
    This also fixed unprotected calls to wsrep_thd_abort
    that will use wsrep_abort_transaction. This is fixed
    by holding THD::LOCK_thd_data while we abort transaction.
    Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
    db50ea3a
wsrep_mysqld.cc 87.4 KB