diff options
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_gtid_stop_start.result | 27 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_gtid_stop_start.test | 40 | ||||
-rw-r--r-- | sql/slave.cc | 24 | ||||
-rw-r--r-- | sql/sql_repl.cc | 72 |
4 files changed, 125 insertions, 38 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index 708b553e76d..a00bad38378 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -69,11 +69,32 @@ a 4 5 6 +*** MDEV-4490: Old-style master position points at the last GTID event after slave restart *** +INSERT INTO t1 VALUES (7); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +include/wait_for_slave_to_start.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable include/stop_slave.inc CHANGE MASTER TO master_use_gtid= no; include/start_slave.inc -INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); SELECT * FROM t1 ORDER BY a; a 1 @@ -83,6 +104,7 @@ a 5 6 7 +8 include/stop_slave.inc SET sql_log_bin= 0; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; @@ -96,7 +118,7 @@ SET sql_log_bin=1; include/start_slave.inc Warnings: Error 1286 Unknown storage engine 'InnoDB' -INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); SELECT * FROM t1 ORDER BY a; a 1 @@ -107,6 +129,7 @@ a 6 7 8 +9 SET sql_log_bin= 0; ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; SET sql_log_bin= 1; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 05cb078558d..d4642381ca8 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -128,6 +128,42 @@ INSERT INTO t1 VALUES (6); SELECT * FROM t1 ORDER BY a; +--echo *** MDEV-4490: Old-style master position points at the last GTID event after slave restart *** + +--connection server_1 +INSERT INTO t1 VALUES (7); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Now we restart the slave server. When it restarts, there is nothing new +# to replicate. Check that the position is nevertheless updated and +# MASTER_POS_WAIT() works correctly and detects that we are up-to-date. + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server 30 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--source include/wait_for_slave_to_start.inc + +--connection server_1 +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + --echo *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable --connection server_2 @@ -136,7 +172,7 @@ CHANGE MASTER TO master_use_gtid= no; --source include/start_slave.inc --connection server_1 -INSERT INTO t1 VALUES (7); +INSERT INTO t1 VALUES (8); --save_master_pos --connection server_2 @@ -169,7 +205,7 @@ SET sql_log_bin=1; --source include/start_slave.inc --connection server_1 -INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (9); --save_master_pos --connection server_2 diff --git a/sql/slave.cc b/sql/slave.cc index 8cb13205f29..1734b2c4f76 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -5071,9 +5071,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) const char *errmsg; Gtid_list_log_event *glev; Log_event *tmp; + uint32 flags; - if (mi->rli.until_condition != Relay_log_info::UNTIL_GTID) - goto default_action; if (!(tmp= Log_event::read_log_event(buf, event_len, &errmsg, mi->rli.relay_log.description_event_for_queue, opt_slave_sql_verify_checksum))) @@ -5082,16 +5081,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) goto err; } glev= static_cast<Gtid_list_log_event *>(tmp); - if (glev->gl_flags & Gtid_list_log_event::FLAG_UNTIL_REACHED) - { - char str_buf[128]; - String str(str_buf, sizeof(str_buf), system_charset_info); - mi->rli.until_gtid_pos.to_string(&str); - sql_print_information("Slave IO thread stops because it reached its" - " UNTIL master_gtid_pos %s", str.c_ptr_safe()); - mi->abort_slave= true; - } event_pos= glev->log_pos; + flags= glev->gl_flags; delete glev; /* @@ -5105,6 +5096,17 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) inc_pos= 0; else inc_pos= event_pos - mi->master_log_pos; + + if (mi->rli.until_condition == Relay_log_info::UNTIL_GTID && + flags & Gtid_list_log_event::FLAG_UNTIL_REACHED) + { + char str_buf[128]; + String str(str_buf, sizeof(str_buf), system_charset_info); + mi->rli.until_gtid_pos.to_string(&str); + sql_print_information("Slave IO thread stops because it reached its" + " UNTIL master_gtid_pos %s", str.c_ptr_safe()); + mi->abort_slave= true; + } } break; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 29f2897315c..283078203ed 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1461,7 +1461,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) { my_off_t pos; size_t len= packet->length(); @@ -1541,7 +1542,7 @@ 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) { /* In strict mode, it is an error if the slave requests to start @@ -1549,24 +1550,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 @@ -1818,6 +1816,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, enum_gtid_until_state gtid_until_group= GTID_UNTIL_NOT_DONE; rpl_binlog_state until_binlog_state; bool slave_gtid_strict_mode; + bool send_fake_gtid_list= false; uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; int old_max_allowed_packet= thd->variables.max_allowed_packet; @@ -2234,11 +2233,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))) { 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 +2439,26 @@ 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))) { 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))) |