summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2013-02-21 08:10:55 +0100
committerunknown <knielsen@knielsen-hq.org>2013-02-21 08:10:55 +0100
commitc350177a212d3c4b00e233917983064f24aff907 (patch)
tree1b7d2118b6299157160a099b70c26157d6631d17
parent7426a466dcf364885a3cc670928b23a6f2fc2a5d (diff)
downloadmariadb-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.inc16
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_basic.result69
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_basic.test81
-rw-r--r--sql/slave.cc35
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;