List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:January 6 2009 8:28pm
Subject:bzr commit into mysql-6.0-backup branch (charles.bell:2746) Bug#39780
View as plain text  
#At file:///D:/source/bzr/mysql-6.0-bug-39780/

 2746 Chuck Bell	2009-01-06
      BUG#39780 Allow restore to skip gap event during restore on master 
      
      This patch adds a new option to the restore command: skip_gap_event.
      It is used to skip writing the incident event when a restore is
      run on a master in an active replication topology (gap event).
modified:
  mysql-test/suite/rpl/r/rpl_backup.result
  mysql-test/suite/rpl/t/rpl_backup.test
  sql/backup/backup_kernel.h
  sql/backup/kernel.cc
  sql/lex.h
  sql/sql_parse.cc
  sql/sql_yacc.yy

per-file messages:
  mysql-test/suite/rpl/r/rpl_backup.result
    Corrected result file.
  mysql-test/suite/rpl/t/rpl_backup.test
    Added test case for skipping gap event.
  sql/backup/backup_kernel.h
    Added parameter to pass on value of skip_gap_event check.
  sql/backup/kernel.cc
    Added parameter to pass on the result of the skip_gap_event check.
    Added code to skip gap event when triggered.
  sql/lex.h
    Added new symbol.
  sql/sql_parse.cc
    Added code to pass the skip_gap_event signal to the proper locations.
    Simplified option check code.
  sql/sql_yacc.yy
    Extended restore syntax to include new option.
=== modified file 'mysql-test/suite/rpl/r/rpl_backup.result'
--- a/mysql-test/suite/rpl/r/rpl_backup.result	2008-12-16 20:54:07 +0000
+++ b/mysql-test/suite/rpl/r/rpl_backup.result	2009-01-06 20:28:28 +0000
@@ -60,7 +60,7 @@ Replicate_Do_DB	
 Replicate_Ignore_DB	
 Replicate_Do_Table	
 Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
+Replicate_Wild_Do_Table	rpl_backup.%
 Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
@@ -119,7 +119,7 @@ Replicate_Do_DB	
 Replicate_Ignore_DB	
 Replicate_Do_Table	
 Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
+Replicate_Wild_Do_Table	rpl_backup.%
 Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
@@ -206,7 +206,7 @@ Replicate_Do_DB	
 Replicate_Ignore_DB	
 Replicate_Do_Table	
 Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
+Replicate_Wild_Do_Table	rpl_backup.%
 Replicate_Wild_Ignore_Table	
 Last_Errno	1590
 Last_Error	The incident RESTORE_ON_MASTER occured on the master. Message: A restore operation was initiated on the master.
@@ -354,7 +354,7 @@ Replicate_Do_DB	
 Replicate_Ignore_DB	
 Replicate_Do_Table	
 Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
+Replicate_Wild_Do_Table	rpl_backup.%
 Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
@@ -407,7 +407,7 @@ Replicate_Do_DB	
 Replicate_Ignore_DB	
 Replicate_Do_Table	
 Replicate_Ignore_Table	
-Replicate_Wild_Do_Table	
+Replicate_Wild_Do_Table	rpl_backup.%
 Replicate_Wild_Ignore_Table	
 Last_Errno	0
 Last_Error	
@@ -431,9 +431,52 @@ Last_SQL_Errno	0
 Last_SQL_Error	
 Now stop the slave.
 SLAVE STOP;
+First, reset replication. 
+RESET MASTER;
+RESET SLAVE;
+SET DEBUG_SYNC = 'reset';
+START SLAVE;
+Create a new database on the master. 
+CREATE DATABASE not_replicated;
+CREATE TABLE not_replicated.t1 (a int);
+INSERT INTO not_replicated.t1 VALUES (200), (300), (400);
+SHOW DATABASES;
+Database
+information_schema
+mysql
+not_replicated
+rpl_backup
+test
+Now let's see if it is replicated on the slave (shouldn't be).
+SHOW DATABASES;
+Database
+information_schema
+mysql
+rpl_backup
+test
+Now back to the master to make a backup of the new database.
+Backup_id = 505.
+BACKUP DATABASE not_replicated TO 'rpl_bup_m4.bak';
+backup_id
+505
+Now let's run the restore and see if the slave stops.
+Backup_id = 506.
+RESTORE FROM 'rpl_bup_m4.bak' OVERWRITE SKIP_GAP_EVENT;
+backup_id
+506
+Let's ensure replication is still running.
+INSERT INTO rpl_backup.t1 VALUES (901), (902), (903);
+SELECT * FROM rpl_backup.t1 WHERE a > 900;
+a
+901
+902
+903
+Now stop the slave.
+SLAVE STOP;
 FLUSH BACKUP LOGS;
 PURGE BACKUP LOGS;
 DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
 FLUSH BACKUP LOGS;
 PURGE BACKUP LOGS;
 DROP DATABASE rpl_backup;

=== modified file 'mysql-test/suite/rpl/t/rpl_backup.test'
--- a/mysql-test/suite/rpl/t/rpl_backup.test	2008-12-16 20:54:07 +0000
+++ b/mysql-test/suite/rpl/t/rpl_backup.test	2009-01-06 20:28:28 +0000
@@ -432,6 +432,65 @@ SLAVE STOP;
 --source include/wait_for_slave_to_stop.inc
 
 #
+# Test case for BUG#39780 - Skip gap event on restore.
+#
+# The new SKIP_GAP_EVENT option for the RESTORE command
+# allows users to pruposefully skip writing the gap event
+# when the restore is run on a master and the databases
+# being restored do not exist on the slave nor are they
+# intended to be on the slave.
+#
+
+--echo First, reset replication. 
+connection master;
+RESET MASTER;
+
+connection slave;
+RESET SLAVE;
+SET DEBUG_SYNC = 'reset';
+
+connection slave;
+START SLAVE;
+--source include/wait_for_slave_to_start.inc
+
+--echo Create a new database on the master. 
+connection master;
+
+CREATE DATABASE not_replicated;
+CREATE TABLE not_replicated.t1 (a int);
+INSERT INTO not_replicated.t1 VALUES (200), (300), (400);
+
+SHOW DATABASES;
+
+--echo Now let's see if it is replicated on the slave (shouldn't be).
+sync_slave_with_master;
+connection slave;
+
+SHOW DATABASES;
+
+--echo Now back to the master to make a backup of the new database.
+connection master;
+
+--echo Backup_id = 505.
+BACKUP DATABASE not_replicated TO 'rpl_bup_m4.bak';
+
+--echo Now let's run the restore and see if the slave stops.
+--echo Backup_id = 506.
+RESTORE FROM 'rpl_bup_m4.bak' OVERWRITE SKIP_GAP_EVENT;
+
+--echo Let's ensure replication is still running.
+INSERT INTO rpl_backup.t1 VALUES (901), (902), (903);
+
+sync_slave_with_master;
+connection slave;
+
+SELECT * FROM rpl_backup.t1 WHERE a > 900;
+
+--echo Now stop the slave.
+SLAVE STOP;
+--source include/wait_for_slave_to_stop.inc
+
+#
 # Cleanup
 #
 connection master;
@@ -439,10 +498,12 @@ connection master;
 FLUSH BACKUP LOGS;
 PURGE BACKUP LOGS;
 DROP DATABASE rpl_backup;
+DROP DATABASE not_replicated;
 
 --remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m1.bak
 --remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m2.bak
 --remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m3.bak
+--remove_file $MYSQLTEST_VARDIR/master-data/rpl_bup_m4.bak
 
 connection slave;
 

=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h	2008-12-18 21:46:36 +0000
+++ b/sql/backup/backup_kernel.h	2009-01-06 20:28:28 +0000
@@ -30,7 +30,7 @@ void backup_shutdown();
   Called from the big switch in mysql_execute_command() to execute
   backup related statement
 */
-int execute_backup_command(THD*, LEX*, String*, bool);
+int execute_backup_command(THD*, LEX*, String*, bool, bool);
 
 // forward declarations
 
@@ -73,7 +73,7 @@ public:
                                    const char*, bool);
   Restore_info* prepare_for_restore(String *location, 
                                    LEX_STRING orig_loc,
-                                   const char*);  
+                                   const char*, bool);  
 
   int do_backup();
   int do_restore(bool overwrite);

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-12-18 21:46:36 +0000
+++ b/sql/backup/kernel.cc	2009-01-06 20:28:28 +0000
@@ -123,6 +123,9 @@ static int send_reply(Backup_restore_ctx
   @param[in] backupdir  value of the backupdir variable from server.
   @param[in] overwrite  whether or not restore should overwrite existing
                         DB with same name as in backup image
+  @param[in] skip_gap_event  whether or not restore should skip writing
+                             the gap event if run on a master in an active
+                             replication scenario
 
   @note This function sends response to the client (ok, result set or error).
 
@@ -134,7 +137,11 @@ static int send_reply(Backup_restore_ctx
  */
 
 int
-execute_backup_command(THD *thd, LEX *lex, String *backupdir, bool overwrite)
+execute_backup_command(THD *thd, 
+                       LEX *lex, 
+                       String *backupdir, 
+                       bool overwrite,
+                       bool skip_gap_event)
 {
   int res= 0;
   
@@ -209,7 +216,7 @@ execute_backup_command(THD *thd, LEX *le
   {
 
     Restore_info *info= context.prepare_for_restore(backupdir, lex->backup_dir, 
-                                                    thd->query);
+                                                   thd->query, skip_gap_event);
     
     if (!info || !info->is_valid())
       DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -682,6 +689,7 @@ Backup_restore_ctx::prepare_for_backup(S
   @param[in] backupdir  path to the file where backup image is stored
   @param[in] orig_loc   path as specified on command line for backup image
   @param[in] query      RESTORE query starting the operation
+  @param[in] skip_gap_event TRUE means do not write gap event
   
   @returns Pointer to a @c Restore_info instance containing catalogue of the
   backup image (read from the image). NULL if errors were detected.
@@ -691,7 +699,8 @@ Backup_restore_ctx::prepare_for_backup(S
 Restore_info* 
 Backup_restore_ctx::prepare_for_restore(String *backupdir,
                                         LEX_STRING orig_loc, 
-                                        const char *query)
+                                        const char *query,
+                                        bool skip_gap_event)
 {
   using namespace backup;  
 
@@ -822,7 +831,8 @@ Backup_restore_ctx::prepare_for_restore(
 
     DEBUG_SYNC(m_thd, "after_disable_slave_connections");
 
-    obs::write_incident_event(m_thd, obs::RESTORE_EVENT);
+    if (!skip_gap_event)
+      obs::write_incident_event(m_thd, obs::RESTORE_EVENT);
     m_engage_binlog= TRUE;
     obs::engage_binlog(FALSE);
   }

=== modified file 'sql/lex.h'
--- a/sql/lex.h	2008-11-17 09:57:51 +0000
+++ b/sql/lex.h	2009-01-06 20:28:28 +0000
@@ -485,6 +485,7 @@ static SYMBOL symbols[] = {
   { "SHUTDOWN",		SYM(SHUTDOWN)},
   { "SIGNED",		SYM(SIGNED_SYM)},
   { "SIMPLE",		SYM(SIMPLE_SYM)},
+  { "SKIP_GAP_EVENT",     SYM(SKIP_GAP_EVENT_SYM)},
   { "SLAVE",            SYM(SLAVE)},
   { "SNAPSHOT",         SYM(SNAPSHOT_SYM)},
   { "SMALLINT",		SYM(SMALLINT)},

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-12-04 23:14:30 +0000
+++ b/sql/sql_parse.cc	2009-01-06 20:28:28 +0000
@@ -44,7 +44,7 @@
   @defgroup Runtime_Environment Runtime Environment
   @{
 */
-int execute_backup_command(THD*, LEX*, String*, bool);
+int execute_backup_command(THD*, LEX*, String*, bool, bool);
 
 /* Used in error handling only */
 #define SP_TYPE_STRING(LP) \
@@ -2316,26 +2316,43 @@ mysql_execute_command(THD *thd)
     /* Used to specify if RESTORE should overwrite existing db with same name */
     bool overwrite_restore= false;
 
-    Item *it= (Item *)lex->value_list.head();
+    /* Used to specify if RESTORE should skup writing the gap event. */
+    bool skip_gap_event= false;
+
+    List<Item> lit= lex->value_list;
+    Item *it= 0;
 
-    // Item only set for RESTORE in sql_yacc.yy, no error checking of
-    // item necessary
-    if (it)
+    // value list only set for RESTORE in sql_yacc.yy, no error checking of
+    // item necessary for backup
+    while (lit.elements)
     {
+      it= lit.pop();
       /*
         it is OK to only emulate fix_fields, because we need only
         value of constant
       */
       it->quick_fix_field();
-
-      if ((int8)it->val_int() == 1)
-        overwrite_restore= true;
+      int8 val= (int8)it->val_int();
+      /*
+        Check options.
+      */
+      switch (val) {
+        /* OVERWRITE option */
+        case 1:
+          overwrite_restore= true;
+          break;
+        /* SKIP GAP EVENT option */
+        case 2:
+          skip_gap_event= true;
+          break;
+      }
     }
     /*
       Note: execute_backup_command() sends a correct response to the client
       (either ok, result set or error message).
      */ 
-    if (execute_backup_command(thd, lex, &backupdir, overwrite_restore))
+    if (execute_backup_command(thd, lex, &backupdir, overwrite_restore,
+                               skip_gap_event))
       goto error;
     break;
   }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2008-12-04 23:14:30 +0000
+++ b/sql/sql_yacc.yy	2009-01-06 20:28:28 +0000
@@ -1074,6 +1074,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SHUTDOWN
 %token  SIGNED_SYM
 %token  SIMPLE_SYM                    /* SQL-2003-N */
+%token  SKIP_GAP_EVENT_SYM
 %token  SLAVE
 %token  SMALLINT                      /* SQL-2003-R */
 %token  SNAPSHOT_SYM
@@ -6435,7 +6436,7 @@ restore:
           }
           FROM
           TEXT_STRING_sys 
-          opt_overwrite
+          opt_overwrite opt_skip_gap_event
           {
             Lex->backup_dir = $4; 
           }
@@ -6459,6 +6460,23 @@ opt_overwrite:
             lex->value_list.push_front(it);
            }
          ;
+         
+opt_skip_gap_event:
+        /* empty */ 
+          {         
+            LEX *lex= Lex;
+            Item *it= new Item_int((int8) 0);
+
+            lex->value_list.push_back(it);
+          }
+        | SKIP_GAP_EVENT_SYM
+          {
+            LEX *lex= Lex;
+            Item *it= new Item_int((int8) 2);
+
+            lex->value_list.push_back(it);
+           }
+         ;
 
 backup:   
           BACKUP_SYM 

Thread
bzr commit into mysql-6.0-backup branch (charles.bell:2746) Bug#39780Chuck Bell6 Jan
  • Re: bzr commit into mysql-6.0-backup branch (charles.bell:2746)Bug#39780Ingo Strüwing7 Jan
    • Re: bzr commit into mysql-6.0-backup branch (charles.bell:2746)Bug#39780Chuck Bell5 Feb
      • Re: bzr commit into mysql-6.0-backup branch (charles.bell:2746)Bug#39780Ingo Strüwing6 Feb
      • Re: bzr commit into mysql-6.0-backup branch (charles.bell:2746)Bug#39780Chuck Bell9 Feb
  • Re: bzr commit into mysql-6.0-backup branch (charles.bell:2746)Bug#39780Jørgen Løland7 Jan