diff options
author | unknown <knielsen@knielsen-hq.org> | 2013-02-21 08:10:55 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2013-02-21 08:10:55 +0100 |
commit | c350177a212d3c4b00e233917983064f24aff907 (patch) | |
tree | 1b7d2118b6299157160a099b70c26157d6631d17 | |
parent | 7426a466dcf364885a3cc670928b23a6f2fc2a5d (diff) | |
download | mariadb-git-c350177a212d3c4b00e233917983064f24aff907.tar.gz |
MDEV-26: Global transaction ID
- Add first basic mysql-test-run test case which tests switch to new master
using MASTER_GTID_POS=AUTO.
- When we connect with GTID, do not use any old relay logs, as they may
contain the wrong events or be corrupt after crash.
- Fix old bug that fails replication if we receive a heartbeat event
immediately after an event was omitted in the stream from the master.
- Fix rpl_end to clear Gtid_Pos_Auto, to keep check_testcase happy.
-rw-r--r-- | mysql-test/include/rpl_end.inc | 16 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_gtid_basic.result | 69 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_gtid_basic.test | 81 | ||||
-rw-r--r-- | sql/slave.cc | 35 |
4 files changed, 199 insertions, 2 deletions
diff --git a/mysql-test/include/rpl_end.inc b/mysql-test/include/rpl_end.inc index f671c442153..b6535f00283 100644 --- a/mysql-test/include/rpl_end.inc +++ b/mysql-test/include/rpl_end.inc @@ -79,6 +79,22 @@ while ($_rpl_server) --source include/rpl_sync.inc --source include/rpl_stop_slaves.inc +if (!$rpl_debug) +{ + --disable_query_log +} +--let $_rpl_server= $rpl_server_count +while ($_rpl_server) +{ + --let $rpl_connection_name= server_$_rpl_server + --source include/rpl_connection.inc + + # Clear Gtid_Pos_Auto in SHOW SLAVE STATUS to keep check_testcase happy. + CHANGE MASTER TO master_log_file=''; + + --dec $_rpl_server +} + # mtr configures server 2 to be a slave before it runs the test. We # have to restore that state now, so we change topology to 1->2. --let $rpl_topology= none diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result index 11de46c7e23..75da3f6cbdb 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result @@ -44,5 +44,74 @@ a b 2 i2 3 i3 4 i4 +*** Now take out D, let it fall behind a bit, and then test re-attaching it to A *** +include/stop_slave.inc +INSERT INTO t1 VALUES (5, "m1a"); +INSERT INTO t2 VALUES (5, "i1a"); +CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT, +MASTER_GTID_POS=AUTO; +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a b +1 m1 +2 m2 +3 m3 +4 m4 +5 m1a +SELECT * FROM t2 ORDER BY a; +a b +1 i1 +2 i2 +3 i3 +4 i4 +5 i1a +*** Now move B to D (C is still replicating from B) *** +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4, +MASTER_GTID_POS=AUTO; +include/start_slave.inc +UPDATE t2 SET b="j1a" WHERE a=5; +SELECT * FROM t1 ORDER BY a; +a b +1 m1 +2 m2 +3 m3 +4 m4 +5 m1a +SELECT * FROM t2 ORDER BY a; +a b +1 i1 +2 i2 +3 i3 +4 i4 +5 j1a +*** Now move C to D, after letting it fall a little behind *** +include/stop_slave.inc +BEGIN; +INSERT INTO t2 VALUES (6, "i6b"); +INSERT INTO t2 VALUES (7, "i7b"); +COMMIT; +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4, +MASTER_GTID_POS=AUTO; +include/start_slave.inc +SELECT * FROM t2 ORDER BY a; +a b +1 i1 +2 i2 +3 i3 +4 i4 +5 j1a +6 i6b +7 i7b +*** Now change everything back to what it was, to make rpl_end.inc happy +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_MYPORT; +include/start_slave.inc +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SLAVE_MYPORT; +include/start_slave.inc +include/stop_slave.inc +CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3; +include/start_slave.inc DROP TABLE t1,t2; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test index 791d093b9a0..5aa3763742c 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -2,6 +2,11 @@ --let $rpl_topology=1->2->3->4 --source include/rpl_init.inc +# Set up a 4-deep replication topology, then test various fail-overs +# using GTID. +# +# A -> B -> C -> D + connection server_1; CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=MyISAM; CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(10)) ENGINE=InnoDB; @@ -31,6 +36,82 @@ sync_with_master; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; + +--echo *** Now take out D, let it fall behind a bit, and then test re-attaching it to A *** +connection server_4; +--source include/stop_slave.inc + +connection server_1; +INSERT INTO t1 VALUES (5, "m1a"); +INSERT INTO t2 VALUES (5, "i1a"); +save_master_pos; + +connection server_4; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT, + MASTER_GTID_POS=AUTO; +--source include/start_slave.inc +sync_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Now move B to D (C is still replicating from B) *** +connection server_2; +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4, + MASTER_GTID_POS=AUTO; +--source include/start_slave.inc + +connection server_4; +UPDATE t2 SET b="j1a" WHERE a=5; +save_master_pos; + +connection server_2; +sync_with_master; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo *** Now move C to D, after letting it fall a little behind *** +connection server_3; +--source include/stop_slave.inc + +connection server_1; +BEGIN; +INSERT INTO t2 VALUES (6, "i6b"); +INSERT INTO t2 VALUES (7, "i7b"); +COMMIT; + +connection server_3; +--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4, + MASTER_GTID_POS=AUTO; +--source include/start_slave.inc +# This time, let's sync up without reference to binlog on D. +--let $wait_condition= SELECT COUNT(*) = 7 FROM t2 +--source include/wait_condition.inc +SELECT * FROM t2 ORDER BY a; + +--echo *** Now change everything back to what it was, to make rpl_end.inc happy +# Also check that MASTER_GTID_POS=AUTO is still enabled. +connection server_2; +--source include/stop_slave.inc +--replace_result $MASTER_MYPORT MASTER_MYPORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT; +--source include/start_slave.inc + +connection server_3; +--source include/stop_slave.inc +--replace_result $SLAVE_MYPORT SLAVE_MYPORT +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT; +--source include/start_slave.inc + +connection server_4; +--source include/stop_slave.inc +--replace_result $SERVER_MYPORT_3 SERVER_MYPORT_3 +eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3; +--source include/start_slave.inc + connection server_1; DROP TABLE t1,t2; diff --git a/sql/slave.cc b/sql/slave.cc index 33455986008..a97599b7e19 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -397,6 +397,33 @@ int init_recovery(Master_info* mi, const char** errmsg) DBUG_RETURN(0); } + + +/* + When connecting a slave to a master with GTID, we reset the relay log + coordinates of the SQL thread and clear the master coordinates of SQL and IO + threads. + + This way we ensure that we start from the correct place even after a change + to new master or a crash where relay log coordinates may be wrong (GTID + state is crash safe but master.info is not). And we get the correct master + coordinates set upon reading the initial fake rotate event sent from master. +*/ +static void +reset_coordinates_for_gtid(Master_info *mi, Relay_log_info *rli) +{ + mi->master_log_pos= 0; + mi->master_log_name[0]= 0; + rli->group_master_log_pos= 0; + rli->group_master_log_name[0]= 0; + rli->group_relay_log_pos= BIN_LOG_HEADER_SIZE; + strmake(rli->group_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(rli->group_relay_log_name)-1); + rli->event_relay_log_pos= BIN_LOG_HEADER_SIZE; + strmake(rli->event_relay_log_name, rli->relay_log.get_log_fname(), + sizeof(mi->rli.event_relay_log_name)-1); +} + /** Convert slave skip errors bitmap into a printable string. @@ -3385,6 +3412,8 @@ connected: if (ret == 1) /* Fatal error */ goto err; + if (mi->gtid_pos_auto) + reset_coordinates_for_gtid(mi, rli); if (ret == 2) { @@ -4694,16 +4723,18 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) Heartbeat is sent only after an event corresponding to the corrdinates the heartbeat carries. - Slave can not have a difference in coordinates except in the only + Slave can not have a higher coordinate except in the only special case when mi->master_log_name, master_log_pos have never been updated by Rotate event i.e when slave does not have any history with the master (and thereafter mi->master_log_pos is NULL). + Slave can have lower coordinates, if some event from master was omitted. + TODO: handling `when' for SHOW SLAVE STATUS' snds behind */ if ((memcmp(mi->master_log_name, hb.get_log_ident(), hb.get_ident_len()) && mi->master_log_name != NULL) - || mi->master_log_pos != hb.log_pos) + || mi->master_log_pos > hb.log_pos) { /* missed events of heartbeat from the past */ error= ER_SLAVE_HEARTBEAT_FAILURE; |