Commit b5fcf33d authored by unknown's avatar unknown

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.
parent 03aa4876
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment