diff options
author | unknown <knielsen@knielsen-hq.org> | 2013-06-07 14:39:00 +0200 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2013-06-07 14:39:00 +0200 |
commit | b5fcf33d24c90f23ab1302688ff315200807f572 (patch) | |
tree | d7812cea70ce404bfdb46ec7ec68eb3949c5ec03 | |
parent | 03aa4876e187fcb7dbae6d43170345d2a25fb0e7 (diff) | |
download | mariadb-git-b5fcf33d24c90f23ab1302688ff315200807f572.tar.gz |
MDEV-4490: Old-style master position points at the last GTID event after slave restart
Now whenever we reach the GTID point requested from the slave (when using GTID
position to connect), we send a fake Gtid_list event. This event is used by
the slave to know the current old-style position for MASTER_POS_WAIT(), and
later the similar binlog position for MASTER_GTID_WAIT().
Without this fake event, if the slave is already fully up-to-date with the
master, there may be no events sent at the given position for an indeterminate
time.
-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))) |