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 ...@@ -69,11 +69,32 @@ a
4 4
5 5
6 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 *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable
include/stop_slave.inc include/stop_slave.inc
CHANGE MASTER TO master_use_gtid= no; CHANGE MASTER TO master_use_gtid= no;
include/start_slave.inc include/start_slave.inc
INSERT INTO t1 VALUES (7); INSERT INTO t1 VALUES (8);
SELECT * FROM t1 ORDER BY a; SELECT * FROM t1 ORDER BY a;
a a
1 1
...@@ -83,6 +104,7 @@ a ...@@ -83,6 +104,7 @@ a
5 5
6 6
7 7
8
include/stop_slave.inc include/stop_slave.inc
SET sql_log_bin= 0; SET sql_log_bin= 0;
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
...@@ -96,7 +118,7 @@ SET sql_log_bin=1; ...@@ -96,7 +118,7 @@ SET sql_log_bin=1;
include/start_slave.inc include/start_slave.inc
Warnings: Warnings:
Error 1286 Unknown storage engine 'InnoDB' Error 1286 Unknown storage engine 'InnoDB'
INSERT INTO t1 VALUES (8); INSERT INTO t1 VALUES (9);
SELECT * FROM t1 ORDER BY a; SELECT * FROM t1 ORDER BY a;
a a
1 1
...@@ -107,6 +129,7 @@ a ...@@ -107,6 +129,7 @@ a
6 6
7 7
8 8
9
SET sql_log_bin= 0; SET sql_log_bin= 0;
ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM;
SET sql_log_bin= 1; SET sql_log_bin= 1;
......
...@@ -128,6 +128,42 @@ INSERT INTO t1 VALUES (6); ...@@ -128,6 +128,42 @@ INSERT INTO t1 VALUES (6);
SELECT * FROM t1 ORDER BY a; 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 --echo *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable
--connection server_2 --connection server_2
...@@ -136,7 +172,7 @@ CHANGE MASTER TO master_use_gtid= no; ...@@ -136,7 +172,7 @@ CHANGE MASTER TO master_use_gtid= no;
--source include/start_slave.inc --source include/start_slave.inc
--connection server_1 --connection server_1
INSERT INTO t1 VALUES (7); INSERT INTO t1 VALUES (8);
--save_master_pos --save_master_pos
--connection server_2 --connection server_2
...@@ -169,7 +205,7 @@ SET sql_log_bin=1; ...@@ -169,7 +205,7 @@ SET sql_log_bin=1;
--source include/start_slave.inc --source include/start_slave.inc
--connection server_1 --connection server_1
INSERT INTO t1 VALUES (8); INSERT INTO t1 VALUES (9);
--save_master_pos --save_master_pos
--connection server_2 --connection server_2
......
...@@ -5071,9 +5071,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) ...@@ -5071,9 +5071,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
const char *errmsg; const char *errmsg;
Gtid_list_log_event *glev; Gtid_list_log_event *glev;
Log_event *tmp; 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, if (!(tmp= Log_event::read_log_event(buf, event_len, &errmsg,
mi->rli.relay_log.description_event_for_queue, mi->rli.relay_log.description_event_for_queue,
opt_slave_sql_verify_checksum))) opt_slave_sql_verify_checksum)))
...@@ -5082,16 +5081,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) ...@@ -5082,16 +5081,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
goto err; goto err;
} }
glev= static_cast<Gtid_list_log_event *>(tmp); 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; event_pos= glev->log_pos;
flags= glev->gl_flags;
delete glev; delete glev;
/* /*
...@@ -5105,6 +5096,17 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) ...@@ -5105,6 +5096,17 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
inc_pos= 0; inc_pos= 0;
else else
inc_pos= event_pos - mi->master_log_pos; 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; break;
......
...@@ -1461,7 +1461,8 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, ...@@ -1461,7 +1461,8 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
slave_connection_state *until_gtid_state, slave_connection_state *until_gtid_state,
enum_gtid_until_state *gtid_until_group, enum_gtid_until_state *gtid_until_group,
rpl_binlog_state *until_binlog_state, 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; my_off_t pos;
size_t len= packet->length(); size_t len= packet->length();
...@@ -1541,7 +1542,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags, ...@@ -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 && if (event_gtid.server_id == gtid->server_id &&
event_gtid.seq_no >= gtid->seq_no) 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 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, ...@@ -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 exist, even though both the prior and subsequent seq_no exists
for same domain_id and server_id. for same domain_id and server_id.
*/ */
if (slave_gtid_strict_mode)
{
my_errno= ER_GTID_START_FROM_BINLOG_HOLE; my_errno= ER_GTID_START_FROM_BINLOG_HOLE;
*error_gtid= *gtid; *error_gtid= *gtid;
return "The binlog on the master is missing the GTID requested " return "The binlog on the master is missing the GTID requested "
"by the slave (even though both a prior and a subsequent " "by the slave (even though both a prior and a subsequent "
"sequence number does exist), and GTID strict mode is enabled."; "sequence number does exist), and GTID strict mode is enabled.";
} }
}
else
{
/* /*
Send a fake Gtid_list event to the slave. Send a fake Gtid_list event to the slave.
This allows the slave to update its current binlog position This allows the slave to update its current binlog position
so MASTER_POS_WAIT() and MASTER_GTID_WAIT() can work. 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_event(until_binlog_state); *send_fake_gtid_list= true;
}
/* /*
Delete this entry if we have reached slave start position (so we 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 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, ...@@ -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; enum_gtid_until_state gtid_until_group= GTID_UNTIL_NOT_DONE;
rpl_binlog_state until_binlog_state; rpl_binlog_state until_binlog_state;
bool slave_gtid_strict_mode; bool slave_gtid_strict_mode;
bool send_fake_gtid_list= false;
uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
int old_max_allowed_packet= thd->variables.max_allowed_packet; int old_max_allowed_packet= thd->variables.max_allowed_packet;
...@@ -2234,11 +2233,25 @@ impossible position"; ...@@ -2234,11 +2233,25 @@ impossible position";
&gtid_state, &gtid_skip_group, &gtid_state, &gtid_skip_group,
until_gtid_state, &gtid_until_group, until_gtid_state, &gtid_until_group,
&until_binlog_state, &until_binlog_state,
slave_gtid_strict_mode, &error_gtid))) slave_gtid_strict_mode, &error_gtid,
&send_fake_gtid_list)))
{ {
errmsg= tmp_msg; errmsg= tmp_msg;
goto err; 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 && if (until_gtid_state &&
is_until_reached(thd, net, packet, &ev_offset, gtid_until_group, is_until_reached(thd, net, packet, &ev_offset, gtid_until_group,
event_type, current_checksum_alg, flags, &errmsg, event_type, current_checksum_alg, flags, &errmsg,
...@@ -2426,13 +2439,26 @@ impossible position"; ...@@ -2426,13 +2439,26 @@ impossible position";
using_gtid_state, &gtid_state, using_gtid_state, &gtid_state,
&gtid_skip_group, until_gtid_state, &gtid_skip_group, until_gtid_state,
&gtid_until_group, &until_binlog_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; errmsg= tmp_msg;
goto err; goto err;
} }
if ( if (unlikely(send_fake_gtid_list) && gtid_skip_group == GTID_SKIP_NOT)
until_gtid_state && {
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, is_until_reached(thd, net, packet, &ev_offset, gtid_until_group,
event_type, current_checksum_alg, flags, &errmsg, event_type, current_checksum_alg, flags, &errmsg,
&until_binlog_state, my_b_tell(&log))) &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