summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2005-10-12 21:58:02 +0200
committerunknown <guilhem@mysql.com>2005-10-12 21:58:02 +0200
commit8b1a32aeadf22776e2e3f8d1f67ee32f0e1fd80d (patch)
treea42e8586944072e7730401a2c2d33f5f227c60c8
parent3f11381b7c27dba3a0b387b642f4353c4d18cb7e (diff)
parent61dfc3347f013eadb46a5035cbf0479bcacc8f22 (diff)
downloadmariadb-git-8b1a32aeadf22776e2e3f8d1f67ee32f0e1fd80d.tar.gz
Merge mysql.com:/home/mysql_src/mysql-4.1
into mysql.com:/home/mysql_src/mysql-5.0; a very bad automerge (issues with non-ascii chars), plus some hard conflicts I'll fix by hand in a next cset BitKeeper/deleted/.del-compile-pentium64-valgrind-max: Delete: BUILD/compile-pentium64-valgrind-max BitKeeper/etc/config: Auto merged sql/log.cc: Auto merged sql/slave.h: Auto merged client/mysqltest.c: manual merge mysql-test/r/subselect.result: manual merge mysql-test/t/subselect.test: manual merge sql/log_event.cc: manual merge sql/log_event.h: manual merge sql/slave.cc: manual merge sql/sql_yacc.yy: manual merge
-rwxr-xr-x[-rw-r--r--]BUILD/compile-pentium64-valgrind-max0
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--mysql-test/r/rpl_dual_pos_advance.result22
-rw-r--r--mysql-test/r/subselect.result5
-rw-r--r--mysql-test/t/rpl_dual_pos_advance-master.opt0
-rw-r--r--mysql-test/t/rpl_dual_pos_advance.test108
-rw-r--r--mysql-test/t/subselect.test10
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc41
-rw-r--r--sql/log_event.h33
-rw-r--r--sql/slave.cc129
-rw-r--r--sql/slave.h11
12 files changed, 324 insertions, 42 deletions
diff --git a/BUILD/compile-pentium64-valgrind-max b/BUILD/compile-pentium64-valgrind-max
index 2e4ff8e0082..2e4ff8e0082 100644..100755
--- a/BUILD/compile-pentium64-valgrind-max
+++ b/BUILD/compile-pentium64-valgrind-max
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index 81e867e514f..b68810b77ac 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -73,5 +73,6 @@ hours:
[nick:]checkout:get
[jonas:]checkout:get
[tomas:]checkout:get
+[guilhem:]checkout:get
checkout:edit
eoln:unix
diff --git a/mysql-test/r/rpl_dual_pos_advance.result b/mysql-test/r/rpl_dual_pos_advance.result
new file mode 100644
index 00000000000..257baa81b74
--- /dev/null
+++ b/mysql-test/r/rpl_dual_pos_advance.result
@@ -0,0 +1,22 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+reset master;
+change master to master_host="127.0.0.1",master_port=SLAVE_PORT,master_user="root";
+start slave;
+create table t1 (n int);
+create table t4 (n int);
+create table t5 (n int);
+create table t6 (n int);
+show tables;
+Tables_in_test
+t1
+t4
+t5
+t6
+stop slave;
+reset slave;
+drop table t1,t4,t5,t6;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 14806279362..91e057da419 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1160,7 +1160,7 @@ Code2 char(2) NOT NULL default '',
PRIMARY KEY (Code)
) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU');
-INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
+INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent);
Continent Name Population
Oceania Sydney 3276207
@@ -2512,7 +2512,7 @@ Code2 char(2) NOT NULL default ''
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
-INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
+INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
@@ -2987,3 +2987,4 @@ select * from (select max(fld) from t1) as foo;
max(fld)
1
drop table t1;
+purge master logs before (select adddate(current_timestamp(), interval -4 day));
diff --git a/mysql-test/t/rpl_dual_pos_advance-master.opt b/mysql-test/t/rpl_dual_pos_advance-master.opt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/t/rpl_dual_pos_advance-master.opt
diff --git a/mysql-test/t/rpl_dual_pos_advance.test b/mysql-test/t/rpl_dual_pos_advance.test
new file mode 100644
index 00000000000..518fa9df885
--- /dev/null
+++ b/mysql-test/t/rpl_dual_pos_advance.test
@@ -0,0 +1,108 @@
+# This test checks that in a dual-head setup
+# A->B->A, where A has --log-slave-updates (why would it?
+# assume that there is a C as slave of A),
+# then the Exec_master_log_pos of SHOW SLAVE STATUS does
+# not stay too low on B(BUG#13023 due to events ignored because
+# of their server id).
+# It also will test BUG#13861.
+
+source include/master-slave.inc;
+
+
+# set up "dual head"
+
+connection slave;
+reset master;
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval change master to master_host="127.0.0.1",master_port=$SLAVE_MYPORT,master_user="root";
+
+start slave;
+
+# now we test it
+
+connection slave;
+
+create table t1 (n int);
+
+save_master_pos;
+connection master;
+sync_with_master;
+
+# Now test BUG#13861. This will be enabled when Guilhem fixes this
+# bug.
+
+# stop slave
+
+# create table t2 (n int); # create one ignored event
+
+# save_master_pos;
+# connection slave;
+# sync_with_master;
+
+# connection slave;
+
+# show tables;
+
+# save_master_pos;
+
+# create table t3 (n int);
+
+# connection master;
+
+# bug is that START SLAVE UNTIL may stop too late, we test that by
+# asking it to stop before creation of t3.
+
+# start slave until master_log_file="slave-bin.000001",master_log_pos=195;
+
+# wait until it's started (the position below is the start of "CREATE
+# TABLE t2") (otherwise wait_for_slave_to_stop may return at once)
+
+# select master_pos_wait("slave-bin.000001",137);
+
+# wait_for_slave_to_stop;
+
+# then BUG#13861 causes t3 to show up below (because stopped too
+# late).
+
+# show tables;
+
+# start slave;
+
+# BUG#13023 is that Exec_master_log_pos may stay too low "forever":
+
+connection master;
+
+create table t4 (n int); # create 3 ignored events
+create table t5 (n int);
+create table t6 (n int);
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+connection slave;
+
+save_master_pos;
+
+connection master;
+
+# then BUG#13023 caused hang below ("master" looks behind, while it's
+# not in terms of updates done).
+
+sync_with_master;
+
+show tables;
+
+# cleanup
+
+stop slave;
+reset slave;
+drop table t1,t4,t5,t6; # add t2 and t3 later
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+# End of 4.1 tests
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 5020902009d..758ec7909f6 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -665,7 +665,7 @@ CREATE TABLE t2 (
) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU');
-INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
+INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ');
select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent);
@@ -1526,7 +1526,7 @@ CREATE TABLE t1 (
) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX');
INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS');
-INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
+INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF');
INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM');
/*!40000 ALTER TABLE t1 ENABLE KEYS */;
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
@@ -1963,3 +1963,9 @@ select * from (select max(fld) from t1) as foo;
drop table t1;
+#
+# BUG #10308: purge log with subselect
+#
+
+purge master logs before (select adddate(current_timestamp(), interval -4 day));
+
diff --git a/sql/log.cc b/sql/log.cc
index 8e9555cc9b2..7ca499c17c7 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1353,7 +1353,8 @@ void MYSQL_LOG::new_file(bool need_lock)
to change base names at some point.
*/
THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */
- Rotate_log_event r(thd,new_name+dirname_length(new_name));
+ Rotate_log_event r(thd,new_name+dirname_length(new_name),
+ 0, LOG_EVENT_OFFSET, 0);
r.write(&log_file);
bytes_written += r.data_written;
}
@@ -1432,7 +1433,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
- pthread_mutex_lock(&LOCK_log);
+ safe_mutex_assert_owner(&LOCK_log);
do
{
if (my_b_append(&log_file,(byte*) buf,len))
@@ -1447,7 +1448,6 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
new_file(0);
err:
- pthread_mutex_unlock(&LOCK_log);
if (!error)
signal_update();
DBUG_RETURN(error);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ed6599f692f..4bfe502d77e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2962,10 +2962,39 @@ void Rotate_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_
#endif /* MYSQL_CLIENT */
+
/*
- Rotate_log_event::Rotate_log_event()
+ Rotate_log_event::Rotate_log_event() (2 constructors)
*/
+
+#ifndef MYSQL_CLIENT
+Rotate_log_event::Rotate_log_event(THD* thd_arg,
+ const char* new_log_ident_arg,
+ uint ident_len_arg, ulonglong pos_arg,
+ uint flags_arg)
+ :Log_event(), new_log_ident(new_log_ident_arg),
+ pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
+ (uint) strlen(new_log_ident_arg)), flags(flags_arg)
+{
+#ifndef DBUG_OFF
+ char buff[22];
+ DBUG_ENTER("Rotate_log_event::Rotate_log_event(THD*,...)");
+ DBUG_PRINT("enter",("new_log_ident %s pos %s flags %lu", new_log_ident_arg,
+ llstr(pos_arg, buff), flags));
+#endif
+ if (flags & DUP_NAME)
+ new_log_ident= my_strdup_with_length(new_log_ident_arg,
+ ident_len,
+ MYF(MY_WME));
+ DBUG_VOID_RETURN;
+}
+#endif
+
+
+Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
+ bool old_format)
+ :Log_event(buf, old_format), new_log_ident(0), flags(DUP_NAME)
Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
const Format_description_log_event* description_event)
:Log_event(buf, description_event) ,new_log_ident(NULL),alloced(0)
@@ -2983,12 +3012,9 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
(header_size+post_header_len));
ident_offset = post_header_len;
set_if_smaller(ident_len,FN_REFLEN-1);
- if (!(new_log_ident= my_strdup_with_length((byte*) buf +
- ident_offset,
- (uint) ident_len,
- MYF(MY_WME))))
- DBUG_VOID_RETURN;
- alloced = 1;
+ new_log_ident= my_strdup_with_length((byte*) buf + ident_offset,
+ (uint) ident_len,
+ MYF(MY_WME));
DBUG_VOID_RETURN;
}
@@ -3001,6 +3027,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
bool Rotate_log_event::write(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
+ DBUG_ASSERT(!(flags & ZERO_LEN)); // such an event cannot be written
int8store(buf + R_POS_OFFSET, pos);
return (write_header(file, ROTATE_HEADER_LEN + ident_len) ||
my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
diff --git a/sql/log_event.h b/sql/log_event.h
index 29580589a34..35bddd14d3b 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -640,6 +640,13 @@ public:
const char **error,
const Format_description_log_event
*description_event);
+ virtual int get_event_len()
+ {
+ return (cached_event_len ? cached_event_len :
+ (cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()));
+ }
+ static Log_event* read_log_event(const char* buf, int event_len,
+ const char **error, bool old_format);
/* returns the human readable name of the event's type */
const char* get_type_str();
};
@@ -1247,18 +1254,18 @@ public:
class Rotate_log_event: public Log_event
{
public:
+ enum {
+ ZERO_LEN= 1, // if event should report 0 as its length
+ DUP_NAME= 2 // if constructor should dup the string argument
+ };
const char* new_log_ident;
ulonglong pos;
uint ident_len;
- bool alloced;
+ uint flags;
#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,
- ulonglong pos_arg = LOG_EVENT_OFFSET)
- :Log_event(), new_log_ident(new_log_ident_arg),
- pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
- (uint) strlen(new_log_ident_arg)), alloced(0)
- {}
+ uint ident_len_arg,
+ ulonglong pos_arg, uint flags);
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
@@ -1271,10 +1278,18 @@ public:
const Format_description_log_event* description_event);
~Rotate_log_event()
{
- if (alloced)
- my_free((gptr) new_log_ident, MYF(0));
+ if (flags & DUP_NAME)
+ my_free((gptr) new_log_ident, MYF(MY_ALLOW_ZERO_PTR));
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
+ virtual int get_event_len()
+ {
+ if (flags & ZERO_LEN)
+ return 0;
+ if (cached_event_len == 0)
+ cached_event_len= LOG_EVENT_HEADER_LEN + get_data_size();
+ return cached_event_len;
+ }
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() const { return new_log_ident != 0; }
#ifndef MYSQL_CLIENT
diff --git a/sql/slave.cc b/sql/slave.cc
index 09b1d79b1de..cb52abc68b3 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1965,6 +1965,55 @@ static int count_relay_log_space(RELAY_LOG_INFO* rli)
}
+/*
+ Builds a Rotate from the ignored events' info and writes it to relay log.
+
+ SYNOPSIS
+ write_ignored_events_info_to_relay_log()
+ thd pointer to I/O thread's thd
+ mi
+
+ DESCRIPTION
+ Slave I/O thread, going to die, must leave a durable trace of the
+ ignored events' end position for the use of the slave SQL thread, by
+ calling this function. Only that thread can call it (see assertion).
+ */
+static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi)
+{
+ RELAY_LOG_INFO *rli= &mi->rli;
+ pthread_mutex_t *log_lock= rli->relay_log.get_log_lock();
+ DBUG_ASSERT(thd == mi->io_thd);
+ pthread_mutex_lock(log_lock);
+ if (rli->ign_master_log_name_end[0])
+ {
+ DBUG_PRINT("info",("writing a Rotate event to track down ignored events"));
+ Rotate_log_event *ev= new Rotate_log_event(thd, rli->ign_master_log_name_end,
+ 0, rli->ign_master_log_pos_end,
+ Rotate_log_event::DUP_NAME);
+ rli->ign_master_log_name_end[0]= 0;
+ /* can unlock before writing as slave SQL thd will soon see our Rotate */
+ pthread_mutex_unlock(log_lock);
+ if (likely((bool)ev))
+ {
+ ev->server_id= 0; // don't be ignored by slave SQL thread
+ if (unlikely(rli->relay_log.append(ev)))
+ sql_print_error("Slave I/O thread failed to write a Rotate event"
+ " to the relay log, "
+ "SHOW SLAVE STATUS may be inaccurate");
+ rli->relay_log.harvest_bytes_written(&rli->log_space_total);
+ flush_master_info(mi, 1);
+ delete ev;
+ }
+ else
+ sql_print_error("Slave I/O thread failed to create a Rotate event"
+ " (out of memory?), "
+ "SHOW SLAVE STATUS may be inaccurate");
+ }
+ else
+ pthread_mutex_unlock(log_lock);
+}
+
+
void init_master_info_with_options(MASTER_INFO* mi)
{
mi->master_log_name[0] = 0;
@@ -2561,7 +2610,7 @@ st_relay_log_info::st_relay_log_info()
{
group_relay_log_name[0]= event_relay_log_name[0]=
group_master_log_name[0]= 0;
- last_slave_error[0]=0; until_log_name[0]= 0;
+ last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0;
bzero((char*) &info_file, sizeof(info_file));
bzero((char*) &cache_buf, sizeof(cache_buf));
@@ -3154,12 +3203,20 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
wait for something for example inside of next_event().
*/
pthread_mutex_lock(&rli->data_lock);
-
+ /*
+ This tests if the position of the end of the last previous executed event
+ hits the UNTIL barrier.
+ We would prefer to test if the position of the start (or possibly) end of
+ the to-be-read event hits the UNTIL barrier, this is different if there
+ was an event ignored by the I/O thread just before (BUG#13861 to be
+ fixed).
+ */
if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
rli->is_until_satisfied())
{
+ char buf[22];
sql_print_error("Slave SQL thread stopped because it reached its"
- " UNTIL position %ld", (long) rli->until_pos());
+ " UNTIL position %s", llstr(rli->until_pos(), buf));
/*
Setting abort_slave flag because we do not want additional message about
error in query execution to be printed.
@@ -3347,6 +3404,7 @@ pthread_handler_t handle_slave_io(void *arg)
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
MASTER_INFO *mi = (MASTER_INFO*)arg;
+ RELAY_LOG_INFO *rli= &mi->rli;
char llbuff[22];
uint retry_count;
@@ -3589,16 +3647,16 @@ reconnect done to recover from failed read");
char llbuf1[22], llbuf2[22];
DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s \
ignore_log_space_limit=%d",
- llstr(mi->rli.log_space_limit,llbuf1),
- llstr(mi->rli.log_space_total,llbuf2),
- (int) mi->rli.ignore_log_space_limit));
+ llstr(rli->log_space_limit,llbuf1),
+ llstr(rli->log_space_total,llbuf2),
+ (int) rli->ignore_log_space_limit));
}
#endif
- if (mi->rli.log_space_limit && mi->rli.log_space_limit <
- mi->rli.log_space_total &&
- !mi->rli.ignore_log_space_limit)
- if (wait_for_relay_log_space(&mi->rli))
+ if (rli->log_space_limit && rli->log_space_limit <
+ rli->log_space_total &&
+ !rli->ignore_log_space_limit)
+ if (wait_for_relay_log_space(rli))
{
sql_print_error("Slave I/O thread aborted while waiting for relay \
log space");
@@ -3629,6 +3687,7 @@ err:
mysql_close(mysql);
mi->mysql=0;
}
+ write_ignored_events_info_to_relay_log(thd, mi);
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&mi->run_lock);
mi->slave_running = 0;
@@ -4013,6 +4072,7 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
if (unlikely(!rev->is_valid()))
DBUG_RETURN(1);
+ /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
DBUG_PRINT("info", ("master_log_pos: '%s' %d",
@@ -4263,6 +4323,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
int error= 0;
ulong inc_pos;
RELAY_LOG_INFO *rli= &mi->rli;
+ pthread_mutex_t *log_lock= rli->relay_log.get_log_lock();
DBUG_ENTER("queue_event");
if (mi->rli.relay_log.description_event_for_queue->binlog_version<4 &&
@@ -4271,11 +4332,6 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
pthread_mutex_lock(&mi->data_lock);
- /*
- TODO: figure out if other events in addition to Rotate
- require special processing.
- Guilhem 2003-06 : I don't think so.
- */
switch (buf[EVENT_TYPE_OFFSET]) {
case STOP_EVENT:
/*
@@ -4360,14 +4416,21 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
direct master (an unsupported, useless setup!).
*/
+ pthread_mutex_lock(log_lock);
+
if ((uint4korr(buf + SERVER_ID_OFFSET) == ::server_id) &&
!replicate_same_server_id)
{
/*
Do not write it to the relay log.
- We still want to increment, so that we won't re-read this event from the
- master if the slave IO thread is now stopped/restarted (more efficient if
- the events we are ignoring are big LOAD DATA INFILE).
+ a) We still want to increment mi->master_log_pos, so that we won't
+ re-read this event from the master if the slave IO thread is now
+ stopped/restarted (more efficient if the events we are ignoring are big
+ LOAD DATA INFILE).
+ b) We want to record that we are skipping events, for the information of
+ the slave SQL thread, otherwise that thread may let
+ rli->group_relay_log_pos stay too small if the last binlog's event is
+ ignored.
But events which were generated by this slave and which do not exist in
the master's binlog (i.e. Format_desc, Rotate & Stop) should not increment
mi->master_log_pos.
@@ -4376,6 +4439,10 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
buf[EVENT_TYPE_OFFSET]!=ROTATE_EVENT &&
buf[EVENT_TYPE_OFFSET]!=STOP_EVENT)
mi->master_log_pos+= inc_pos;
+ memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN);
+ DBUG_ASSERT(rli->ign_master_log_name_end[0]);
+ rli->ign_master_log_pos_end= mi->master_log_pos;
+ rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
}
else
@@ -4388,8 +4455,11 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
else
- error=3;
+ error= 3;
+ rli->ign_master_log_name_end[0]= 0; // last event is not ignored
}
+ pthread_mutex_unlock(log_lock);
+
err:
pthread_mutex_unlock(&mi->data_lock);
@@ -4773,6 +4843,27 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
rli->last_master_timestamp= 0;
DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count);
+
+ if (rli->ign_master_log_name_end[0])
+ {
+ /* We generate and return a Rotate, to make our positions advance */
+ DBUG_PRINT("info",("seeing an ignored end segment"));
+ ev= new Rotate_log_event(thd, rli->ign_master_log_name_end,
+ 0, rli->ign_master_log_pos_end,
+ Rotate_log_event::DUP_NAME |
+ Rotate_log_event::ZERO_LEN);
+ rli->ign_master_log_name_end[0]= 0;
+ if (unlikely(!ev))
+ {
+ errmsg= "Slave SQL thread failed to create a Rotate event "
+ "(out of memory?), SHOW SLAVE STATUS may be inaccurate";
+ goto err;
+ }
+ pthread_mutex_unlock(log_lock);
+ ev->server_id= 0; // don't be ignored by slave SQL thread
+ DBUG_RETURN(ev);
+ }
+
/*
We can, and should release data_lock while we are waiting for
update. If we do not, show slave status will block
diff --git a/sql/slave.h b/sql/slave.h
index cbb885ea48b..4d3c338680d 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -302,6 +302,17 @@ typedef struct st_relay_log_info
*/
ulong trans_retries, retried_trans;
+ /*
+ If the end of the hot relay log is made of master's events ignored by the
+ slave I/O thread, these two keep track of the coords (in the master's
+ binlog) of the last of these events seen by the slave I/O thread. If not,
+ ign_master_log_name_end[0] == 0.
+ As they are like a Rotate event read/written from/to the relay log, they
+ are both protected by rli->relay_log.LOCK_log.
+ */
+ char ign_master_log_name_end[FN_REFLEN];
+ ulonglong ign_master_log_pos_end;
+
st_relay_log_info();
~st_relay_log_info();