#At file:///home/daogangqu/mysql/bzrwork/wl4033/mysql-5.1-rep%2B2/ based on revid:li-bing.song@stripped
3185 Dao-Gang.Qu@stripped 2010-05-04
WL#344 Support for informational log events
Adding a new ignorable event, and its incremental sub-hierarchy,
which have as default that if their type code are not recognized,
these events are just ignored and replication keeps going as usual.
@ mysql-test/suite/rpl/r/rpl_ignorable_event.result
Test result for wl#4033.
@ mysql-test/suite/rpl/t/rpl_ignorable_event.test
Added test to verify if the 'Comment_log_event' is
written into binlog with its row event.
@ sql/log.cc
Added code to write ignorable log event to binlog.
@ sql/log_event.cc
Added code to create an object of 'Ignorable_log_event' for unrecognized
sub-class. So that SLAVE SQL THREAD can ignore an unrecognized one.
@ sql/log_event.h
Added Ignorable_log_event class and its sub-class 'Comment_log_event'
to send over ignorable data to the slave.
@ sql/slave.cc
Added code to handle recognized sub-class of Ignorable_log_event
according to its logic and treat unrecognized sub-class as its
base class 'Ignorable_log_event' and ignore it after update
the positions of the relay log.
@ sql/sql_class.cc
Added code to write the 'Comment_log_event' into binlog
with its row event.
added:
mysql-test/suite/rpl/r/rpl_ignorable_event.result
mysql-test/suite/rpl/t/rpl_ignorable_event.test
modified:
sql/log.cc
sql/log.h
sql/log_event.cc
sql/log_event.h
sql/slave.cc
sql/sql_class.cc
=== added file 'mysql-test/suite/rpl/r/rpl_ignorable_event.result'
--- a/mysql-test/suite/rpl/r/rpl_ignorable_event.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_ignorable_event.result 2010-05-04 08:34:02 +0000
@@ -0,0 +1,48 @@
+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;
+create table t1(a int, b int);
+insert into t1(a,b) values(1,1),(2,1),(3,1);
+update t1 set a = a + 5 where b = 1;
+delete from t1 where a = 6;
+insert into t1(a,b) values(1,2);
+insert into t1(a,b) values(1,3);
+insert into t1(a,b) values(1,4);
+SHOW BINLOG EVENTS;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 109 Server ver: 5.1.46-debug-log, Binlog ver: 4
+master-bin.000001 109 Query 1 201 use `test`; create table t1(a int, b int)
+master-bin.000001 201 Ignorable 1 264 #insert into t1(a,b) values(1,1),(2,1),(3,1)
+master-bin.000001 264 Query 1 332 BEGIN
+master-bin.000001 332 Table_map 1 374 table_id: 23 (test.t1)
+master-bin.000001 374 Write_rows 1 430 table_id: 23 flags: STMT_END_F
+master-bin.000001 430 Query 1 499 COMMIT
+master-bin.000001 499 Ignorable 1 554 #update t1 set a = a + 5 where b = 1
+master-bin.000001 554 Query 1 622 BEGIN
+master-bin.000001 622 Table_map 1 664 table_id: 23 (test.t1)
+master-bin.000001 664 Update_rows 1 748 table_id: 23 flags: STMT_END_F
+master-bin.000001 748 Query 1 817 COMMIT
+master-bin.000001 817 Ignorable 1 863 #delete from t1 where a = 6
+master-bin.000001 863 Query 1 931 BEGIN
+master-bin.000001 931 Table_map 1 973 table_id: 23 (test.t1)
+master-bin.000001 973 Delete_rows 1 1011 table_id: 23 flags: STMT_END_F
+master-bin.000001 1011 Query 1 1080 COMMIT
+master-bin.000001 1080 Ignorable 1 1131 #insert into t1(a,b) values(1,2)
+master-bin.000001 1131 Query 1 1199 BEGIN
+master-bin.000001 1199 Table_map 1 1241 table_id: 23 (test.t1)
+master-bin.000001 1241 Write_rows 1 1279 table_id: 23 flags: STMT_END_F
+master-bin.000001 1279 Query 1 1348 COMMIT
+master-bin.000001 1348 Ignorable 1 1399 #insert into t1(a,b) values(1,3)
+master-bin.000001 1399 Query 1 1467 BEGIN
+master-bin.000001 1467 Table_map 1 1509 table_id: 23 (test.t1)
+master-bin.000001 1509 Write_rows 1 1547 table_id: 23 flags: STMT_END_F
+master-bin.000001 1547 Query 1 1616 COMMIT
+master-bin.000001 1616 Ignorable 1 1667 #insert into t1(a,b) values(1,4)
+master-bin.000001 1667 Query 1 1735 BEGIN
+master-bin.000001 1735 Table_map 1 1777 table_id: 23 (test.t1)
+master-bin.000001 1777 Write_rows 1 1815 table_id: 23 flags: STMT_END_F
+master-bin.000001 1815 Query 1 1884 COMMIT
+DROP TABLE t1;
=== added file 'mysql-test/suite/rpl/t/rpl_ignorable_event.test'
--- a/mysql-test/suite/rpl/t/rpl_ignorable_event.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_ignorable_event.test 2010-05-04 08:34:02 +0000
@@ -0,0 +1,16 @@
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+
+create table t1(a int, b int);
+
+insert into t1(a,b) values(1,1),(2,1),(3,1);
+update t1 set a = a + 5 where b = 1;
+delete from t1 where a = 6;
+insert into t1(a,b) values(1,2);
+insert into t1(a,b) values(1,3);
+insert into t1(a,b) values(1,4);
+SHOW BINLOG EVENTS;
+
+DROP TABLE t1;
+sync_slave_with_master;
+
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2010-03-17 11:31:50 +0000
+++ b/sql/log.cc 2010-05-04 08:34:02 +0000
@@ -5031,6 +5031,25 @@ bool MYSQL_BIN_LOG::write_incident(THD *
DBUG_RETURN(error);
}
+bool MYSQL_BIN_LOG::write_ignorable_event(Ignorable_log_event* ev, bool lock)
+{
+ uint error= 0;
+ DBUG_ENTER("MYSQL_BIN_LOG::write_information");
+ if (lock)
+ pthread_mutex_lock(&LOCK_log);
+ error= ev->write(&log_file);
+ if (lock)
+ {
+ if (!error && !(error= flush_and_sync(0)))
+ {
+ signal_update();
+ rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+ }
+ pthread_mutex_unlock(&LOCK_log);
+ }
+ DBUG_RETURN(error);
+}
+
/**
Write a cached log entry to the binary log.
- To support transaction over replication, we wrap the transaction
=== modified file 'sql/log.h'
--- a/sql/log.h 2010-02-13 09:42:41 +0000
+++ b/sql/log.h 2010-05-04 08:34:02 +0000
@@ -19,6 +19,7 @@
class Relay_log_info;
class Format_description_log_event;
+class Ignorable_log_event;
bool trans_has_updated_trans_table(const THD* thd);
bool stmt_has_updated_trans_table(const THD *thd);
@@ -395,6 +396,7 @@ public:
bool write(Log_event* event_info);
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
bool write_incident(THD *thd, bool lock);
+ bool write_ignorable_event(Ignorable_log_event* ev, bool lock);
int write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
void set_write_error(THD *thd);
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-03-03 14:43:35 +0000
+++ b/sql/log_event.cc 2010-05-04 08:34:02 +0000
@@ -644,6 +644,8 @@ const char* Log_event::get_type_str(Log_
case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
case INCIDENT_EVENT: return "Incident";
+ case IGNORABLE_LOG_EVENT: return "Ignorable";
+ case COMMENT_LOG_EVENT: return "Ignorable";
default: return "Unknown"; /* impossible */
}
}
@@ -1294,7 +1296,19 @@ Log_event* Log_event::read_log_event(con
case INCIDENT_EVENT:
ev = new Incident_log_event(buf, event_len, description_event);
break;
+ case COMMENT_LOG_EVENT:
+ ev= new Comment_log_event(buf, event_len, description_event);
+ break;
default:
+ /*
+ Create an object of Ignorable_log_event for unrecognized sub-class.
+ So that SLAVE SQL THREAD can ignore the unrecognized one.
+ */
+ if (uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F)
+ {
+ ev= new Ignorable_log_event(buf, description_event);
+ DBUG_RETURN(ev);
+ }
DBUG_PRINT("error",("Unknown event code: %d",
(int) buf[EVENT_TYPE_OFFSET]));
ev= NULL;
@@ -3811,6 +3825,8 @@ Format_description_log_event(uint8 binlo
post_header_len[DELETE_ROWS_EVENT-1]= 6;);
post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;
post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
+ post_header_len[IGNORABLE_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
+ post_header_len[COMMENT_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
// Sanity-check that all post header lengths are initialized.
IF_DBUG({
@@ -9639,6 +9655,80 @@ Incident_log_event::write_data_body(IO_C
}
+Ignorable_log_event::Ignorable_log_event(const char *buf,
+ const Format_description_log_event *descr_event)
+ : Log_event(buf, descr_event)
+{
+ DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
+ DBUG_VOID_RETURN;
+}
+
+Ignorable_log_event::~Ignorable_log_event()
+{
+}
+
+
+Comment_log_event::Comment_log_event(const char *buf, uint event_len,
+ const Format_description_log_event *descr_event)
+ : Ignorable_log_event(buf, descr_event)
+{
+ DBUG_ENTER("Comment_log_event::Comment_log_event");
+ uint8 const common_header_len=
+ descr_event->common_header_len;
+ uint8 const post_header_len=
+ descr_event->post_header_len[COMMENT_LOG_EVENT-1];
+
+ DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
+ event_len, common_header_len, post_header_len));
+
+ char const *ptr= buf + common_header_len + post_header_len;
+ char const *const str_end= buf + event_len;
+ uint8 len= 0; // Assignment to keep compiler happy
+ const char *str= NULL; // Assignment to keep compiler happy
+ read_str(&ptr, str_end, &str, &len);
+ m_comment.str= const_cast<char*>(str);
+ m_comment.length= len;
+ DBUG_PRINT("info", ("m_comment: %s", m_comment.str));
+ DBUG_VOID_RETURN;
+}
+
+Comment_log_event::~Comment_log_event()
+{
+}
+
+#ifndef MYSQL_CLIENT
+void Comment_log_event::pack_info(Protocol *protocol)
+{
+ char buf[256];
+ size_t bytes;
+ bytes= my_snprintf(buf, sizeof(buf), "#%s", m_comment.str);
+ protocol->store(buf, bytes, &my_charset_bin);
+}
+#endif
+
+#ifdef MYSQL_CLIENT
+void
+Comment_log_event::print(FILE *file,
+ PRINT_EVENT_INFO *print_event_info)
+{
+ if (print_event_info->short_form)
+ return;
+
+ Write_on_release_cache cache(&print_event_info->head_cache, file);
+ print_header(&cache, print_event_info, FALSE);
+ my_b_printf(&cache, "\tIgnorable\n");
+ my_b_printf(&cache, "# comment: %s\n", m_comment.str);
+}
+#endif
+
+bool
+Comment_log_event::write_data_body(IO_CACHE *file)
+{
+ DBUG_ENTER("Comment_log_event::write_data_body");
+ DBUG_RETURN(write_str(file, m_comment.str, (uint) m_comment.length));
+}
+
+
#ifdef MYSQL_CLIENT
/**
The default values for these variables should be values that are
=== modified file 'sql/log_event.h'
--- a/sql/log_event.h 2010-02-14 01:14:36 +0000
+++ b/sql/log_event.h 2010-05-04 08:34:02 +0000
@@ -251,6 +251,7 @@ struct sql_ex_info
#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
#define INCIDENT_HEADER_LEN 2
#define HEARTBEAT_HEADER_LEN 0
+#define IGNORABLE_HEADER_LEN 0
/*
Max number of possible extra bytes in a replication event compared to a
packet (i.e. a query) sent from client to master;
@@ -489,6 +490,13 @@ struct sql_ex_info
#define LOG_EVENT_RELAY_LOG_F 0x40
/**
+ @def LOG_EVENT_IGNORABLE_F
+
+ Events with this flag set are ignorable on slave
+*/
+#define LOG_EVENT_IGNORABLE_F 0x80
+
+/**
@def OPTIONS_WRITTEN_TO_BIN_LOG
OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must
@@ -585,7 +593,16 @@ enum Log_event_type
to ensure master's online status to slave
*/
HEARTBEAT_LOG_EVENT= 27,
-
+
+ /*
+ In some situations, it is necessary to send over ignorable
+ data to the slave: data that a slave can handle in case there
+ is code for handling it, but which can be ignored if it is not
+ recognized.
+ */
+ IGNORABLE_LOG_EVENT= 28,
+ COMMENT_LOG_EVENT= 29,
+
/*
Add new events here - right above this comment!
Existing events (except ENUM_END_EVENT) should never change their numbers
@@ -1065,6 +1082,7 @@ public:
void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; }
bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; }
bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; }
+ bool is_ignorable_event() const { return flags & LOG_EVENT_IGNORABLE_F; }
inline bool use_trans_cache() const
{
return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
@@ -3994,6 +4012,86 @@ private:
LEX_STRING m_message;
};
+
+/**
+ @class Ignorable_log_event
+ Ignorable log event to send over ignorable data to the slave,
+ and its incremental sub-hierarchy, which have as default that if
+ their type code are not recognized, these events are just ignored
+ and replication keeps going as usual.
+**/
+class Ignorable_log_event : public Log_event {
+public:
+#ifndef MYSQL_CLIENT
+ Ignorable_log_event(THD *thd_arg) : Log_event(thd_arg, 0, FALSE)
+ {
+ DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
+ set_ignorable_event();
+ DBUG_VOID_RETURN;
+ }
+#endif
+
+ Ignorable_log_event(const char *buf,
+ const Format_description_log_event *descr_event);
+
+ virtual ~Ignorable_log_event();
+
+#ifdef MYSQL_CLIENT
+ virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info) { return; }
+#endif
+
+ virtual Log_event_type get_type_code() { return IGNORABLE_LOG_EVENT; }
+
+ virtual bool is_valid() const { return 1; }
+
+ virtual int get_data_size() { return IGNORABLE_HEADER_LEN; }
+
+private:
+ void set_ignorable_event() { flags |= LOG_EVENT_IGNORABLE_F; }
+};
+
+
+class Comment_log_event : public Ignorable_log_event {
+public:
+#ifndef MYSQL_CLIENT
+ Comment_log_event(THD *thd_arg, LEX_STRING const comment)
+ : Ignorable_log_event(thd_arg)
+ {
+ DBUG_ENTER("Comment_log_event::Comment_log_event");
+ DBUG_PRINT("enter", ("comment: %s", comment.str));
+ m_comment= comment;
+ DBUG_VOID_RETURN;
+ }
+#endif
+
+#ifndef MYSQL_CLIENT
+ void pack_info(Protocol*);
+#endif
+
+ Comment_log_event(const char *buf, uint event_len,
+ const Format_description_log_event *descr_event);
+
+ virtual ~Comment_log_event();
+
+#ifdef MYSQL_CLIENT
+ virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
+#endif
+ virtual bool write_data_body(IO_CACHE *file);
+
+ virtual Log_event_type get_type_code() { return COMMENT_LOG_EVENT; }
+
+ virtual int get_data_size()
+ {
+ return IGNORABLE_HEADER_LEN + 1 + (uint) m_comment.length;
+ }
+
+private:
+
+ LEX_STRING m_comment;
+};
+
+
+
static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache,
FILE *file)
{
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2010-02-12 23:30:44 +0000
+++ b/sql/slave.cc 2010-05-04 08:34:02 +0000
@@ -2369,6 +2369,51 @@ static int exec_relay_log_event(THD* thd
delete ev;
DBUG_RETURN(1);
}
+
+ /*
+ Every concrete sub-class of Ignorable_log_event will be handled
+ according to its logic if the SLAVE SQL THREAD can recognize it.
+ Else the unrecognized one is treated as an Ignorable_log_event
+ and is ignored after update the positions of the relay log.
+ */
+ if (ev && ev->is_ignorable_event())
+ {
+ int err_update_pos= 0;
+ pthread_mutex_unlock(&rli->data_lock);
+ switch(ev->get_type_code()) {
+ case IGNORABLE_LOG_EVENT:
+ case COMMENT_LOG_EVENT:
+ err_update_pos= ev->update_pos(rli);
+ delete ev;
+ break;
+ /*
+ TODO: Added new ignorable event and handle it
+ according to the concrete class
+ case table_checksum_log_event:
+ ......
+ case lock_log_event:
+ ......
+ */
+ default:
+ rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
+ "It should never be happened.");
+ DBUG_RETURN(1);
+ }
+ if (err_update_pos)
+ {
+ char buf[22];
+ rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
+ "It was not possible to update the positions"
+ " of the relay log information: the slave may"
+ " be in an inconsistent state."
+ " Stopped in %s position %s",
+ rli->group_relay_log_name,
+ llstr(rli->group_relay_log_pos, buf));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+ }
+
if (ev)
{
int exec_res;
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2010-03-03 14:43:35 +0000
+++ b/sql/sql_class.cc 2010-05-04 08:34:02 +0000
@@ -4359,7 +4359,12 @@ int THD::binlog_query(THD::enum_binlog_q
("is_current_stmt_binlog_format_row: %d",
is_current_stmt_binlog_format_row()));
if (is_current_stmt_binlog_format_row())
- DBUG_RETURN(0);
+ {
+ /* Write the 'query' information even into binlog with its row event */
+ LEX_STRING const comment= { const_cast<char*>(query_arg), query_len };
+ Comment_log_event* ev= new Comment_log_event(this, comment);
+ DBUG_RETURN(mysql_bin_log.write_ignorable_event(ev, TRUE));
+ }
/* Fall through */
/*
Attachment: [text/bzr-bundle] bzr/dao-gang.qu@sun.com-20100504083402-emdti8zzjstl0z9s.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-rep+2 branch (Dao-Gang.Qu:3185) WL#344 | Dao-Gang.Qu | 4 May |