summaryrefslogtreecommitdiff
path: root/sql/sql_repl.cc
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2003-11-18 17:31:17 +0100
committerunknown <guilhem@mysql.com>2003-11-18 17:31:17 +0100
commit80649ee8746aab02a198285248668cb49ce70f33 (patch)
treeec5bb0041cb8165d054181972fb92a7953f20ec4 /sql/sql_repl.cc
parentfdd0e7078dcec0aa07c4719125d94241d9d0d6b1 (diff)
downloadmariadb-git-80649ee8746aab02a198285248668cb49ce70f33.tar.gz
Fix for BUG#1870
"CHANGE MASTER makes SQL thread restart from coordinates of I/O thread". So, in CHANGE MASTER: when it seems reasonable that the user did not want to discontinue its replication (i.e. when he is not specifying host or port or master_log_file or master_log_pos; this will be documented), set the coordinates of the I/O thread to those of the SQL thread. This way, the SQL thread will see no discontinuity in the relay log (i.e. will skip no events), because the I/O thread will fill the brand new relay log with the events which are just after the position where the SQL thread had stopped (before CHANGE MASTER was issued). And a new test for this bug. mysql-test/r/rpl_loaddata.result: Now, after CHANGE MASTER the coordinates of the I/O thread are the last ones of the SQL thread, so result update. sql/sql_repl.cc: Fix for BUG#1870 "CHANGE MASTER makes SQL thread restart from coordinates of I/O thread". So, in CHANGE MASTER: when it seems reasonable that the user did not want to discontinue its replication (i.e. when he is not specifying host or port or master_log_file or master_log_pos; this will be documented), set the coordinates of the I/O thread to those of the SQL thread. This way, the SQL thread will see no discontinuity in the relay log (i.e. will skip no events), because the I/O thread will fill the brand new relay log with the events which are just after the position where the SQL thread had stopped (before CHANGE MASTER was issued).
Diffstat (limited to 'sql/sql_repl.cc')
-rw-r--r--sql/sql_repl.cc49
1 files changed, 45 insertions, 4 deletions
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 10581431c72..c95cdc1b04e 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -853,8 +853,8 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
int change_master(THD* thd, MASTER_INFO* mi)
{
int thread_mask;
- const char* errmsg=0;
- bool need_relay_log_purge=1;
+ const char* errmsg= 0;
+ bool need_relay_log_purge= 1;
DBUG_ENTER("change_master");
lock_slave_threads(mi);
@@ -928,6 +928,36 @@ int change_master(THD* thd, MASTER_INFO* mi)
mi->rli.relay_log_pos=lex_mi->relay_log_pos;
}
+ /*
+ If user did specify neither host nor port nor any log name nor any log
+ pos, i.e. he specified only user/password/master_connect_retry, he probably
+ wants replication to resume from where it had left, i.e. from the
+ coordinates of the **SQL** thread (imagine the case where the I/O is ahead
+ of the SQL; restarting from the coordinates of the I/O would lose some
+ events which is probably unwanted when you are just doing minor changes
+ like changing master_connect_retry).
+ A side-effect is that if only the I/O thread was started, this thread may
+ restart from ''/4 after the CHANGE MASTER. That's a minor problem (it is a
+ much more unlikely situation than the one we are fixing here).
+ Note: coordinates of the SQL thread must be read here, before the
+ 'if (need_relay_log_purge)' block which resets them.
+ */
+ if (!lex_mi->host && !lex_mi->port &&
+ !lex_mi->log_file_name && !lex_mi->pos &&
+ need_relay_log_purge)
+ {
+ /*
+ Sometimes mi->rli.master_log_pos == 0 (it happens when the SQL thread is
+ not initialized), so we use a max().
+ What happens to mi->rli.master_log_pos during the initialization stages
+ of replication is not 100% clear, so we guard against problems using
+ max().
+ */
+ mi->master_log_pos = max(BIN_LOG_HEADER_SIZE, mi->rli.master_log_pos);
+ strmake(mi->master_log_name,mi->rli.master_log_name,
+ sizeof(mi->master_log_name)-1);
+ }
+
flush_master_info(mi);
if (need_relay_log_purge)
{
@@ -959,10 +989,21 @@ int change_master(THD* thd, MASTER_INFO* mi)
}
}
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
- /* If changing RELAY_LOG_FILE or RELAY_LOG_POS, this will be nonsense: */
+
+ /*
+ Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,
+ so restore them to good values. If we left them to ''/0, that would work;
+ but that would fail in the case of 2 successive CHANGE MASTER (without a
+ START SLAVE in between): because first one would set the coords in mi to
+ the good values of those in rli, the set those in rli to ''/0, then
+ second CHANGE MASTER would set the coords in mi to those of rli, i.e. to
+ ''/0: we have lost all copies of the original good coordinates.
+ That's why we always save good coords in rli.
+ */
mi->rli.master_log_pos = mi->master_log_pos;
strmake(mi->rli.master_log_name,mi->master_log_name,
- sizeof(mi->rli.master_log_name)-1);
+ sizeof(mi->rli.master_log_name)-1);
+
if (!mi->rli.master_log_name[0]) // uninitialized case
mi->rli.master_log_pos=0;