diff options
author | Kristian Nielsen <knielsen@knielsen-hq.org> | 2016-09-20 15:30:57 +0200 |
---|---|---|
committer | Kristian Nielsen <knielsen@knielsen-hq.org> | 2016-10-14 22:44:40 +0200 |
commit | 50f19ca8099994e992e1b411c7c05287855a7bdd (patch) | |
tree | 7616768e8db48e1a83c8f20699e717731c7f741f /sql/slave.cc | |
parent | 7e0c9de86484815b6e014ce3ad3e3a9b74ec0ce0 (diff) | |
download | mariadb-git-50f19ca8099994e992e1b411c7c05287855a7bdd.tar.gz |
Remove unnecessary global mutex in parallel replication.
The function apply_event_and_update_pos() is called with the
rli->data_lock mutex held. However, there seems to be nothing in the
function actually needing the mutex to be held. Certainly not in the
parallel replication case, where sql_slave_skip_counter is always 0
since the non-zero case is handled by the SQL driver thread.
So this patch makes parallel replication use a variant of
apply_event_and_update_pos() without the need to take the
rli->data_lock mutex. This avoids one contended global mutex for each
event executed, which might improve performance on CPU-bound workloads
somewhat.
Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
Diffstat (limited to 'sql/slave.cc')
-rw-r--r-- | sql/slave.cc | 130 |
1 files changed, 92 insertions, 38 deletions
diff --git a/sql/slave.cc b/sql/slave.cc index 4981819577f..a55d26b1aa0 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3377,39 +3377,17 @@ has_temporary_error(THD *thd) } -/** - Applies the given event and advances the relay log position. - - In essence, this function does: - - @code - ev->apply_event(rli); - ev->update_pos(rli); - @endcode - - But it also does some maintainance, such as skipping events if - needed and reporting errors. - - If the @c skip flag is set, then it is tested whether the event - should be skipped, by looking at the slave_skip_counter and the - server id. The skip flag should be set when calling this from a - replication thread but not set when executing an explicit BINLOG - statement. - - @retval 0 OK. - - @retval 1 Error calling ev->apply_event(). +/* + First half of apply_event_and_update_pos(), see below. + Setup some THD variables for applying the event. - @retval 2 No error calling ev->apply_event(), but error calling - ev->update_pos(). + Split out so that it can run with rli->data_lock held in non-parallel + replication, but without the mutex held in the parallel case. */ -int apply_event_and_update_pos(Log_event* ev, THD* thd, - rpl_group_info *rgi, - rpl_parallel_thread *rpt) +static int +apply_event_and_update_pos_setup(Log_event* ev, THD* thd, rpl_group_info *rgi) { - int exec_res= 0; - Relay_log_info* rli= rgi->rli; - DBUG_ENTER("apply_event_and_update_pos"); + DBUG_ENTER("apply_event_and_update_pos_setup"); DBUG_PRINT("exec_event",("%s(type_code: %d; server_id: %d)", ev->get_type_str(), ev->get_type_code(), @@ -3459,13 +3437,23 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, (ev->flags & LOG_EVENT_SKIP_REPLICATION_F ? OPTION_SKIP_REPLICATION : 0); ev->thd = thd; // because up to this point, ev->thd == 0 - int reason= ev->shall_skip(rgi); - if (reason == Log_event::EVENT_SKIP_COUNT) - { - DBUG_ASSERT(rli->slave_skip_counter > 0); - rli->slave_skip_counter--; - } - mysql_mutex_unlock(&rli->data_lock); + DBUG_RETURN(ev->shall_skip(rgi)); +} + + +/* + Second half of apply_event_and_update_pos(), see below. + + Do the actual event apply (or skip), and position update. + */ +static int +apply_event_and_update_pos_apply(Log_event* ev, THD* thd, rpl_group_info *rgi, + int reason) +{ + int exec_res= 0; + Relay_log_info* rli= rgi->rli; + + DBUG_ENTER("apply_event_and_update_pos_apply"); DBUG_EXECUTE_IF("inject_slave_sql_before_apply_event", { DBUG_ASSERT(!debug_sync_set_action @@ -3554,6 +3542,72 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, /** + Applies the given event and advances the relay log position. + + In essence, this function does: + + @code + ev->apply_event(rli); + ev->update_pos(rli); + @endcode + + But it also does some maintainance, such as skipping events if + needed and reporting errors. + + If the @c skip flag is set, then it is tested whether the event + should be skipped, by looking at the slave_skip_counter and the + server id. The skip flag should be set when calling this from a + replication thread but not set when executing an explicit BINLOG + statement. + + @retval 0 OK. + + @retval 1 Error calling ev->apply_event(). + + @retval 2 No error calling ev->apply_event(), but error calling + ev->update_pos(). + + This function is only used in non-parallel replication, where it is called + with rli->data_lock held; this lock is released during this function. +*/ +int +apply_event_and_update_pos(Log_event* ev, THD* thd, rpl_group_info *rgi) +{ + Relay_log_info* rli= rgi->rli; + mysql_mutex_assert_owner(&rli->data_lock); + int reason= apply_event_and_update_pos_setup(ev, thd, rgi); + if (reason == Log_event::EVENT_SKIP_COUNT) + { + DBUG_ASSERT(rli->slave_skip_counter > 0); + rli->slave_skip_counter--; + } + mysql_mutex_unlock(&rli->data_lock); + return apply_event_and_update_pos_apply(ev, thd, rgi, reason); +} + + +/* + The version of above apply_event_and_update_pos() used in parallel + replication. Unlike the non-parallel case, this function is called without + rli->data_lock held. +*/ +int +apply_event_and_update_pos_for_parallel(Log_event* ev, THD* thd, + rpl_group_info *rgi) +{ + Relay_log_info* rli= rgi->rli; + mysql_mutex_assert_not_owner(&rli->data_lock); + int reason= apply_event_and_update_pos_setup(ev, thd, rgi); + /* + In parallel replication, sql_slave_skip_counter is handled in the SQL + driver thread, so 23 should never see EVENT_SKIP_COUNT here. + */ + DBUG_ASSERT(reason != Log_event::EVENT_SKIP_COUNT); + return apply_event_and_update_pos_apply(ev, thd, rgi, reason); +} + + +/** Keep the relay log transaction state up to date. The state reflects how things are after the given event, that has just been @@ -3803,7 +3857,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli, serial_rgi->future_event_relay_log_pos= rli->future_event_relay_log_pos; serial_rgi->event_relay_log_name= rli->event_relay_log_name; serial_rgi->event_relay_log_pos= rli->event_relay_log_pos; - exec_res= apply_event_and_update_pos(ev, thd, serial_rgi, NULL); + exec_res= apply_event_and_update_pos(ev, thd, serial_rgi); #ifdef WITH_WSREP WSREP_DEBUG("apply_event_and_update_pos() result: %d", exec_res); |