[Commits] Rev 3008: MWL#234: @@do_not_replicate. in http://bazaar.launchpad.net/~maria-captains/maria/5.2

knielsen at knielsen-hq.org knielsen at knielsen-hq.org
Thu Aug 4 17:10:01 EEST 2011


At http://bazaar.launchpad.net/~maria-captains/maria/5.2

------------------------------------------------------------
revno: 3008
revision-id: knielsen at knielsen-hq.org-20110804141000-hahpy5hq8lfsy4yz
parent: knielsen at knielsen-hq.org-20110801085624-tltcaz0w4sits9gh
committer: knielsen at knielsen-hq.org
branch nick: work-5.2-mwl234
timestamp: Thu 2011-08-04 16:10:00 +0200
message:
  MWL#234: @@do_not_replicate.
  
  Stage 1 implementation: filtering only on slave side.
  
  Also missing protection from changing @@do_not_replicate in the middle of
  a binlog event group (statement or transaction).
=== modified file 'client/mysqlbinlog.cc'
--- a/client/mysqlbinlog.cc	2011-05-03 16:10:10 +0000
+++ b/client/mysqlbinlog.cc	2011-08-04 14:10:00 +0000
@@ -671,6 +671,31 @@ print_use_stmt(PRINT_EVENT_INFO* pinfo,
 
 
 /**
+   Print "SET do_not_replicate=..." statement when needed.
+
+   Not all servers support this (only MariaDB from some version on). So we
+   mark the SET to only execute from the version of MariaDB that supports it,
+   and also only output it if we actually see events with the flag set, to not
+   get spurious errors on MySQL at Oracle servers of higher version that do not
+   support the flag.
+
+   So we start out assuming @@do_not_replicate is 0, and only output a SET
+   statement when it changes.
+*/
+static void
+print_do_not_replicate_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev)
+{
+  int cur_val;
+
+  cur_val= (ev->flags & LOG_EVENT_DO_NOT_REPLICATE_F) != 0;
+  if (cur_val == pinfo->do_not_replicate)
+    return;                                     /* Not changed. */
+  fprintf(result_file, "/*!50400 SET do_not_replicate=%d*/%s\n",
+          cur_val, pinfo->delimiter);
+  pinfo->do_not_replicate= cur_val;
+}
+
+/**
   Prints the given event in base64 format.
 
   The header is printed to the head cache and the body is printed to
@@ -802,7 +827,10 @@ Exit_status process_event(PRINT_EVENT_IN
           goto end;
       }
       else
+      {
+        print_do_not_replicate_statement(print_event_info, ev);
         ev->print(result_file, print_event_info);
+      }
       break;
     }
 
@@ -832,7 +860,10 @@ Exit_status process_event(PRINT_EVENT_IN
           goto end;
       }
       else
+      {
+        print_do_not_replicate_statement(print_event_info, ev);
         ce->print(result_file, print_event_info, TRUE);
+      }
 
       // If this binlog is not 3.23 ; why this test??
       if (glob_description_event->binlog_version >= 3)
@@ -927,6 +958,7 @@ Exit_status process_event(PRINT_EVENT_IN
       if (!shall_skip_database(exlq->db))
       {
         print_use_stmt(print_event_info, exlq);
+        print_do_not_replicate_statement(print_event_info, ev);
         if (fname)
         {
           convert_path_to_forward_slashes(fname);
@@ -1030,6 +1062,12 @@ Exit_status process_event(PRINT_EVENT_IN
       }
       /* FALL THROUGH */
     }
+    case INTVAR_EVENT:
+    case RAND_EVENT:
+    case USER_VAR_EVENT:
+    case XID_EVENT:
+      print_do_not_replicate_statement(print_event_info, ev);
+      /* Fall through ... */
     default:
       ev->print(result_file, print_event_info);
     }

=== modified file 'configure.in'
--- a/configure.in	2011-06-11 11:28:37 +0000
+++ b/configure.in	2011-08-04 14:10:00 +0000
@@ -13,7 +13,7 @@ dnl When changing the major version numb
 dnl statement in mysqlbinlog::check_master_version().  You may also need
 dnl to update version.c in ndb.
 
-AC_INIT([MariaDB Server], [5.2.7-MariaDB], [], [mysql])
+AC_INIT([MariaDB Server], [5.4.0-MariaDB], [], [mysql])
 
 AC_CONFIG_SRCDIR([sql/mysqld.cc])
 AC_CANONICAL_SYSTEM

=== added file 'mysql-test/suite/rpl/r/rpl_do_not_replicate.result'
--- a/mysql-test/suite/rpl/r/rpl_do_not_replicate.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_do_not_replicate.result	2011-08-04 14:10:00 +0000
@@ -0,0 +1,100 @@
+include/master-slave.inc
+[connection master]
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+START SLAVE;
+SET do_not_replicate=0;
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
+INSERT INTO t1(a) VALUES (1);
+INSERT INTO t2(a) VALUES (1);
+SET do_not_replicate=1;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t1(a) VALUES (2);
+INSERT INTO t2(a) VALUES (2);
+SHOW TABLES;
+Tables_in_test
+t1
+t2
+SELECT * FROM t1;
+a       b
+1       NULL
+SELECT * FROM t2;
+a       b
+1       NULL
+DROP TABLE t3;
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=0;
+START SLAVE;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t3(a) VALUES(2);
+SELECT * FROM t3;
+a       b
+2       NULL
+DROP TABLE t3;
+TRUNCATE t1;
+RESET MASTER;
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (1,0);
+SET do_not_replicate=1;
+INSERT INTO t1 VALUES (2,0);
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (3,0);
+SELECT * FROM t1 ORDER by a;
+a       b
+1       0
+2       0
+3       0
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+TRUNCATE t1;
+SELECT * FROM t1 ORDER by a;
+a       b
+1       0
+2       0
+3       0
+START SLAVE;
+SELECT * FROM t1 ORDER by a;
+a       b
+1       0
+3       0
+TRUNCATE t1;
+STOP SLAVE;
+SET GLOBAL sql_slave_skip_counter=2;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+START SLAVE;
+SET @old_binlog_format= @@binlog_format;
+SET binlog_format= statement;
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (1,5);
+SET do_not_replicate=1;
+INSERT INTO t1 VALUES (2,5);
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (3,5);
+INSERT INTO t1 VALUES (4,5);
+SET binlog_format= @old_binlog_format;
+SELECT * FROM t1;
+a       b
+4       5
+TRUNCATE t1;
+BINLOG '66I6Tg8BAAAAZgAAAGoAAAABAAQANS40LjAtTWFyaWFEQi12YWxncmluZC1tYXgtZGVidWctbG9n
+AAAAAAAAAAAAAAAAAADrojpOEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC';
+BINLOG 'HaM6ThMBAAAAKgAAANgAAAAAgA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
+HaM6ThcBAAAAJgAAAP4AAAAAgA8AAAAAAAEAAv/8AQAAAAgAAAA=';
+BINLOG 'JqM6ThMBAAAAKgAAALEBAAAAAA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
+JqM6ThcBAAAAJgAAANcBAAAAAA8AAAAAAAEAAv/8AgAAAAgAAAA=';
+SELECT * FROM t1 ORDER BY a;
+a       b
+1       8
+2       8
+SELECT * FROM t1 ORDER by a;
+a       b
+2       8
+SET do_not_replicate=0;
+DROP TABLE t1,t2;
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=0;
+START SLAVE;
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl/t/rpl_do_not_replicate.test'
--- a/mysql-test/suite/rpl/t/rpl_do_not_replicate.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_do_not_replicate.test	2011-08-04 14:10:00 +0000
@@ -0,0 +1,173 @@
+--source include/master-slave.inc
+--source include/have_innodb.inc
+
+connection slave;
+--error ER_SLAVE_MUST_STOP
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+START SLAVE;
+
+connection master;
+SET do_not_replicate=0;
+
+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=innodb;
+INSERT INTO t1(a) VALUES (1);
+INSERT INTO t2(a) VALUES (1);
+
+SET do_not_replicate=1;
+
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t1(a) VALUES (2);
+INSERT INTO t2(a) VALUES (2);
+
+sync_slave_with_master;
+connection slave;
+SHOW TABLES;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+connection master;
+DROP TABLE t3;
+
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=0;
+START SLAVE;
+
+connection master;
+CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam;
+INSERT INTO t3(a) VALUES(2);
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t3;
+connection master;
+DROP TABLE t3;
+
+#
+# Test that the slave will preserve the @@do_not_replicate flag in its
+# own binlog.
+#
+
+TRUNCATE t1;
+sync_slave_with_master;
+connection slave;
+RESET MASTER;
+
+connection master;
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (1,0);
+SET do_not_replicate=1;
+INSERT INTO t1 VALUES (2,0);
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (3,0);
+
+sync_slave_with_master;
+connection slave;
+# Since slave has @@replicate_ignore_do_not_replicate=0, it should have
+# applied all events.
+SELECT * FROM t1 ORDER by a;
+
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+let $SLAVE_DATADIR= `select @@datadir`;
+
+connection master;
+TRUNCATE t1;
+
+# Now apply the slave binlog to the master, to check that both the slave
+# and mysqlbinlog will preserve the @@do_not_replicate flag.
+--exec $MYSQL_BINLOG $SLAVE_DATADIR/slave-bin.000001 > $MYSQLTEST_VARDIR/tmp/rpl_do_not_replicate.binlog
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/rpl_do_not_replicate.binlog
+
+# The master should have all three events.
+SELECT * FROM t1 ORDER by a;
+
+# The slave should be missing event 2, which is marked with the
+# @@do_not_replicate flag.
+
+connection slave;
+START SLAVE;
+
+connection master;
+sync_slave_with_master;
+
+connection slave;
+SELECT * FROM t1 ORDER by a;
+
+#
+# Test that @@sql_slave_skip_counter does not count skipped @@do_not_replicate
+# events.
+#
+
+connection master;
+TRUNCATE t1;
+
+sync_slave_with_master;
+connection slave;
+STOP SLAVE;
+SET GLOBAL sql_slave_skip_counter=2;
+SET GLOBAL replicate_ignore_do_not_replicate=1;
+START SLAVE;
+
+connection master;
+# Need to fix @@binlog_format to get consistent event count.
+SET @old_binlog_format= @@binlog_format;
+SET binlog_format= statement;
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (1,5);
+SET do_not_replicate=1;
+INSERT INTO t1 VALUES (2,5);
+SET do_not_replicate=0;
+INSERT INTO t1 VALUES (3,5);
+INSERT INTO t1 VALUES (4,5);
+SET binlog_format= @old_binlog_format;
+
+sync_slave_with_master;
+connection slave;
+
+# The slave should have skipped the first three inserts (number 1 and 3 due
+# to @@sql_slave_skip_counter=2, number 2 due to
+# @@replicate_ignore_do_not_replicate=1). So only number 4 should be left.
+SELECT * FROM t1;
+
+
+#
+# Check that BINLOG statement preserves the @@do_not_replicate flag.
+#
+connection master;
+TRUNCATE t1;
+
+# Format description log event.
+BINLOG '66I6Tg8BAAAAZgAAAGoAAAABAAQANS40LjAtTWFyaWFEQi12YWxncmluZC1tYXgtZGVidWctbG9n
+AAAAAAAAAAAAAAAAAADrojpOEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC';
+# INSERT INTO t1 VALUES (1,8)  # with @@do_not_replicate=1
+BINLOG 'HaM6ThMBAAAAKgAAANgAAAAAgA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
+HaM6ThcBAAAAJgAAAP4AAAAAgA8AAAAAAAEAAv/8AQAAAAgAAAA=';
+# INSERT INTO t1 VALUES (2,8)  # with @@do_not_replicate=0
+BINLOG 'JqM6ThMBAAAAKgAAALEBAAAAAA8AAAAAAAEABHRlc3QAAnQxAAIDAwAC
+JqM6ThcBAAAAJgAAANcBAAAAAA8AAAAAAAEAAv/8AgAAAAgAAAA=';
+
+SELECT * FROM t1 ORDER BY a;
+sync_slave_with_master;
+connection slave;
+# Slave should have only the second insert, the first should be ignored due to
+# the @@do_not_replicate flag.
+SELECT * FROM t1 ORDER by a;
+
+
+# ToDo: Test behaviour when changing @@do_not_replicate inside a transaction or statement.
+
+
+# Clean up.
+connection master;
+SET do_not_replicate=0;
+DROP TABLE t1,t2;
+connection slave;
+STOP SLAVE;
+SET GLOBAL replicate_ignore_do_not_replicate=0;
+START SLAVE;
+
+--source include/rpl_end.inc

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2011-05-03 16:10:10 +0000
+++ b/sql/log_event.cc	2011-08-04 14:10:00 +0000
@@ -665,11 +665,13 @@ const char* Log_event::get_type_str()
 
 #ifndef MYSQL_CLIENT
 Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
-  :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), thd(thd_arg)
+  :log_pos(0), temp_buf(0), exec_time(0), thd(thd_arg)
 {
   server_id=    thd->server_id;
   when=         thd->start_time;
   cache_stmt=   using_trans;
+  flags= flags_arg |
+    (thd->options & OPTION_DO_NOT_REPLICATE ? LOG_EVENT_DO_NOT_REPLICATE_F : 0);
 }
 
 
@@ -825,7 +827,9 @@ Log_event::do_shall_skip(Relay_log_info
                       rli->replicate_same_server_id,
                       rli->slave_skip_counter));
   if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
-      (rli->slave_skip_counter == 1 && rli->is_in_group()))
+      (rli->slave_skip_counter == 1 && rli->is_in_group()) ||
+      (flags & LOG_EVENT_DO_NOT_REPLICATE_F
+       && opt_replicate_ignore_do_not_replicate))
     return EVENT_SKIP_IGNORE;
   if (rli->slave_skip_counter > 0)
     return EVENT_SKIP_COUNT;
@@ -3483,6 +3487,14 @@ Query_log_event::do_shall_skip(Relay_log
   DBUG_PRINT("debug", ("query: %s; q_len: %d", query, q_len));
   DBUG_ASSERT(query && q_len > 0);
 
+  /*
+    An event skipped due to @@do_not_replicate must not be counted towards the
+    number of events to be skipped due to @@sql_slave_skip_counter.
+  */
+  if (flags & LOG_EVENT_DO_NOT_REPLICATE_F &&
+      opt_replicate_ignore_do_not_replicate)
+    DBUG_RETURN(Log_event::EVENT_SKIP_IGNORE);
+
   if (rli->slave_skip_counter > 0)
   {
     if (strcmp("BEGIN", query) == 0)
@@ -9780,7 +9792,7 @@ st_print_event_info::st_print_event_info
    auto_increment_increment(0),auto_increment_offset(0), charset_inited(0),
    lc_time_names_number(~0),
    charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
-   thread_id(0), thread_id_printed(false),
+   thread_id(0), thread_id_printed(false), do_not_replicate(0),
    base64_output_mode(BASE64_OUTPUT_UNSPEC), printed_fd_event(FALSE)
 {
   /*

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2011-02-28 17:39:30 +0000
+++ b/sql/log_event.h	2011-08-04 14:10:00 +0000
@@ -491,6 +491,19 @@ struct sql_ex_info
 #define LOG_EVENT_RELAY_LOG_F 0x40
 
 /**
+   @def LOG_EVENT_DO_NOT_REPLICATE_F
+
+   Flag set by application creating the event (with @@do_not_replicate); the
+   slave will skip replication of such events if
+   --replicate-ignore-do-not-replicate is set.
+
+   This is a MariaDB flag; we allocate it from the end of the available
+   values to reduce risk of conflict with new MySQL flags.
+*/
+#define LOG_EVENT_DO_NOT_REPLICATE_F 0x8000
+
+
+/**
   @def OPTIONS_WRITTEN_TO_BIN_LOG
 
   OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must
@@ -656,6 +669,11 @@ typedef struct st_print_event_info
   uint charset_database_number;
   uint thread_id;
   bool thread_id_printed;
+  /*
+    Track when @@do_not_replicate changes so we need to output a SET
+    statement for it.
+  */
+  int do_not_replicate;
 
   st_print_event_info();
 
@@ -910,8 +928,8 @@ public:
 
   /**
     Some 16 flags. See the definitions above for LOG_EVENT_TIME_F,
-    LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F, and
-    LOG_EVENT_SUPPRESS_USE_F for notes.
+    LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F,
+    LOG_EVENT_SUPPRESS_USE_F, and LOG_EVENT_DO_NOT_REPLICATE_F for notes.
   */
   uint16 flags;
 
@@ -3915,6 +3933,8 @@ public:
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
     m_message.str= NULL;                    /* Just as a precaution */
     m_message.length= 0;
+    /* Replicate the incident irregardless of @@do_not_replicate. */
+    flags&= ~LOG_EVENT_DO_NOT_REPLICATE_F;
     DBUG_VOID_RETURN;
   }
 
@@ -3924,6 +3944,8 @@ public:
     DBUG_ENTER("Incident_log_event::Incident_log_event");
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
     m_message= msg;
+    /* Replicate the incident irregardless of @@do_not_replicate. */
+    flags&= ~LOG_EVENT_DO_NOT_REPLICATE_F;
     DBUG_VOID_RETURN;
   }
 #endif

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2011-07-21 10:15:09 +0000
+++ b/sql/mysql_priv.h	2011-08-04 14:10:00 +0000
@@ -504,6 +504,7 @@ protected:
 */
 #define TMP_TABLE_FORCE_MYISAM          (ULL(1) << 32)
 #define OPTION_PROFILING                (ULL(1) << 33)
+#define OPTION_DO_NOT_REPLICATE         (ULL(1) << 34) // THD, user
 
 
 
@@ -2064,6 +2065,7 @@ extern my_bool opt_old_style_user_limits
 extern uint opt_crash_binlog_innodb;
 extern char *shared_memory_base_name, *mysqld_unix_port;
 extern my_bool opt_enable_shared_memory;
+extern my_bool opt_replicate_ignore_do_not_replicate;
 extern char *default_tz_name;
 #endif /* MYSQL_SERVER */
 #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-06-24 09:08:45 +0000
+++ b/sql/mysqld.cc	2011-08-04 14:10:00 +0000
@@ -553,6 +553,8 @@ uint    opt_large_page_size= 0;
 uint    opt_debug_sync_timeout= 0;
 #endif /* defined(ENABLED_DEBUG_SYNC) */
 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
+my_bool opt_replicate_ignore_do_not_replicate;
+
 /*
   True if there is at least one per-hour limit for some user, so we should
   check them before each query (and possibly reset counters when hour is
@@ -6085,7 +6087,8 @@ enum options_mysqld
   OPT_IGNORE_BUILTIN_INNODB,
   OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
   OPT_DEFAULT_CHARACTER_SET_OLD,
-  OPT_MAX_LONG_DATA_SIZE
+  OPT_MAX_LONG_DATA_SIZE,
+  OPT_REPLICATE_IGNORE_DO_NOT_REPLICATE
 };
 
 
@@ -6782,6 +6785,11 @@ each time the SQL thread starts.",
    "cross database updates. If you need cross database updates to work, "
    "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
    "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"replicate-ignore-do-not-replicate", OPT_REPLICATE_IGNORE_DO_NOT_REPLICATE,
+   "Tells the slave thread not to replicate events that were created with"
+   "@@do_not_replicat=1.", &opt_replicate_ignore_do_not_replicate,
+   &opt_replicate_ignore_do_not_replicate, 0, GET_BOOL, NO_ARG,
+   0, 0, 0 ,0, 0, 0},
   {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
    "Tells the slave thread to not replicate to the specified table. To specify "
    "more than one table to ignore, use the directive multiple times, once for "

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2011-05-03 16:10:10 +0000
+++ b/sql/set_var.cc	2011-08-04 14:10:00 +0000
@@ -830,6 +830,9 @@ static sys_var_thd_bit  sys_profiling(&v
 static sys_var_thd_ulong        sys_profiling_history_size(&vars, "profiling_history_size",
                                               &SV::profiling_history_size);
 #endif
+static sys_var_thd_bit  sys_do_not_replicate(&vars, "do_not_replicate", 0,
+                                             set_option_bit,
+                                             OPTION_DO_NOT_REPLICATE);
 
 /* Local state variables */
 
@@ -906,6 +909,12 @@ static sys_var_thd_set sys_log_slow_verb
                                               "log_slow_verbosity",
                                               &SV::log_slow_verbosity,
                                               &log_slow_verbosity_typelib);
+#ifdef HAVE_REPLICATION
+static sys_var_replicate_ignore_do_not_replicate
+  sys_replicate_ignore_do_not_replicate(&vars,
+                                        "replicate_ignore_do_not_replicate",
+                                        &opt_replicate_ignore_do_not_replicate);
+#endif
 
 /* Global read-only variable containing hostname */
 static sys_var_const_str        sys_hostname(&vars, "hostname", glob_hostname);
@@ -4412,6 +4421,32 @@ sys_var_event_scheduler::update(THD *thd
 }
 
 
+#ifdef HAVE_REPLICATION
+bool sys_var_replicate_ignore_do_not_replicate::update(THD *thd, set_var *var)
+{
+  bool result;
+  int thread_mask;
+  DBUG_ENTER("sys_var_replicate_ignore_do_not_replicate::update");
+
+  /* Slave threads must be stopped to change the variable. */
+  pthread_mutex_lock(&LOCK_active_mi);
+  lock_slave_threads(active_mi);
+  init_thread_mask(&thread_mask, active_mi, 0 /*not inverse*/);
+  if (thread_mask) // We refuse if any slave thread is running
+  {
+    my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
+    result= TRUE;
+  }
+  else
+    result= sys_var_bool_ptr::update(thd, var);
+
+  unlock_slave_threads(active_mi);
+  pthread_mutex_unlock(&LOCK_active_mi);
+  DBUG_RETURN(result);
+}
+#endif
+
+
 uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
                                          LEX_STRING *base)
 {

=== modified file 'sql/set_var.h'
--- a/sql/set_var.h	2011-02-28 17:39:30 +0000
+++ b/sql/set_var.h	2011-08-04 14:10:00 +0000
@@ -1283,6 +1283,25 @@ public:
   bool is_readonly() const;
 };
 
+
+#ifdef HAVE_REPLICATION
+/**
+  Handler for setting the system variable --replicate-ignore-do-not-replicate.
+*/
+
+class sys_var_replicate_ignore_do_not_replicate :public sys_var_bool_ptr
+{
+public:
+  sys_var_replicate_ignore_do_not_replicate(sys_var_chain *chain,
+                                            const char *name_arg,
+                                            my_bool *value_arg) :
+    sys_var_bool_ptr(chain, name_arg, value_arg) {};
+  ~sys_var_replicate_ignore_do_not_replicate() {};
+  bool update(THD *thd, set_var *var);
+};
+#endif
+
+
 /****************************************************************************
   Classes for parsing of the SET command
 ****************************************************************************/

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2011-05-03 16:10:10 +0000
+++ b/sql/slave.cc	2011-08-04 14:10:00 +0000
@@ -2114,6 +2114,8 @@ int apply_event_and_update_pos(Log_event
   thd->lex->current_select= 0;
   if (!ev->when)
     ev->when= my_time(0);
+  thd->options= (thd->options & ~OPTION_DO_NOT_REPLICATE) |
+    (ev->flags & LOG_EVENT_DO_NOT_REPLICATE_F ? OPTION_DO_NOT_REPLICATE : 0);
   ev->thd = thd; // because up to this point, ev->thd == 0
 
   int reason= ev->shall_skip(rli);

=== modified file 'sql/sql_binlog.cc'
--- a/sql/sql_binlog.cc	2011-02-20 16:51:43 +0000
+++ b/sql/sql_binlog.cc	2011-08-04 14:10:00 +0000
@@ -33,6 +33,7 @@
 
 void mysql_client_binlog_statement(THD* thd)
 {
+  ulonglong save_do_not_replicate;
   DBUG_ENTER("mysql_client_binlog_statement");
   DBUG_PRINT("info",("binlog base64: '%*s'",
                      (int) (thd->lex->comment.length < 2048 ?
@@ -213,7 +214,15 @@ void mysql_client_binlog_statement(THD*
         reporting.
       */
 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
+      save_do_not_replicate= thd->options & OPTION_DO_NOT_REPLICATE;
+      thd->options= (thd->options & ~OPTION_DO_NOT_REPLICATE) |
+        (ev->flags & LOG_EVENT_DO_NOT_REPLICATE_F ?
+         OPTION_DO_NOT_REPLICATE : 0);
+
       err= ev->apply_event(rli);
+
+      thd->options= (thd->options & ~OPTION_DO_NOT_REPLICATE) |
+        save_do_not_replicate;
 #else
       err= 0;
 #endif



More information about the commits mailing list