Commit f1abd015 authored by Andrei Elkin's avatar Andrei Elkin

Bug #47210 first execution of "start slave until" stops too early

Until-pos guarding did not distiguish the master originated events from ones that the slave 
can introduce to the relay log e.g Rotate to the next relay log at slave restarting.
The local Rotate's coordinate are incomparable with the Until-master-pos.
That led to the unexpectable stop this bug describes.

Fixed with to avoid Until-master-pos comparison for a local slave's event.
Notice that if --replicate-same-server is true such event is treated as coming from
the master side.


mysql-test/r/rpl_until.result:
  results changed.
mysql-test/t/rpl_until.test:
  regression test for bug#47210 is added.
sql/slave.cc:
  st_relay_log_info::is_until_satisfied() is augmented with avoidance of 
  Until-master-pos comparison for a local slave's event.
  if --replicate-same-server is true such event is treated as coming from
  the master side.
sql/slave.h:
  signature of is_until_satisfied() changed to supply THD and Event to the routine.
parent 903d2128
...@@ -194,3 +194,31 @@ start slave sql_thread; ...@@ -194,3 +194,31 @@ start slave sql_thread;
start slave until master_log_file='master-bin.000001', master_log_pos=776; start slave until master_log_file='master-bin.000001', master_log_pos=776;
Warnings: Warnings:
Note 1254 Slave is already running Note 1254 Slave is already running
include/stop_slave.inc
drop table if exists t1;
reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
drop table if exists t1;
reset master;
create table t1 (a int primary key auto_increment);
start slave;
include/stop_slave.inc
master and slave are in sync now
select 0 as zero;
zero
0
insert into t1 set a=null;
insert into t1 set a=null;
select count(*) as two from t1;
two
2
start slave until master_log_file='master-bin.000001', master_log_pos= UNTIL_POS;;
slave stopped at the prescribed position
select 0 as zero;
zero
0
select count(*) as one from t1;
one
1
drop table t1;
start slave;
...@@ -84,4 +84,67 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; ...@@ -84,4 +84,67 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561;
start slave sql_thread; start slave sql_thread;
start slave until master_log_file='master-bin.000001', master_log_pos=776; start slave until master_log_file='master-bin.000001', master_log_pos=776;
# End of 4.1 tests #
# bug#47210 first execution of "start slave until" stops too early
#
# testing that a slave rotate event that is caused by stopping the slave
# does not intervene anymore in UNTIL condition.
#
connection slave;
source include/stop_slave.inc;
--disable_warnings
drop table if exists t1;
--enable_warnings
reset slave;
--replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
connection master;
--disable_warnings
drop table if exists t1;
--enable_warnings
reset master;
create table t1 (a int primary key auto_increment);
save_master_pos;
let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
connection slave;
start slave;
sync_with_master;
# at this point slave will close the relay log stamping it with its own
# Rotate log event. This event won't be examined on matter of the master
# UNTIL pos anymore.
source include/stop_slave.inc;
let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
--echo master and slave are in sync now
let $diff_pos= `select $master_pos - $slave_exec_pos`;
eval select $diff_pos as zero;
connection master;
insert into t1 set a=null;
let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1);
insert into t1 set a=null;
select count(*) as two from t1;
connection slave;
--replace_result $until_pos UNTIL_POS;
eval start slave until master_log_file='master-bin.000001', master_log_pos= $until_pos;
source include/wait_for_slave_sql_to_stop.inc;
let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1);
--echo slave stopped at the prescribed position
let $diff_pos= `select $until_pos - $slave_exec_pos`;
eval select $diff_pos as zero;
select count(*) as one from t1;
connection master;
drop table t1;
connection slave;
start slave;
sync_with_master;
# End of tests
...@@ -3223,7 +3223,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) ...@@ -3223,7 +3223,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
false - condition not met false - condition not met
*/ */
bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) bool st_relay_log_info::is_until_satisfied(THD *thd, Log_event *ev)
{ {
const char *log_name; const char *log_name;
ulonglong log_pos; ulonglong log_pos;
...@@ -3232,8 +3232,12 @@ bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) ...@@ -3232,8 +3232,12 @@ bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos)
if (until_condition == UNTIL_MASTER_POS) if (until_condition == UNTIL_MASTER_POS)
{ {
if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id)
return FALSE;
log_name= group_master_log_name; log_name= group_master_log_name;
log_pos= master_beg_pos; log_pos= (!ev)? group_master_log_pos :
((thd->options & OPTION_BEGIN || !ev->log_pos) ?
group_master_log_pos : ev->log_pos - ev->data_written);
} }
else else
{ /* until_condition == UNTIL_RELAY_POS */ { /* until_condition == UNTIL_RELAY_POS */
...@@ -3333,9 +3337,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) ...@@ -3333,9 +3337,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
hits the UNTIL barrier. hits the UNTIL barrier.
*/ */
if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE &&
rli->is_until_satisfied((thd->options & OPTION_BEGIN || !ev->log_pos) ? rli->is_until_satisfied(thd, ev))
rli->group_master_log_pos :
ev->log_pos - ev->data_written))
{ {
char buf[22]; char buf[22];
sql_print_information("Slave SQL thread stopped because it reached its" sql_print_information("Slave SQL thread stopped because it reached its"
...@@ -4065,7 +4067,7 @@ Slave SQL thread aborted. Can't execute init_slave query"); ...@@ -4065,7 +4067,7 @@ Slave SQL thread aborted. Can't execute init_slave query");
*/ */
pthread_mutex_lock(&rli->data_lock); pthread_mutex_lock(&rli->data_lock);
if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE &&
rli->is_until_satisfied(rli->group_master_log_pos)) rli->is_until_satisfied(thd, NULL))
{ {
char buf[22]; char buf[22];
sql_print_information("Slave SQL thread stopped because it reached its" sql_print_information("Slave SQL thread stopped because it reached its"
......
...@@ -348,7 +348,7 @@ typedef struct st_relay_log_info ...@@ -348,7 +348,7 @@ typedef struct st_relay_log_info
void close_temporary_tables(); void close_temporary_tables();
/* Check if UNTIL condition is satisfied. See slave.cc for more. */ /* Check if UNTIL condition is satisfied. See slave.cc for more. */
bool is_until_satisfied(my_off_t master_beg_pos); bool is_until_satisfied(THD *thd, Log_event *ev);
inline ulonglong until_pos() inline ulonglong until_pos()
{ {
return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos :
......
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