diff options
Diffstat (limited to 'sql/sql_repl.cc')
-rw-r--r-- | sql/sql_repl.cc | 124 |
1 files changed, 86 insertions, 38 deletions
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 0d6c97842d4..802161a09a9 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -894,7 +894,8 @@ contains_all_slave_gtid(slave_connection_state *st, Gtid_list_log_event *glev) static int check_slave_start_position(THD *thd, slave_connection_state *st, const char **errormsg, rpl_gtid *error_gtid, - slave_connection_state *until_gtid_state) + slave_connection_state *until_gtid_state, + HASH *fake_gtid_hash) { uint32 i; int err; @@ -998,11 +999,30 @@ check_slave_start_position(THD *thd, slave_connection_state *st, &start_gtid) && start_gtid.seq_no > slave_gtid->seq_no) { + rpl_gtid *fake_gtid; /* Start replication within this domain at the first GTID that we logged ourselves after becoming a master. + + Remember that this starting point is in fact a "fake" GTID which may + not exists in the binlog, so that we do not complain about it in + --gtid-strict-mode. */ slave_gtid->server_id= global_system_variables.server_id; + if (!(fake_gtid= (rpl_gtid *)my_malloc(sizeof(*fake_gtid), MYF(0)))) + { + *errormsg= "Out of memory while checking slave start position"; + err= ER_OUT_OF_RESOURCES; + goto end; + } + *fake_gtid= *slave_gtid; + if (my_hash_insert(fake_gtid_hash, (uchar *)fake_gtid)) + { + my_free(fake_gtid); + *errormsg= "Out of memory while checking slave start position"; + err= ER_OUT_OF_RESOURCES; + goto end; + } } else if (mysql_bin_log.lookup_domain_in_binlog_state(slave_gtid->domain_id, &start_gtid)) @@ -1022,8 +1042,8 @@ check_slave_start_position(THD *thd, slave_connection_state *st, */ if (!delete_list) { - if ((delete_list= (rpl_gtid **)my_malloc(sizeof(*delete_list), - MYF(MY_WME)))) + if (!(delete_list= (rpl_gtid **) + my_malloc(sizeof(*delete_list) * st->hash.records, MYF(MY_WME)))) { *errormsg= "Out of memory while checking slave start position"; err= ER_OUT_OF_RESOURCES; @@ -1461,7 +1481,8 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, slave_connection_state *until_gtid_state, enum_gtid_until_state *gtid_until_group, rpl_binlog_state *until_binlog_state, - bool slave_gtid_strict_mode, rpl_gtid *error_gtid) + bool slave_gtid_strict_mode, rpl_gtid *error_gtid, + bool *send_fake_gtid_list, HASH *fake_gtid_hash) { my_off_t pos; size_t len= packet->length(); @@ -1541,7 +1562,9 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, if (event_gtid.server_id == gtid->server_id && event_gtid.seq_no >= gtid->seq_no) { - if (event_gtid.seq_no > gtid->seq_no) + if (slave_gtid_strict_mode && event_gtid.seq_no > gtid->seq_no && + !my_hash_search(fake_gtid_hash, + (const uchar *)&event_gtid.domain_id, 0)) { /* In strict mode, it is an error if the slave requests to start @@ -1549,24 +1572,21 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, exist, even though both the prior and subsequent seq_no exists for same domain_id and server_id. */ - if (slave_gtid_strict_mode) - { - my_errno= ER_GTID_START_FROM_BINLOG_HOLE; - *error_gtid= *gtid; - return "The binlog on the master is missing the GTID requested " - "by the slave (even though both a prior and a subsequent " - "sequence number does exist), and GTID strict mode is enabled."; - } - } - else - { - /* - Send a fake Gtid_list event to the slave. - This allows the slave to update its current binlog position - so MASTER_POS_WAIT() and MASTER_GTID_WAIT() can work. - */ -// send_fake_gtid_list_event(until_binlog_state); + my_errno= ER_GTID_START_FROM_BINLOG_HOLE; + *error_gtid= *gtid; + return "The binlog on the master is missing the GTID requested " + "by the slave (even though both a prior and a subsequent " + "sequence number does exist), and GTID strict mode is enabled."; } + + /* + Send a fake Gtid_list event to the slave. + This allows the slave to update its current binlog position + so MASTER_POS_WAIT() and MASTER_GTID_WAIT() can work. + The fake event will be sent at the end of this event group. + */ + *send_fake_gtid_list= true; + /* Delete this entry if we have reached slave start position (so we will not skip subsequent events and won't have to look them up @@ -1817,7 +1837,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, enum_gtid_skip_type gtid_skip_group= GTID_SKIP_NOT; enum_gtid_until_state gtid_until_group= GTID_UNTIL_NOT_DONE; rpl_binlog_state until_binlog_state; - bool slave_gtid_strict_mode; + bool slave_gtid_strict_mode= false; + bool send_fake_gtid_list= false; + HASH fake_gtid_hash; uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; int old_max_allowed_packet= thd->variables.max_allowed_packet; @@ -1831,6 +1853,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, bzero((char*) &log,sizeof(log)); bzero(&error_gtid, sizeof(error_gtid)); + my_hash_init(&fake_gtid_hash, &my_charset_bin, 32, + offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, my_free, + HASH_UNIQUE); /* heartbeat_period from @master_heartbeat_period user variable */ @@ -1930,7 +1955,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, goto err; } if ((error= check_slave_start_position(thd, >id_state, &errmsg, - &error_gtid, until_gtid_state))) + &error_gtid, until_gtid_state, + &fake_gtid_hash))) { my_errno= error; goto err; @@ -2234,11 +2260,25 @@ impossible position"; >id_state, >id_skip_group, until_gtid_state, >id_until_group, &until_binlog_state, - slave_gtid_strict_mode, &error_gtid))) + slave_gtid_strict_mode, &error_gtid, + &send_fake_gtid_list, &fake_gtid_hash))) { errmsg= tmp_msg; goto err; } + if (unlikely(send_fake_gtid_list) && gtid_skip_group == GTID_SKIP_NOT) + { + Gtid_list_log_event glev(&until_binlog_state, 0); + + if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg) || + fake_gtid_list_event(net, packet, &glev, &errmsg, + current_checksum_alg, my_b_tell(&log))) + { + my_errno= ER_UNKNOWN_ERROR; + goto err; + } + send_fake_gtid_list= false; + } if (until_gtid_state && is_until_reached(thd, net, packet, &ev_offset, gtid_until_group, event_type, current_checksum_alg, flags, &errmsg, @@ -2426,13 +2466,27 @@ impossible position"; using_gtid_state, >id_state, >id_skip_group, until_gtid_state, >id_until_group, &until_binlog_state, - slave_gtid_strict_mode, &error_gtid))) + slave_gtid_strict_mode, &error_gtid, + &send_fake_gtid_list, + &fake_gtid_hash))) { errmsg= tmp_msg; goto err; } - if ( - until_gtid_state && + if (unlikely(send_fake_gtid_list) && gtid_skip_group == GTID_SKIP_NOT) + { + Gtid_list_log_event glev(&until_binlog_state, 0); + + if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg) || + fake_gtid_list_event(net, packet, &glev, &errmsg, + current_checksum_alg, my_b_tell(&log))) + { + my_errno= ER_UNKNOWN_ERROR; + goto err; + } + send_fake_gtid_list= false; + } + if (until_gtid_state && is_until_reached(thd, net, packet, &ev_offset, gtid_until_group, event_type, current_checksum_alg, flags, &errmsg, &until_binlog_state, my_b_tell(&log))) @@ -2504,6 +2558,7 @@ impossible position"; end: end_io_cache(&log); mysql_file_close(file, MYF(MY_WME)); + my_hash_free(&fake_gtid_hash); RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags)); my_eof(thd); @@ -2574,6 +2629,7 @@ err: mysql_mutex_unlock(&LOCK_thread_count); if (file >= 0) mysql_file_close(file, MYF(MY_WME)); + my_hash_free(&fake_gtid_hash); thd->variables.max_allowed_packet= old_max_allowed_packet; my_message(my_errno, error_text, MYF(0)); @@ -3297,16 +3353,6 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) ret= TRUE; goto err; } - - if (mi->using_gtid != Master_info::USE_GTID_NO) - { - /* - Clear the position in the master binlogs, so that we request the - correct GTID position. - */ - mi->master_log_name[0]= 0; - mi->master_log_pos= 0; - } } else { @@ -3722,6 +3768,8 @@ bool show_binlogs(THD* thd) if (protocol->write()) goto err; } + if(index_file->error == -1) + goto err; mysql_bin_log.unlock_index(); my_eof(thd); DBUG_RETURN(FALSE); |