1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge MDEV-7847 and MDEV-7882 into 10.0.

Conflicts:
	mysql-test/suite/rpl/r/rpl_parallel.result
	sql/rpl_parallel.cc
This commit is contained in:
Kristian Nielsen
2015-03-30 15:10:29 +02:00
5 changed files with 518 additions and 21 deletions

View File

@@ -112,6 +112,7 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id,
wait_for_commit *wfc= &rgi->commit_orderer;
int err;
thd->get_stmt_da()->set_overwrite_status(true);
/*
Remove any left-over registration to wait for a prior commit to
complete. Normally, such wait would already have been removed at
@@ -128,14 +129,14 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id,
for us to complete and rely on this also ensuring that any other
event in the group has completed.
But in the error case, we have to abort anyway, and it seems best
to just complete as quickly as possible with unregister. Anyone
waiting for us will in any case receive the error back from their
wait_for_prior_commit() call.
And in the error case, correct GCO lifetime relies on the fact that once
the last event group in the GCO has executed wait_for_prior_commit(),
all earlier event groups have also committed; this way no more
mark_start_commit() calls can be made and it is safe to de-allocate
the GCO.
*/
if (rgi->worker_error)
wfc->unregister_wait_for_prior_commit();
else if ((err= wfc->wait_for_prior_commit(thd)))
err= wfc->wait_for_prior_commit(thd);
if (unlikely(err) && !rgi->worker_error)
signal_error_to_sql_driver_thread(thd, rgi, err);
thd->wait_for_commit_ptr= NULL;
@@ -192,6 +193,10 @@ finish_event_group(rpl_parallel_thread *rpt, uint64 sub_id,
thd->clear_error();
thd->reset_killed();
/*
Would do thd->get_stmt_da()->set_overwrite_status(false) here, but
reset_diagnostics_area() already does that.
*/
thd->get_stmt_da()->reset_diagnostics_area();
wfc->wakeup_subsequent_commits(rgi->worker_error);
}
@@ -385,16 +390,10 @@ do_retry:
register_wait_for_prior_event_group_commit(rgi, entry);
mysql_mutex_unlock(&entry->LOCK_parallel_entry);
if (rgi->speculation != rpl_group_info::SPECULATE_OPTIMISTIC)
break;
/*
We speculatively tried to run this in parallel with prior event groups,
but it did not work for some reason.
So let us wait for all prior transactions to complete before trying
again. This way, we avoid repeatedly retrying and failing a small
transaction that conflicts with a prior long-running one.
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()))
{
@@ -800,8 +799,7 @@ handle_rpl_parallel_thread(void *arg)
if (unlikely(entry->stop_on_error_sub_id <= rgi->wait_commit_sub_id))
skip_event_group= true;
else
register_wait_for_prior_event_group_commit(rgi, entry);
register_wait_for_prior_event_group_commit(rgi, entry);
unlock_or_exit_cond(thd, &entry->LOCK_parallel_entry,
&did_enter_cond, &old_stage);
@@ -888,7 +886,9 @@ handle_rpl_parallel_thread(void *arg)
else
{
delete qev->ev;
thd->get_stmt_da()->set_overwrite_status(true);
err= thd->wait_for_prior_commit();
thd->get_stmt_da()->set_overwrite_status(false);
}
end_of_group=