mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
MDEV-7882: Excessive transaction retry in parallel replication
When a transaction in parallel replication needs to retry (eg. because of deadlock kill), first wait for all prior transactions to commit before doing the retry. This way, we avoid the retry once again conflicting with a prior transaction, requiring yet another retry. Without this patch, we saw "in the wild" that transactions had to be retried more than 10 times to succeed, which exceeds the default --slave_transaction_retries value and is in any case undesirable. (We already do this in 10.1 in "optimistic" parallel replication mode; this patch just makes the code use the same logic for "conservative" mode (only mode in 10.0)).
This commit is contained in:
parent
fb71449b10
commit
a4082918c8
1 changed files with 28 additions and 3 deletions
|
@ -372,10 +372,35 @@ do_retry:
|
||||||
statistic_increment(slave_retried_transactions, LOCK_status);
|
statistic_increment(slave_retried_transactions, LOCK_status);
|
||||||
mysql_mutex_unlock(&rli->data_lock);
|
mysql_mutex_unlock(&rli->data_lock);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
mysql_mutex_lock(&entry->LOCK_parallel_entry);
|
mysql_mutex_lock(&entry->LOCK_parallel_entry);
|
||||||
register_wait_for_prior_event_group_commit(rgi, entry);
|
register_wait_for_prior_event_group_commit(rgi, entry);
|
||||||
mysql_mutex_unlock(&entry->LOCK_parallel_entry);
|
mysql_mutex_unlock(&entry->LOCK_parallel_entry);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Let us wait for all prior transactions to complete before trying again.
|
||||||
|
This way, we avoid repeatedly conflicting with and getting deadlock
|
||||||
|
killed by the same earlier transaction.
|
||||||
|
*/
|
||||||
|
if (!(err= thd->wait_for_prior_commit()))
|
||||||
|
break;
|
||||||
|
|
||||||
|
convert_kill_to_deadlock_error(rgi);
|
||||||
|
if (!has_temporary_error(thd))
|
||||||
|
goto err;
|
||||||
|
/*
|
||||||
|
If we get a temporary error such as a deadlock kill, we can safely
|
||||||
|
ignore it, as we already rolled back.
|
||||||
|
|
||||||
|
But we still want to retry the wait for the prior transaction to
|
||||||
|
complete its commit.
|
||||||
|
*/
|
||||||
|
thd->clear_error();
|
||||||
|
if(thd->wait_for_commit_ptr)
|
||||||
|
thd->wait_for_commit_ptr->unregister_wait_for_prior_commit();
|
||||||
|
}
|
||||||
|
|
||||||
strmake_buf(log_name, ir->name);
|
strmake_buf(log_name, ir->name);
|
||||||
if ((fd= open_binlog(&rlog, log_name, &errmsg)) <0)
|
if ((fd= open_binlog(&rlog, log_name, &errmsg)) <0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue