#At file:///media/sda3/work/mysql/bzrwork/b38734/5.1-rpl/
2661 He Zhenxing 2008-08-22
BUG#38734 rpl_server_id2 sync_with_master failed
Rotate event is automatically generated and written when rotating binary
log or relay log. Rotate events for relay logs are usually ignored by slave
SQL thread becuase they have the same server id as that of the slave.
However, if --replicate-same-server-id is enabled, rotate event
for relay log would be treated as if it's a rotate event from master, and
would be executed by slave to update the rli->group_master_log_name and
rli->group_master_log_pos to a wrong value and cause the MASTER_POS_WAIT
function to fail and return NULL.
This patch fixed this problem by setting a flag bit in the event to tell the
SQL thread to ignore these Rotate events generated for relay logs.
modified:
sql/log.cc
sql/log.h
sql/log_event.cc
sql/log_event.h
sql/slave.cc
per-file messages:
sql/log.cc
Add a parameter to MYSQL_BIN_LOG::new_file to distinguish create new file for binary
log or relay log.
sql/log.h
Add a parameter to MYSQL_BIN_LOG::new_file to distinguish create new file for binary
log or relay log.
sql/log_event.cc
If LOG_EVENT_IGNORE_F is set in the event flags, ignore it
sql/log_event.h
Add LOG_EVENT_IGNORE_F flag to Log_event flags, events has this flags set will be
ignored by slave SQL thread
Add RELAY_LOG flag to Rotate_log_event flags
sql/slave.cc
Set parameter relay_log to 1 when creating new relay log files
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-07-22 10:41:55 +0000
+++ b/sql/log.cc 2008-08-22 05:06:23 +0000
@@ -3388,15 +3388,15 @@ bool MYSQL_BIN_LOG::is_active(const char
method).
*/
-void MYSQL_BIN_LOG::new_file()
+void MYSQL_BIN_LOG::new_file(bool relay_log)
{
- new_file_impl(1);
+ new_file_impl(1, relay_log);
}
-void MYSQL_BIN_LOG::new_file_without_locking()
+void MYSQL_BIN_LOG::new_file_without_locking(bool relay_log)
{
- new_file_impl(0);
+ new_file_impl(0, relay_log);
}
@@ -3409,7 +3409,7 @@ void MYSQL_BIN_LOG::new_file_without_loc
The new file name is stored last in the index file
*/
-void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
+void MYSQL_BIN_LOG::new_file_impl(bool need_lock, bool relay_log)
{
char new_name[FN_REFLEN], *new_name_ptr, *old_name;
@@ -3468,7 +3468,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool n
to change base names at some point.
*/
Rotate_log_event r(new_name+dirname_length(new_name),
- 0, LOG_EVENT_OFFSET, 0);
+ 0, LOG_EVENT_OFFSET, relay_log ? Rotate_log_event::RELAY_LOG :
0);
r.write(&log_file);
bytes_written += r.data_written;
}
=== modified file 'sql/log.h'
--- a/sql/log.h 2007-10-30 08:03:34 +0000
+++ b/sql/log.h 2008-08-22 05:06:23 +0000
@@ -268,8 +268,8 @@ class MYSQL_BIN_LOG: public TC_LOG, priv
new_file() is locking. new_file_without_locking() does not acquire
LOCK_log.
*/
- void new_file_without_locking();
- void new_file_impl(bool need_lock);
+ void new_file_without_locking(bool relay_log=0);
+ void new_file_impl(bool need_lock, bool relay_log=0);
public:
MYSQL_LOG::generate_name;
@@ -341,7 +341,7 @@ public:
bool open_index_file(const char *index_file_name_arg,
const char *log_name);
/* Use this to start writing a new log file */
- void new_file();
+ void new_file(bool relay_log=0);
bool write(Log_event* event_info); // binary log write
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2008-08-06 10:41:27 +0000
+++ b/sql/log_event.cc 2008-08-22 05:06:23 +0000
@@ -725,6 +725,9 @@ Log_event::do_shall_skip(Relay_log_info
(ulong) server_id, (ulong) ::server_id,
rli->replicate_same_server_id,
rli->slave_skip_counter));
+ DBUG_PRINT("info", ("ev->type=%d, ev->flags=%d", get_type_code(), flags));
+ if (flags & LOG_EVENT_IGNORE_F)
+ return EVENT_SKIP_IGNORE;
if (server_id == ::server_id && !rli->replicate_same_server_id ||
rli->slave_skip_counter == 1 && rli->is_in_group())
return EVENT_SKIP_IGNORE;
@@ -4054,6 +4057,8 @@ Rotate_log_event::Rotate_log_event(const
#endif
if (flags & DUP_NAME)
new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
+ if (flags & RELAY_LOG)
+ Log_event::flags |= LOG_EVENT_IGNORE_F;
DBUG_VOID_RETURN;
}
#endif
@@ -4144,6 +4149,7 @@ int Rotate_log_event::do_update_pos(Rela
relay log, which shall not change the group positions.
*/
if ((server_id != ::server_id || rli->replicate_same_server_id) &&
+ !(Log_event::flags & LOG_EVENT_IGNORE_F) &&
!rli->is_in_group())
{
DBUG_PRINT("info", ("old group_master_log_name: '%s' "
=== modified file 'sql/log_event.h'
--- a/sql/log_event.h 2008-07-31 06:24:27 +0000
+++ b/sql/log_event.h 2008-08-22 05:06:23 +0000
@@ -449,6 +449,9 @@ struct sql_ex_info
*/
#define LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F 0x10
+/* Event with this flag set will be ignored by SQL thread */
+#define LOG_EVENT_IGNORE_F 0x20
+
/**
@def OPTIONS_WRITTEN_TO_BIN_LOG
@@ -2518,7 +2521,8 @@ class Rotate_log_event: public Log_event
{
public:
enum {
- DUP_NAME= 2 // if constructor should dup the string argument
+ DUP_NAME= 2, // if constructor should dup the string argument
+ RELAY_LOG= 4 // generated by slave for relay log
};
const char* new_log_ident;
ulonglong pos;
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2008-06-30 20:11:18 +0000
+++ b/sql/slave.cc 2008-08-22 05:06:23 +0000
@@ -4029,7 +4029,7 @@ void rotate_relay_log(Master_info* mi)
}
/* If the relay log is closed, new_file() will do nothing. */
- rli->relay_log.new_file();
+ rli->relay_log.new_file(1);
/*
We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately