mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-23586 Mariabackup: GTID saved for replication in 10.4.14 is wrong
MDEV-21953 deadlock between BACKUP STAGE BLOCK_COMMIT and parallel replication Fixed by partly reverting MDEV-21953 to put back MDL_BACKUP_COMMIT locking before log_and_order. The original problem for MDEV-21953 was that while a thread was waiting in for another threads to commit in 'log_and_order', it had the MDL_BACKUP_COMMIT lock. The backup thread was waiting to get the MDL_BACKUP_WAIT_COMMIT lock, which blocks all new MDL_BACKUP_COMMIT locks. This causes a deadlock as the waited-for thread can never get past the MDL_BACKUP_COMMIT lock in ha_commit_trans. The main part of the bug fix is to release the MDL_BACKUP_COMMIT lock while a thread is waiting for other 'previous' threads to commit. This ensures that no transactional thread keeps MDL_BACKUP_COMMIT while waiting, which ensures that there are no deadlocks anymore.
This commit is contained in:
@ -1271,6 +1271,7 @@ void THD::init()
|
||||
first_successful_insert_id_in_prev_stmt_for_binlog= 0;
|
||||
first_successful_insert_id_in_cur_stmt= 0;
|
||||
current_backup_stage= BACKUP_FINISHED;
|
||||
backup_commit_lock= 0;
|
||||
#ifdef WITH_WSREP
|
||||
wsrep_last_query_id= 0;
|
||||
wsrep_xid.null();
|
||||
@ -1383,7 +1384,7 @@ void THD::init_for_queries()
|
||||
set_time();
|
||||
/*
|
||||
We don't need to call ha_enable_transaction() as we can't have
|
||||
any active transactions that has to be commited
|
||||
any active transactions that has to be committed
|
||||
*/
|
||||
transaction.on= TRUE;
|
||||
|
||||
@ -7386,16 +7387,33 @@ wait_for_commit::register_wait_for_prior_commit(wait_for_commit *waitee)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Wait for commit of another transaction to complete, as already registered
|
||||
/**
|
||||
Waits for commit of another transaction to complete, as already registered
|
||||
with register_wait_for_prior_commit(). If the commit already completed,
|
||||
returns immediately.
|
||||
|
||||
If thd->backup_commit_lock is set, release it while waiting for other threads
|
||||
*/
|
||||
|
||||
int
|
||||
wait_for_commit::wait_for_prior_commit2(THD *thd)
|
||||
{
|
||||
PSI_stage_info old_stage;
|
||||
wait_for_commit *loc_waitee;
|
||||
bool backup_lock_released= 0;
|
||||
|
||||
/*
|
||||
Release MDL_BACKUP_COMMIT LOCK while waiting for other threads to commit
|
||||
This is needed to avoid deadlock between the other threads (which not
|
||||
yet have the MDL_BACKUP_COMMIT_LOCK) and any threads using
|
||||
BACKUP LOCK BLOCK_COMMIT.
|
||||
*/
|
||||
if (thd->backup_commit_lock && thd->backup_commit_lock->ticket)
|
||||
{
|
||||
backup_lock_released= 1;
|
||||
thd->mdl_context.release_lock(thd->backup_commit_lock->ticket);
|
||||
thd->backup_commit_lock->ticket= 0;
|
||||
}
|
||||
|
||||
mysql_mutex_lock(&LOCK_wait_commit);
|
||||
DEBUG_SYNC(thd, "wait_for_prior_commit_waiting");
|
||||
@ -7445,10 +7463,16 @@ wait_for_commit::wait_for_prior_commit2(THD *thd)
|
||||
use within enter_cond/exit_cond.
|
||||
*/
|
||||
DEBUG_SYNC(thd, "wait_for_prior_commit_killed");
|
||||
if (backup_lock_released)
|
||||
thd->mdl_context.acquire_lock(thd->backup_commit_lock,
|
||||
thd->variables.lock_wait_timeout);
|
||||
return wakeup_error;
|
||||
|
||||
end:
|
||||
thd->EXIT_COND(&old_stage);
|
||||
if (backup_lock_released)
|
||||
thd->mdl_context.acquire_lock(thd->backup_commit_lock,
|
||||
thd->variables.lock_wait_timeout);
|
||||
return wakeup_error;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user