mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-4506: Parallel replication.
Fix some more parts of old-style position updates. Now we save in rgi some coordinates for master log and relay log, so that in do_update_pos() we can use the right set of coordinates with the right events. The Rotate_log_event::do_update_pos() is fixed in the parallel case to not directly update relay-log.info (as Rotate event runs directly in the driver SQL thread, ahead of actual event execution). Instead, group_master_log_file is updated as part of do_update_pos() in each event execution. In the parallel case, position updates happen in parallel without any ordering, but taking care that position is not updated backwards. Since position update happens only after event execution this leads to the right result. Also fix an access-after-free introduced in an earlier commit.
This commit is contained in:
@ -3843,17 +3843,6 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
|
|||||||
thd->variables.auto_increment_increment= auto_increment_increment;
|
thd->variables.auto_increment_increment= auto_increment_increment;
|
||||||
thd->variables.auto_increment_offset= auto_increment_offset;
|
thd->variables.auto_increment_offset= auto_increment_offset;
|
||||||
|
|
||||||
/*
|
|
||||||
InnoDB internally stores the master log position it has executed so far,
|
|
||||||
i.e. the position just after the COMMIT event.
|
|
||||||
When InnoDB will want to store, the positions in rli won't have
|
|
||||||
been updated yet, so group_master_log_* will point to old BEGIN
|
|
||||||
and event_master_log* will point to the beginning of current COMMIT.
|
|
||||||
But log_pos of the COMMIT Query event is what we want, i.e. the pos of the
|
|
||||||
END of the current log event (COMMIT). We save it in rli so that InnoDB can
|
|
||||||
access it.
|
|
||||||
*/
|
|
||||||
const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
|
|
||||||
DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
|
DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
|
||||||
|
|
||||||
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
|
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
|
||||||
@ -3882,7 +3871,6 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
|
|||||||
invariants like IN_STMT flag must be off at committing the transaction.
|
invariants like IN_STMT flag must be off at committing the transaction.
|
||||||
*/
|
*/
|
||||||
rgi->inc_event_relay_log_pos();
|
rgi->inc_event_relay_log_pos();
|
||||||
const_cast<Relay_log_info*>(rli)->clear_flag(Relay_log_info::IN_STMT);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -5535,16 +5523,6 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi,
|
|||||||
thd->lex->local_file= local_fname;
|
thd->lex->local_file= local_fname;
|
||||||
mysql_reset_thd_for_next_command(thd, 0);
|
mysql_reset_thd_for_next_command(thd, 0);
|
||||||
|
|
||||||
if (!use_rli_only_for_errors)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Saved for InnoDB, see comment in
|
|
||||||
Query_log_event::do_apply_event()
|
|
||||||
*/
|
|
||||||
const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
|
|
||||||
DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We test replicate_*_db rules. Note that we have already prepared
|
We test replicate_*_db rules. Note that we have already prepared
|
||||||
the file to load, even if we are going to ignore and delete it
|
the file to load, even if we are going to ignore and delete it
|
||||||
@ -5940,11 +5918,16 @@ int Rotate_log_event::do_update_pos(rpl_group_info *rgi)
|
|||||||
correspond to the beginning of the transaction. Starting from
|
correspond to the beginning of the transaction. Starting from
|
||||||
5.0.0, there also are some rotates from the slave itself, in the
|
5.0.0, there also are some rotates from the slave itself, in the
|
||||||
relay log, which shall not change the group positions.
|
relay log, which shall not change the group positions.
|
||||||
|
|
||||||
|
In parallel replication, rotate event is executed out-of-band with normal
|
||||||
|
events, so we cannot update group_master_log_name or _pos here, it will
|
||||||
|
be updated with the next normal event instead.
|
||||||
*/
|
*/
|
||||||
if ((server_id != global_system_variables.server_id ||
|
if ((server_id != global_system_variables.server_id ||
|
||||||
rli->replicate_same_server_id) &&
|
rli->replicate_same_server_id) &&
|
||||||
!is_relay_log_event() &&
|
!is_relay_log_event() &&
|
||||||
!rli->is_in_group())
|
!rli->is_in_group() &&
|
||||||
|
!rgi->is_parallel_exec)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&rli->data_lock);
|
mysql_mutex_lock(&rli->data_lock);
|
||||||
DBUG_PRINT("info", ("old group_master_log_name: '%s' "
|
DBUG_PRINT("info", ("old group_master_log_name: '%s' "
|
||||||
@ -7712,7 +7695,7 @@ int Stop_log_event::do_update_pos(rpl_group_info *rgi)
|
|||||||
*/
|
*/
|
||||||
if (rli->get_flag(Relay_log_info::IN_TRANSACTION))
|
if (rli->get_flag(Relay_log_info::IN_TRANSACTION))
|
||||||
rgi->inc_event_relay_log_pos();
|
rgi->inc_event_relay_log_pos();
|
||||||
else
|
else if (!rgi->is_parallel_exec)
|
||||||
{
|
{
|
||||||
rpl_global_gtid_slave_state.record_and_update_gtid(thd, rgi);
|
rpl_global_gtid_slave_state.record_and_update_gtid(thd, rgi);
|
||||||
rli->inc_group_relay_log_pos(0, rgi);
|
rli->inc_group_relay_log_pos(0, rgi);
|
||||||
@ -8408,7 +8391,6 @@ int Execute_load_log_event::do_apply_event(rpl_group_info *rgi)
|
|||||||
calls mysql_load()).
|
calls mysql_load()).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const_cast<Relay_log_info*>(rli)->future_group_master_log_pos= log_pos;
|
|
||||||
if (lev->do_apply_event(0,rgi,1))
|
if (lev->do_apply_event(0,rgi,1))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -64,7 +64,11 @@ rpt_handle_event(rpl_parallel_thread::queued_event *qev,
|
|||||||
/* ToDo: Access to thd, and what about rli, split out a parallel part? */
|
/* ToDo: Access to thd, and what about rli, split out a parallel part? */
|
||||||
mysql_mutex_lock(&rli->data_lock);
|
mysql_mutex_lock(&rli->data_lock);
|
||||||
qev->ev->thd= thd;
|
qev->ev->thd= thd;
|
||||||
|
strcpy(rgi->event_relay_log_name_buf, qev->event_relay_log_name);
|
||||||
|
rgi->event_relay_log_name= rgi->event_relay_log_name_buf;
|
||||||
|
rgi->event_relay_log_pos= qev->event_relay_log_pos;
|
||||||
rgi->future_event_relay_log_pos= qev->future_event_relay_log_pos;
|
rgi->future_event_relay_log_pos= qev->future_event_relay_log_pos;
|
||||||
|
strcpy(rgi->future_event_master_log_name, qev->future_event_master_log_name);
|
||||||
err= apply_event_and_update_pos(qev->ev, thd, rgi, rpt);
|
err= apply_event_and_update_pos(qev->ev, thd, rgi, rpt);
|
||||||
thd->rgi_slave= NULL;
|
thd->rgi_slave= NULL;
|
||||||
|
|
||||||
@ -660,7 +664,10 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev)
|
|||||||
}
|
}
|
||||||
qev->ev= ev;
|
qev->ev= ev;
|
||||||
qev->next= NULL;
|
qev->next= NULL;
|
||||||
|
strcpy(qev->event_relay_log_name, rli->event_relay_log_name);
|
||||||
|
qev->event_relay_log_pos= rli->event_relay_log_pos;
|
||||||
qev->future_event_relay_log_pos= rli->future_event_relay_log_pos;
|
qev->future_event_relay_log_pos= rli->future_event_relay_log_pos;
|
||||||
|
strcpy(qev->future_event_master_log_name, rli->future_event_master_log_name);
|
||||||
|
|
||||||
if (typ == GTID_EVENT)
|
if (typ == GTID_EVENT)
|
||||||
{
|
{
|
||||||
@ -674,6 +681,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev)
|
|||||||
delete rgi;
|
delete rgi;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
rgi->is_parallel_exec = true;
|
||||||
if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()))
|
if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()))
|
||||||
rgi->deferred_events= new Deferred_log_events(rli);
|
rgi->deferred_events= new Deferred_log_events(rli);
|
||||||
|
|
||||||
@ -783,6 +791,14 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev)
|
|||||||
have GTID, like a MariaDB 5.5 or MySQL master.
|
have GTID, like a MariaDB 5.5 or MySQL master.
|
||||||
*/
|
*/
|
||||||
qev->rgi= serial_rgi;
|
qev->rgi= serial_rgi;
|
||||||
|
/* Handle master log name change, seen in Rotate_log_event. */
|
||||||
|
if (typ == ROTATE_EVENT)
|
||||||
|
{
|
||||||
|
Rotate_log_event *rev= static_cast<Rotate_log_event *>(qev->ev);
|
||||||
|
memcpy(rli->future_event_master_log_name,
|
||||||
|
rev->new_log_ident, rev->ident_len+1);
|
||||||
|
}
|
||||||
|
|
||||||
rpt_handle_event(qev, NULL);
|
rpt_handle_event(qev, NULL);
|
||||||
delete_or_keep_event_post_apply(serial_rgi, typ, qev->ev);
|
delete_or_keep_event_post_apply(serial_rgi, typ, qev->ev);
|
||||||
my_free(qev);
|
my_free(qev);
|
||||||
|
@ -24,6 +24,9 @@ struct rpl_parallel_thread {
|
|||||||
Log_event *ev;
|
Log_event *ev;
|
||||||
rpl_group_info *rgi;
|
rpl_group_info *rgi;
|
||||||
ulonglong future_event_relay_log_pos;
|
ulonglong future_event_relay_log_pos;
|
||||||
|
char event_relay_log_name[FN_REFLEN];
|
||||||
|
char future_event_master_log_name[FN_REFLEN];
|
||||||
|
ulonglong event_relay_log_pos;
|
||||||
} *event_queue, *last_in_queue;
|
} *event_queue, *last_in_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -877,7 +877,9 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
|
|||||||
if (!skip_lock)
|
if (!skip_lock)
|
||||||
mysql_mutex_lock(&data_lock);
|
mysql_mutex_lock(&data_lock);
|
||||||
rgi->inc_event_relay_log_pos();
|
rgi->inc_event_relay_log_pos();
|
||||||
if (opt_slave_parallel_threads > 0)
|
DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
|
||||||
|
(long) log_pos, (long) group_master_log_pos));
|
||||||
|
if (rgi->is_parallel_exec)
|
||||||
{
|
{
|
||||||
/* In case of parallel replication, do not update the position backwards. */
|
/* In case of parallel replication, do not update the position backwards. */
|
||||||
int cmp= strcmp(group_relay_log_name, event_relay_log_name);
|
int cmp= strcmp(group_relay_log_name, event_relay_log_name);
|
||||||
@ -888,6 +890,18 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
|
|||||||
notify_group_relay_log_name_update();
|
notify_group_relay_log_name_update();
|
||||||
} else if (cmp == 0 && group_relay_log_pos < event_relay_log_pos)
|
} else if (cmp == 0 && group_relay_log_pos < event_relay_log_pos)
|
||||||
group_relay_log_pos= event_relay_log_pos;
|
group_relay_log_pos= event_relay_log_pos;
|
||||||
|
|
||||||
|
cmp= strcmp(group_master_log_name, rgi->future_event_master_log_name);
|
||||||
|
if (cmp <= 0)
|
||||||
|
{
|
||||||
|
if (cmp < 0)
|
||||||
|
{
|
||||||
|
strcpy(group_master_log_name, rgi->future_event_master_log_name);
|
||||||
|
notify_group_master_log_name_update();
|
||||||
|
}
|
||||||
|
if (group_master_log_pos < log_pos)
|
||||||
|
group_master_log_pos= log_pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -895,6 +909,8 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
|
|||||||
group_relay_log_pos= event_relay_log_pos;
|
group_relay_log_pos= event_relay_log_pos;
|
||||||
strmake_buf(group_relay_log_name, event_relay_log_name);
|
strmake_buf(group_relay_log_name, event_relay_log_name);
|
||||||
notify_group_relay_log_name_update();
|
notify_group_relay_log_name_update();
|
||||||
|
if (log_pos) // 3.23 binlogs don't have log_posx
|
||||||
|
group_master_log_pos= log_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -927,12 +943,6 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
|
|||||||
the relay log is not "val".
|
the relay log is not "val".
|
||||||
With the end_log_pos solution, we avoid computations involving lengthes.
|
With the end_log_pos solution, we avoid computations involving lengthes.
|
||||||
*/
|
*/
|
||||||
DBUG_PRINT("info", ("log_pos: %lu group_master_log_pos: %lu",
|
|
||||||
(long) log_pos, (long) group_master_log_pos));
|
|
||||||
if (log_pos) // 3.23 binlogs don't have log_posx
|
|
||||||
{
|
|
||||||
group_master_log_pos= log_pos;
|
|
||||||
}
|
|
||||||
mysql_cond_broadcast(&data_cond);
|
mysql_cond_broadcast(&data_cond);
|
||||||
if (!skip_lock)
|
if (!skip_lock)
|
||||||
mysql_mutex_unlock(&data_lock);
|
mysql_mutex_unlock(&data_lock);
|
||||||
@ -1436,6 +1446,7 @@ rpl_group_info::rpl_group_info(Relay_log_info *rli_)
|
|||||||
wait_commit_group_info(0), wait_start_sub_id(0), parallel_entry(0),
|
wait_commit_group_info(0), wait_start_sub_id(0), parallel_entry(0),
|
||||||
deferred_events(NULL), m_annotate_event(0), tables_to_lock(0),
|
deferred_events(NULL), m_annotate_event(0), tables_to_lock(0),
|
||||||
tables_to_lock_count(0), trans_retries(0), last_event_start_time(0),
|
tables_to_lock_count(0), trans_retries(0), last_event_start_time(0),
|
||||||
|
is_parallel_exec(false),
|
||||||
row_stmt_start_timestamp(0), long_find_row_note_printed(false)
|
row_stmt_start_timestamp(0), long_find_row_note_printed(false)
|
||||||
{
|
{
|
||||||
bzero(¤t_gtid, sizeof(current_gtid));
|
bzero(¤t_gtid, sizeof(current_gtid));
|
||||||
|
@ -185,6 +185,10 @@ public:
|
|||||||
char event_relay_log_name[FN_REFLEN];
|
char event_relay_log_name[FN_REFLEN];
|
||||||
ulonglong event_relay_log_pos;
|
ulonglong event_relay_log_pos;
|
||||||
ulonglong future_event_relay_log_pos;
|
ulonglong future_event_relay_log_pos;
|
||||||
|
/*
|
||||||
|
The master log name for current event. Only used in parallel replication.
|
||||||
|
*/
|
||||||
|
char future_event_master_log_name[FN_REFLEN];
|
||||||
|
|
||||||
#ifdef HAVE_valgrind
|
#ifdef HAVE_valgrind
|
||||||
bool is_fake; /* Mark that this is a fake relay log info structure */
|
bool is_fake; /* Mark that this is a fake relay log info structure */
|
||||||
@ -216,18 +220,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool sql_force_rotate_relay;
|
bool sql_force_rotate_relay;
|
||||||
|
|
||||||
/*
|
|
||||||
When it commits, InnoDB internally stores the master log position it has
|
|
||||||
processed so far; the position to store is the one of the end of the
|
|
||||||
committing event (the COMMIT query event, or the event if in autocommit
|
|
||||||
mode).
|
|
||||||
*/
|
|
||||||
#if MYSQL_VERSION_ID < 40100
|
|
||||||
ulonglong future_master_log_pos;
|
|
||||||
#else
|
|
||||||
ulonglong future_group_master_log_pos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
time_t last_master_timestamp;
|
time_t last_master_timestamp;
|
||||||
|
|
||||||
void clear_until_condition();
|
void clear_until_condition();
|
||||||
@ -557,7 +549,15 @@ struct rpl_group_info
|
|||||||
*/
|
*/
|
||||||
time_t last_event_start_time;
|
time_t last_event_start_time;
|
||||||
|
|
||||||
|
char *event_relay_log_name;
|
||||||
|
char event_relay_log_name_buf[FN_REFLEN];
|
||||||
|
ulonglong event_relay_log_pos;
|
||||||
ulonglong future_event_relay_log_pos;
|
ulonglong future_event_relay_log_pos;
|
||||||
|
/*
|
||||||
|
The master log name for current event. Only used in parallel replication.
|
||||||
|
*/
|
||||||
|
char future_event_master_log_name[FN_REFLEN];
|
||||||
|
bool is_parallel_exec;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
@ -685,7 +685,7 @@ public:
|
|||||||
|
|
||||||
inline void inc_event_relay_log_pos()
|
inline void inc_event_relay_log_pos()
|
||||||
{
|
{
|
||||||
if (opt_slave_parallel_threads == 0 ||
|
if (!is_parallel_exec ||
|
||||||
rli->event_relay_log_pos < future_event_relay_log_pos)
|
rli->event_relay_log_pos < future_event_relay_log_pos)
|
||||||
rli->event_relay_log_pos= future_event_relay_log_pos;
|
rli->event_relay_log_pos= future_event_relay_log_pos;
|
||||||
}
|
}
|
||||||
|
@ -3361,6 +3361,8 @@ 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->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, NULL);
|
||||||
|
|
||||||
delete_or_keep_event_post_apply(serial_rgi, typ, ev);
|
delete_or_keep_event_post_apply(serial_rgi, typ, ev);
|
||||||
|
@ -4228,6 +4228,8 @@ static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var)
|
|||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
delete thd->rli_fake;
|
delete thd->rli_fake;
|
||||||
thd->rli_fake= NULL;
|
thd->rli_fake= NULL;
|
||||||
|
delete thd->rgi_fake;
|
||||||
|
thd->rgi_fake= NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (previous_val && val)
|
else if (previous_val && val)
|
||||||
|
Reference in New Issue
Block a user