• unknown's avatar
    MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel · 629b8229
    unknown authored
    replication causing replication to fail.
    
    In parallel replication, we run transactions from the master in parallel, but
    force them to commit in the same order they did on the master. If we force T1
    to commit before T2, but T2 holds eg. a row lock that is needed by T1, we get
    a deadlock when T2 waits until T1 has committed.
    
    Usually, we do not run T1 and T2 in parallel if there is a chance that they
    can have conflicting locks like this, but there are certain edge cases where
    it can occasionally happen (eg. MDEV-5914, MDEV-5941, MDEV-6020). The bug was
    that this would cause replication to hang, eventually getting a lock timeout
    and causing the slave to stop with error.
    
    With this patch, InnoDB will report back to the upper layer whenever a
    transactions T1 is about to do a lock wait on T2. If T1 and T2 are parallel
    replication transactions, and T2 needs to commit later than T1, we can thus
    detect the deadlock; we then kill T2, setting a flag that causes it to catch
    the kill and convert it to a deadlock error; this error will then cause T2 to
    roll back and release its locks (so that T1 can commit), and later T2 will be
    re-tried and eventually also committed.
    
    The kill happens asynchroneously in a slave background thread; this is
    necessary, as the reporting from InnoDB about lock waits happen deep inside
    the locking code, at a point where it is not possible to directly call
    THD::awake() due to mutexes held.
    
    Deadlock is assumed to be (very) rarely occuring, so this patch tries to
    minimise the performance impact on the normal case where no deadlocks occur,
    rather than optimise the handling of the occasional deadlock.
    
    Also fix transaction retry due to deadlock when it happens after a transaction
    already signalled to later transactions that it started to commit. In this
    case we need to undo this signalling (and later redo it when we commit again
    during retry), so following transactions will not start too early.
    
    Also add a missing thd->send_kill_message() that got triggered during testing
    (this corrects an incorrect fix for MySQL Bug#58933).
    629b8229
log.cc 286 KB