List:Commits« Previous MessageNext Message »
From:Andrei Elkin Date:March 24 2011 5:17pm
Subject:bzr commit into mysql-trunk branch (andrei.elkin:3311) Bug#11748510
View as plain text  
#At file:///home/andrei/MySQL/BZR/2a-23May/FIXES/bug11748510_36524-deadlock_overdram/ based on revid:magne.mahre@stripped

 3311 Andrei Elkin	2011-03-24
      bug#11748510 incident of deadlock on slave is overdramatized
      
      In cases of temporary errors in replication event execution (deadlock,
      timeout) the error log gained an overreacting error message whereas
      just a warning would be fine.
      
      Fixed with checking of the temporary status of the error inside
      Slave_reporting_capability::report() to demote the error to the
      warning level if needed. 
      The warning gets converted into the error
      whenever number of successive attempts to re-apply the event(s) gets
      equal to @@global.slave_trans_retries.
      
      The patch also changes the slave service error gathering and reporting
      as the following.
      Slave_reporting_capability::report() populates 
      thd->main_da the standard placeholder for the errors and calls the stderr writers 
      for errors and lesser severity levels as specified by
      @@global_system_variables.log_warnings.
      That said  report() mimics my_error().
      Slave_reporting_capability::display() is introduced to display errors 
      through show-slave-status interfaces.
      The latter mimics send_error(). 
      
      Some number of test result files got affected and in some cases the
      new results revealed issues in the old versions. This patch contains a
      limited part dealing with the tests. See the following commit that
      completes the fixes.
     @ mysql-test/extra/rpl_tests/rpl_deadlock.test
        regression test is added to prove a temporary failure warning is escalated.
     @ mysql-test/include/check-testcase.test
        IO errors can be gathered during IO thread session time and can't be reset.
        So they are masked out until we will have gotten facility to wipe them out.
     @ mysql-test/suite/rpl/r/rpl_deadlock_innodb.result
        results get updated.
     @ sql/log_event.cc
        treating rli->report() as an error reporting similar to my_error().
        Gathering errors in the diag area should be completed with displaying
        via rli->display() each time a slave thread breaks the applying loop.
        Relocating clear_all_errors() definition into rpl_slave.cc.
     @ sql/rpl_reporting.cc
        report() method is turned to be a wrapper of functions dealing with
        the diag area like my_error() and ones with the error log.  One of its
        use case to register an error and print it out the error log.  A new
        display() method copies the gathered errors the area of the Show
        Slave Status when a slave thread is about to exit.
     @ sql/rpl_reporting.h
         a new display() method added as well as comments for report().
     @ sql/rpl_slave.cc
        exporting has_temporary_error() to be used in rpl_reporting.cc;
        docking definition of clear_all_errors() to use in both modules;
        run-out-of-tries case is finished with raising on the fatal error flag;
        finalizing the error branch of events execution with display() to
        make gathered error be saved in show-slave-status area;
        deploying display() at the end of io-thread and sql-thread.
     @ sql/rpl_slave.h
        exporting functions shared with slave.cc, rpl_reporting.cc, log_event.cc.

    modified:
      mysql-test/extra/rpl_tests/rpl_deadlock.test
      mysql-test/include/check-testcase.test
      mysql-test/suite/rpl/r/rpl_deadlock_innodb.result
      sql/log_event.cc
      sql/rpl_reporting.cc
      sql/rpl_reporting.h
      sql/rpl_slave.cc
      sql/rpl_slave.h
=== modified file 'mysql-test/extra/rpl_tests/rpl_deadlock.test'
--- a/mysql-test/extra/rpl_tests/rpl_deadlock.test	2010-12-19 17:07:28 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_deadlock.test	2011-03-24 17:17:13 +0000
@@ -10,6 +10,10 @@
 
 --source include/master-slave.inc
 
+connection slave;
+call mtr.add_suppression("Could not execute Write_rows event on table test.t1,handler error HA_ERR_LOCK_WAIT_TIMEOUT");
+connection master;
+
 # 0) Prepare tables and data
 --echo *** Prepare tables and data ***
 
@@ -123,6 +127,58 @@ SELECT * FROM t3;
 source include/check_slave_is_running.inc;
 --echo
 
+#
+# bug#11748510/36524 incident of deadlock on slave is overdramatized
+#
+# Observe that the slave stopped when the number of transation retries 
+# exceeds @@global.slave_transaction_retries
+#
+connection master;
+
+--echo *** Test the deadlock warning to be escalated into the error ***
+
+delete from t1;
+delete from t2;
+delete from t3;
+
+sync_slave_with_master;
+
+# make sure slave's unilateral row gone as well
+delete from t1;
+delete from t2;
+delete from t3;
+
+# the first attempt to run a deadlock scenario of p 1) leads to the error
+set @save.slave_transaction_retries= @@global.slave_transaction_retries;
+set @@global.slave_transaction_retries= 0;
+source include/stop_slave.inc;
+
+connection master;
+
+BEGIN;
+INSERT INTO t1 VALUES (1);
+# We make a long transaction here
+INSERT INTO t2 VALUES (2), (2), (2), (2), (2), (2), (2), (2), (2), (2);
+INSERT INTO t3 VALUES (3);
+COMMIT;
+
+connection slave;
+BEGIN;
+SELECT count(*) as zero FROM t1 FOR UPDATE;
+
+start slave;
+
+--echo *** Now the slave must be stopped due to deadlock ***
+
+# slow slave environment can report ER_LOCK_TIMEOUT
+let $slave_sql_errno= 1213, 1205; # ER_LOCK_DEADLOCK or TIMEOUT
+let $show_slave_sql_error= 0;
+source include/wait_for_slave_sql_error.inc;
+
+rollback;
+
+set @@global.slave_transaction_retries= @save.slave_transaction_retries;
+source include/start_slave.inc;
 # Clean up
 --echo *** Clean up ***
 connection master;

=== modified file 'mysql-test/include/check-testcase.test'
--- a/mysql-test/include/check-testcase.test	2011-02-07 15:31:01 +0000
+++ b/mysql-test/include/check-testcase.test	2011-03-24 17:17:13 +0000
@@ -54,8 +54,8 @@ if ($tmp)
   --echo Master_SSL_Key	
   --echo Seconds_Behind_Master	NULL
   --echo Master_SSL_Verify_Server_Cert	No
-  --echo Last_IO_Errno	0
-  --echo Last_IO_Error	
+  --echo Last_IO_Errno	#
+  --echo Last_IO_Error	#
   --echo Last_SQL_Errno	0
   --echo Last_SQL_Error	
   --echo Replicate_Ignore_Server_Ids	
@@ -72,7 +72,7 @@ if ($tmp)
 }
 if (!$tmp) {
   # Note: after WL#5177, fields 13-18 shall not be filtered-out.
-  --replace_column 4 # 5 # 6 # 7 # 8 # 9 # 10 # 13 # 14 # 15 # 16 # 17 # 18 # 22 # 23 # 24 # 25 # 26 # 40 # 41 # 42 # 46 #
+  --replace_column 4 # 5 # 6 # 7 # 8 # 9 # 10 # 13 # 14 # 15 # 16 # 17 # 18 # 22 # 23 # 24 # 25 # 26 # 35 # 36 # 40 # 41 # 42 # 46 #
   query_vertical
   SHOW SLAVE STATUS;
 }

=== modified file 'mysql-test/suite/rpl/r/rpl_deadlock_innodb.result'
--- a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result	2010-12-19 17:22:30 +0000
+++ b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result	2011-03-24 17:17:13 +0000
@@ -1,5 +1,6 @@
 include/master-slave.inc
 [connection master]
+call mtr.add_suppression("Could not execute Write_rows event on table test.t1,handler error HA_ERR_LOCK_WAIT_TIMEOUT");
 *** Prepare tables and data ***
 CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=innodb;
 CREATE TABLE t2 (a INT) ENGINE=innodb;
@@ -103,6 +104,31 @@ a
 3
 include/check_slave_is_running.inc
 
+*** Test the deadlock warning to be escalated into the error ***
+delete from t1;
+delete from t2;
+delete from t3;
+delete from t1;
+delete from t2;
+delete from t3;
+set @save.slave_transaction_retries= @@global.slave_transaction_retries;
+set @@global.slave_transaction_retries= 0;
+include/stop_slave.inc
+BEGIN;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2), (2), (2), (2), (2), (2), (2), (2), (2), (2);
+INSERT INTO t3 VALUES (3);
+COMMIT;
+BEGIN;
+SELECT count(*) as zero FROM t1 FOR UPDATE;
+zero
+0
+start slave;
+*** Now the slave must be stopped due to deadlock ***
+include/wait_for_slave_sql_error.inc [errno=1213, 1205]
+rollback;
+set @@global.slave_transaction_retries= @save.slave_transaction_retries;
+include/start_slave.inc
 *** Clean up ***
 DROP TABLE t1,t2,t3;
 SET global max_relay_log_size= @my_max_relay_log_size;

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2011-03-14 17:09:16 +0000
+++ b/sql/log_event.cc	2011-03-24 17:17:13 +0000
@@ -209,35 +209,21 @@ static void inline slave_rows_error_repo
                                            const char *log_name, ulong pos)
 {
   const char *handler_error= HA_ERR(ha_error);
-  char buff[MAX_SLAVE_ERRMSG], *slider;
-  const char *buff_end= buff + sizeof(buff);
-  uint len;
-  List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
-  MYSQL_ERROR *err;
-  buff[0]= 0;
-
-  for (err= it++, slider= buff; err && slider < buff_end - 1;
-       slider += len, err= it++)
-  {
-    len= my_snprintf(slider, buff_end - slider,
-                     " %s, Error_code: %d;", err->get_message_text(),
-                     err->get_sql_errno());
-  }
 
   if (ha_error != 0)
     rli->report(level, thd->is_error() ? thd->stmt_da->sql_errno() : 0,
-                "Could not execute %s event on table %s.%s;"
-                "%s handler error %s; "
+                "Could not execute %s event on table %s.%s,"
+                "handler error %s, "
                 "the event's master log %s, end_log_pos %lu",
                 type, table->s->db.str, table->s->table_name.str,
-                buff, handler_error == NULL ? "<unknown>" : handler_error,
+                handler_error == NULL ? "<unknown>" : handler_error,
                 log_name, pos);
   else
     rli->report(level, thd->is_error() ? thd->stmt_da->sql_errno() : 0,
-                "Could not execute %s event on table %s.%s;"
-                "%s the event's master log %s, end_log_pos %lu",
+                "Could not execute %s event on table %s.%s,"
+                "the event's master log %s, end_log_pos %lu",
                 type, table->s->db.str, table->s->table_name.str,
-                buff, log_name, pos);
+                log_name, pos);
 }
 
 static void set_thd_db(THD *thd, const char *db, uint32 db_len)
@@ -293,13 +279,6 @@ static void pretty_print_str(IO_CACHE* c
 
 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
 
-static void clear_all_errors(THD *thd, Relay_log_info *rli)
-{
-  thd->is_slave_error = 0;
-  thd->clear_error();
-  rli->clear_error();
-}
-
 inline int idempotent_error_code(int err_code)
 {
   int ret= 0;
@@ -3700,7 +3679,7 @@ compare_errors:
         !ignored_error_code(actual_error) &&
         !ignored_error_code(expected_error))
     {
-      rli->report(ERROR_LEVEL, 0,
+      rli->report(ERROR_LEVEL, ER_UNKNOWN_ERROR,
                       "\
 Query caused different errors on master and slave.     \
 Error on master: message (format)='%s' error code=%d ; \

=== modified file 'sql/rpl_reporting.cc'
--- a/sql/rpl_reporting.cc	2010-08-05 17:45:25 +0000
+++ b/sql/rpl_reporting.cc	2011-03-24 17:17:13 +0000
@@ -17,6 +17,7 @@
 #include "rpl_reporting.h"
 #include "log.h" // sql_print_error, sql_print_warning,
                  // sql_print_information
+#include "rpl_slave.h"
 
 Slave_reporting_capability::Slave_reporting_capability(char const *thread_name)
   : m_thread_name(thread_name)
@@ -25,54 +26,153 @@ Slave_reporting_capability::Slave_report
                    &err_lock, MY_MUTEX_INIT_FAST);
 }
 
+/**
+   The method treats a supplied message depending on the level:
+
+       - an error is queued in the diagnostic area 
+         to be recorded eventually in Show Slave status area and
+         in the error log.
+       - a warning or an info level are optinally (log_warnings)
+         stored into the error log
+
+   @param level     severity of the message.
+   @param err_code  the user level error code
+   @param msg       the format string of the message,
+                    can be followed with more arguments
+                    providing the data for the format string
+
+   @note Queueing in the da is protected by @err_lock mutex
+         to collabote with a concurrent reader from the da.
+*/
 void
 Slave_reporting_capability::report(loglevel level, int err_code,
                                    const char *msg, ...) const
 {
+  THD *thd= current_thd;
   void (*report_function)(const char *, ...);
-  char buff[MAX_SLAVE_ERRMSG];
+  char buff[sizeof(m_last_error.message)];
   char *pbuff= buff;
-  uint pbuffsize= sizeof(buff);
   va_list args;
+
+  if (level == ERROR_LEVEL && has_temporary_error(thd, err_code))
+    level= WARNING_LEVEL;
+
   va_start(args, msg);
+  my_vsnprintf(pbuff, sizeof(buff), msg, args);
+  va_end(args);
 
   mysql_mutex_lock(&err_lock);
   switch (level)
   {
   case ERROR_LEVEL:
     /*
-      It's an error, it must be reported in Last_error and Last_errno in SHOW
-      SLAVE STATUS.
+      It's an error, it goes in a slave thread's main_da.
     */
-    pbuff= m_last_error.message;
-    pbuffsize= sizeof(m_last_error.message);
-    m_last_error.number = err_code;
+    m_last_error.number= err_code;
     m_last_error.update_timestamp();
+    if (err_code > 0)
+    {
+      if (thd->stmt_da->is_set())
+        thd->stmt_da->can_overwrite_status= TRUE;
+      my_printf_error(err_code, "%s", MYF(0), pbuff);
+      if (thd->stmt_da->can_overwrite_status)
+        thd->stmt_da->can_overwrite_status= FALSE;
+    }
+
     report_function= sql_print_error;
     break;
   case WARNING_LEVEL:
-    report_function= sql_print_warning;
+    report_function= global_system_variables.log_warnings?
+      sql_print_warning : NULL;
     break;
   case INFORMATION_LEVEL:
-    report_function= sql_print_information;
+    report_function= global_system_variables.log_warnings?
+      sql_print_information : NULL;
     break;
   default:
     DBUG_ASSERT(0);                            // should not come here
     return;          // don't crash production builds, just do nothing
   }
 
-  my_vsnprintf(pbuff, pbuffsize, msg, args);
-
+  /* If the msg string ends with '.', do not add a ',' it would be ugly */
+  if (report_function)
+    report_function("Slave %s: %s%s Error_code: %d",
+                    m_thread_name, pbuff,
+                    (pbuff[0] && *(strend(pbuff) - 1) == '.') ? "" : ",",
+                    err_code);
   mysql_mutex_unlock(&err_lock);
+}
+
+/**
+   compose Last_Error to be shown by SHOW SLAVE STATUS
+
+   @param err_code    The summary error code to display. If zero
+                      the last reported default will be set to Last*Errno
+
+   @param msg         The summary message's format string optinally followed
+                      by arguments. It can be NULL.
+
+   @note  The method tries gathering all queued *error-level* messages
+          into the limited-size buffer and may not compose the whole
+          list. In that case the rest can be found anyway in the error log.
+          The Last_Error's code corresponds to the last queued error if
+          the supplied @c err_code is zero.
+          
+          The gathering procedure is protected by @c err_lock
+          to provide collaboration with a concurrent reader such as
+          show slave status.
+*/
+void
+Slave_reporting_capability::display(int err_code, const char *msg, ...) const
+{
+  uint len, size= sizeof(m_last_error.message);
+  char *slider, *buff= m_last_error.message, *buff_end= buff + size;
+  List_iterator_fast<MYSQL_ERROR> it(current_thd->warning_info->warn_list());
+  MYSQL_ERROR *err;
+  uint32 err_number;
+  const char err_code_fmt[]= ", Error_code: %d; ";
+  va_list args;
+
+  va_start(args, msg);
+  len= msg == NULL? 0 : my_vsnprintf(buff, size, msg, args);
   va_end(args);
+ 
+  mysql_mutex_lock(&err_lock);
+
+  /*
+    In case of multiple errors the error codes are printed along with msgs ...
+  */
+  for (err= it++,
+         err_number= 0,
+         slider= buff + len;
+       err;
+       slider += len, err= it++)
+  {
+    if (err->get_level() != MYSQL_ERROR::WARN_LEVEL_ERROR)
+      continue;
+    if (err_number != 0)
+    {
+      len= my_snprintf(slider, buff_end - slider, err_code_fmt, err_number);
+      slider += len;
+    }
+    err_number= err->get_sql_errno();    // Last*Errno is of the error level
+    if (slider < buff_end)
+      len= my_snprintf(slider, buff_end - slider,"%s", err->get_message_text());
+  }
+  m_last_error.number= err_code == 0? err_number : err_code;
+  /*
+    ... except for the last error if its code is equal to @c err_code
+    the supplied summary's.
+  */
+  if ((err_number != 0 && err_number != m_last_error.number) &&
+      slider < buff_end)
+    my_snprintf(slider, buff_end - slider, err_code_fmt, err_number);
+
+  mysql_mutex_unlock(&err_lock);
 
-  /* If the msg string ends with '.', do not add a ',' it would be ugly */
-  report_function("Slave %s: %s%s Error_code: %d",
-                  m_thread_name, pbuff,
-                  (pbuff[0] && *(strend(pbuff)-1) == '.') ? "" : ",",
-                  err_code);
 }
 
+
 Slave_reporting_capability::~Slave_reporting_capability()
 {
   mysql_mutex_destroy(&err_lock);

=== modified file 'sql/rpl_reporting.h'
--- a/sql/rpl_reporting.h	2010-08-05 17:45:25 +0000
+++ b/sql/rpl_reporting.h	2011-03-24 17:17:13 +0000
@@ -43,8 +43,7 @@ public:
   Slave_reporting_capability(char const *thread_name);
 
   /**
-     Writes a message and, if it's an error message, to Last_Error
-     (which will be displayed by SHOW SLAVE STATUS).
+     Writes a message into diag area and/or/either the error log
 
      @param level       The severity level
      @param err_code    The error code
@@ -56,6 +55,14 @@ public:
     ATTRIBUTE_FORMAT(printf, 4, 5);
 
   /**
+     compose Last_Error to be shown by SHOW SLAVE STATUS
+     @param err_code    The summary code to display instead of the last reported
+     @param msg         A summary message to set afront of the reported errors
+  */
+  void display(int err_code, const char *msg, ...) const
+    ATTRIBUTE_FORMAT(printf, 3, 4);
+
+  /**
      Clear errors. They will not show up under <code>SHOW SLAVE
      STATUS</code>.
    */

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2011-03-17 13:20:36 +0000
+++ b/sql/rpl_slave.cc	2011-03-24 17:17:13 +0000
@@ -2514,15 +2514,23 @@ static ulong read_event(MYSQL* mysql, Ma
   DBUG_RETURN(len - 1);
 }
 
-/*
+/**
   Check if the current error is of temporary nature of not.
   Some errors are temporary in nature, such as
   ER_LOCK_DEADLOCK and ER_LOCK_WAIT_TIMEOUT.  Ndb also signals
   that the error is temporary by pushing a warning with the error code
   ER_GET_TEMPORARY_ERRMSG, if the originating error is temporary.
+
+  @param      thd  a THD instance, typically of the slave SQL thread's.
+  @error_arg  the error code for assessment. 
+              defaults to zero which makes the function check the top
+              of the have been reported errors stack.
+
+  @return 1 as the positive and 0 as the negative verdict
 */
-static int has_temporary_error(THD *thd)
+int has_temporary_error(THD *thd, uint error_arg)
 {
+  uint error;
   DBUG_ENTER("has_temporary_error");
 
   DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
@@ -2537,16 +2545,17 @@ static int has_temporary_error(THD *thd)
     error or not. This is currently the case for Incident_log_event,
     which sets no message. Return FALSE.
   */
-  if (!thd->is_error())
+  if (thd->is_fatal_error || !thd->is_error())
     DBUG_RETURN(0);
 
+  error= (error_arg == 0)? thd->stmt_da->sql_errno() : error_arg;
+
   /*
     Temporary error codes:
     currently, InnoDB deadlock detected by InnoDB or lock
     wait timeout (innodb_lock_wait_timeout exceeded
   */
-  if (thd->stmt_da->sql_errno() == ER_LOCK_DEADLOCK ||
-      thd->stmt_da->sql_errno() == ER_LOCK_WAIT_TIMEOUT)
+  if (error == ER_LOCK_DEADLOCK || error == ER_LOCK_WAIT_TIMEOUT)
     DBUG_RETURN(1);
 
 #ifdef HAVE_NDB_BINLOG
@@ -2637,6 +2646,13 @@ static int sql_delay_event(Log_event *ev
   DBUG_RETURN(0);
 }
 
+void clear_all_errors(THD *thd, Relay_log_info *rli)
+{
+  thd->is_slave_error = 0;
+  thd->clear_error();
+  rli->clear_error();
+}
+
 
 /**
   Applies the given event and advances the relay log position.
@@ -3007,10 +3023,13 @@ static int exec_relay_log_event(THD* thd
           }
         }
         else
+        {
           sql_print_error("Slave SQL thread retried transaction %lu time(s) "
                           "in vain, giving up. Consider raising the value of "
                           "the slave_transaction_retries variable.",
                           slave_trans_retries);
+          thd->is_fatal_error= 1; // to force has_temporary_error() return 0
+        }
       }
       else if ((exec_res && !temp_err) ||
                (opt_using_transactions &&
@@ -3491,6 +3510,7 @@ err:
     mi->mysql=0;
   }
   write_ignored_events_info_to_relay_log(thd, mi);
+  mi->display(0, NULL);
   thd_proc_info(thd, "Waiting for slave mutex on exit");
   mysql_mutex_lock(&mi->run_lock);
 
@@ -3776,39 +3796,10 @@ log '%s' at position %s, relay log '%s' 
       if (!sql_slave_killed(thd,rli))
       {
         /*
-          retrieve as much info as possible from the thd and, error
-          codes and warnings and print this to the error log as to
-          allow the user to locate the error
-        */
-        uint32 const last_errno= rli->last_error().number;
-
-        if (thd->is_error())
-        {
-          char const *const errmsg= thd->stmt_da->message();
-
-          DBUG_PRINT("info",
-                     ("thd->stmt_da->sql_errno()=%d; rli->last_error.number=%d",
-                      thd->stmt_da->sql_errno(), last_errno));
-          if (last_errno == 0)
-          {
-            /*
- 	      This function is reporting an error which was not reported
- 	      while executing exec_relay_log_event().
- 	    */ 
-            rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), "%s", errmsg);
-          }
-          else if (last_errno != thd->stmt_da->sql_errno())
-          {
-            /*
-             * An error was reported while executing exec_relay_log_event()
-             * however the error code differs from what is in the thread.
-             * This function prints out more information to help finding
-             * what caused the problem.
-             */  
-            sql_print_error("Slave (additional info): %s Error_code: %d",
-                            errmsg, thd->stmt_da->sql_errno());
-          }
-        }
+          Reporting all gather errors while executing exec_relay_log_event()
+          analogously send_error()
+        */ 
+        rli->display(0, NULL);
 
         /* Print any warnings issued */
         List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
@@ -3839,6 +3830,14 @@ llstr(rli->get_group_master_log_pos(), l
       }
       goto err;
     }
+    else
+    {
+      /*
+        Event applying succeeded, reset errors and diag area status
+      */
+      clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
+      thd->stmt_da->reset_diagnostics_area();
+    }
   }
 
   /* Thread stopped. Print the current replication position to the log */
@@ -3849,6 +3848,7 @@ llstr(rli->get_group_master_log_pos(), l
 
  err:
 
+  rli->display(0, NULL);
   /*
     Some events set some playgrounds, which won't be cleared because thread
     stops. Stopping of this thread may not be known to these events ("stop"

=== modified file 'sql/rpl_slave.h'
--- a/sql/rpl_slave.h	2011-02-16 17:13:30 +0000
+++ b/sql/rpl_slave.h	2011-03-24 17:17:13 +0000
@@ -213,6 +213,8 @@ void set_slave_thread_options(THD* thd);
 void set_slave_thread_default_charset(THD *thd, Relay_log_info const *rli);
 int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli);
 int rotate_relay_log(Master_info* mi);
+int has_temporary_error(THD *thd, uint err= 0);
+void clear_all_errors(THD *thd, Relay_log_info *rli);
 
 pthread_handler_t handle_slave_io(void *arg);
 pthread_handler_t handle_slave_sql(void *arg);


Attachment: [text/bzr-bundle] bzr/andrei.elkin@oracle.com-20110324171713-ipabhttwofc2ixrs.bundle
Thread
bzr commit into mysql-trunk branch (andrei.elkin:3311) Bug#11748510Andrei Elkin25 Mar