summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_stop_start.result27
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_stop_start.test40
-rw-r--r--sql/slave.cc24
-rw-r--r--sql/sql_repl.cc72
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";
&gtid_state, &gtid_skip_group,
until_gtid_state, &gtid_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, &gtid_state,
&gtid_skip_group, until_gtid_state,
&gtid_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)))