List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:March 9 2012 5:00pm
Subject:bzr push into mysql-trunk branch (frazer.clement:3744 to 3745) Bug#54854
View as plain text  
 3745 Frazer Clement	2012-03-09
      Bug#54854 Can't find good position for replication break between DDL statements
      
      Part 1 of patches to mysql-trunk.
      
      Overall fix has two parts :
        1) Improve Ndb replication channel cutover with precise 
           next-position-after-epoch-trans in the mysql.ndb_binlog_index
           table.
        2) Simplify configuration of DDL-idempotency with a new
           MySQL Server option
      
      Part 1) of the fix includes patches affecting the generic MySQL Server
      (this commit) and patches affecting the Ndb storage engine.
      
      Part 2) of the fix includes patches affecting the generic MySQL Server.
      
      This commit adds a THD member which records the next Binlog position
      (filename and offset) after the last Binlog event recorded by the
      thread.
      This information is exposed via an extension to the Binlog injector
      Api.
      
      Further patches to be pushed to the MySQL Cluster branches make use
      of this functionality to fix bug#54854.
      
      In mysql-trunk builds, this functionality has no externally visible
      effect, and therefore no specific testcase.
      
      Testcases are added in branches merging this branch and MySQL Cluster.

    modified:
      sql/binlog.cc
      sql/binlog.h
      sql/log.h
      sql/log_event.h
      sql/rpl_injector.cc
      sql/rpl_injector.h
      sql/sql_class.cc
      sql/sql_class.h
 3744 Jorgen Loland	2012-03-09
      Bug#13810145: FIX WARNINGS BY FORTIFY
     @ sql/opt_range.cc
        Fix Fortify warning

    modified:
      sql/opt_range.cc
=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2012-03-06 14:29:42 +0000
+++ b/sql/binlog.cc	2012-03-09 16:56:10 +0000
@@ -4160,6 +4160,19 @@ MYSQL_BIN_LOG::remove_pending_rows_event
 }
 
 /*
+  Updates thd's position-of-next-event variables
+  after a *real* write a file.
+ */
+void MYSQL_BIN_LOG::update_thd_next_event_pos(THD* thd)
+{
+  if (likely(thd != NULL))
+  {
+    thd->set_next_event_pos(log_file_name,
+                            my_b_tell(&log_file));
+  }
+}
+
+/*
   Moves the last bunch of rows from the pending Rows event to a cache (either
   transactional cache if is_transaction is @c true, or the non-transactional
   cache otherwise. Sets a new pending event.
@@ -4924,12 +4937,14 @@ bool MYSQL_BIN_LOG::write_cache(THD *thd
       mysql_mutex_lock(&LOCK_prep_xids);
       prepared_xids++;
       mysql_mutex_unlock(&LOCK_prep_xids);
+      update_thd_next_event_pos(thd);
       mysql_mutex_unlock(&LOCK_log);
     }
     else
     {
       if (rotate(false, &check_purge))
         goto err;
+      update_thd_next_event_pos(thd);
       mysql_mutex_unlock(&LOCK_log);
       if (check_purge) 
         purge();

=== modified file 'sql/binlog.h'
--- a/sql/binlog.h	2012-01-26 10:53:34 +0000
+++ b/sql/binlog.h	2012-03-09 16:56:10 +0000
@@ -213,6 +213,7 @@ public:
   int recover(IO_CACHE *log, Format_description_log_event *fdle);
 #if !defined(MYSQL_CLIENT)
 
+  void update_thd_next_event_pos(THD *thd);
   int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
                                        bool is_transactional);
   int remove_pending_rows_event(THD *thd, bool is_transactional);

=== modified file 'sql/log.h'
--- a/sql/log.h	2011-12-09 21:08:37 +0000
+++ b/sql/log.h	2012-03-09 16:56:10 +0000
@@ -19,6 +19,21 @@
 #include "unireg.h"                    // REQUIRED: for other includes
 #include "handler.h"                            /* my_xid */
 
+/**
+  the struct aggregates two paramenters that identify an event
+  uniquely in scope of communication of a particular master and slave couple.
+  I.e there can not be 2 events from the same staying connected master which
+  have the same coordinates.
+  @note
+  Such identifier is not yet unique generally as the event originating master
+  is resetable. Also the crashed master can be replaced with some other.
+*/
+typedef struct event_coordinates
+{
+  char * file_name; // binlog file name (directories stripped)
+  my_off_t  pos;       // event's position in the binlog file
+} LOG_POS_COORD;
+
 /*
   Transaction Coordinator log - a base abstract class
   for two different implementations

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2012-03-06 14:29:42 +0000
+++ b/sql/log_event.h	2012-03-09 16:56:10 +0000
@@ -812,21 +812,6 @@ typedef struct st_print_event_info
 #endif
 
 /**
-  the struct aggregates two paramenters that identify an event
-  uniquely in scope of communication of a particular master and slave couple.
-  I.e there can not be 2 events from the same staying connected master which
-  have the same coordinates.
-  @note
-  Such identifier is not yet unique generally as the event originating master
-  is resetable. Also the crashed master can be replaced with some other.
-*/
-typedef struct event_coordinates
-{
-  char * file_name; // binlog file name (directories stripped)
-  my_off_t  pos;       // event's position in the binlog file
-} LOG_POS_COORD;
-
-/**
   @class Log_event
 
   This is the abstract base class for binary log events.

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2012-03-06 14:29:42 +0000
+++ b/sql/rpl_injector.cc	2012-03-09 16:56:10 +0000
@@ -41,6 +41,28 @@ injector::transaction::transaction(MYSQL
   m_start_pos.m_file_name= my_strdup(log_info.log_file_name, MYF(0));
   m_start_pos.m_file_pos= log_info.pos;
 
+  if (unlikely(m_start_pos.m_file_name == NULL))
+  {
+    m_thd= NULL;
+    return;
+  }
+
+  /*
+     Next pos is unknown until after commit of the Binlog transaction
+  */
+  m_next_pos.m_file_name= 0;
+  m_next_pos.m_file_pos= 0;
+
+  /*
+    Ensure we don't pick up this thd's last written Binlog pos in
+    empty-transaction-commit cases.
+    This is not ideal, as it zaps this information for any other
+    usage (e.g. WL4047)
+    Potential improvement : save the 'old' next pos prior to
+    commit, and restore on error.
+  */
+  m_thd->clear_next_event_pos();
+
   trans_begin(m_thd);
 }
 
@@ -50,16 +72,18 @@ injector::transaction::~transaction()
     return;
 
   /* Needed since my_free expects a 'char*' (instead of 'void*'). */
-  char* const the_memory= const_cast<char*>(m_start_pos.m_file_name);
+  char* const start_pos_memory= const_cast<char*>(m_start_pos.m_file_name);
 
-  /*
-    We set the first character to null just to give all the copies of the
-    start position a (minimal) chance of seening that the memory is lost.
-    All assuming the my_free does not step over the memory, of course.
-  */
-  *the_memory= '\0';
-
-  my_free(the_memory);
+  if (start_pos_memory)
+  {
+    my_free(start_pos_memory);
+  }
+
+  char* const next_pos_memory= const_cast<char*>(m_next_pos.m_file_name);
+  if (next_pos_memory)
+  {
+    my_free(next_pos_memory);
+  }
 }
 
 /**
@@ -95,6 +119,22 @@ int injector::transaction::commit()
      close_thread_tables(m_thd);
      m_thd->mdl_context.release_transactional_locks();
    }
+
+   /* Copy next position out into our next pos member */
+   if ((error == 0) &&
+       (m_thd->binlog_next_event_pos.file_name != NULL) &&
+       ((m_next_pos.m_file_name=
+         my_strdup(m_thd->binlog_next_event_pos.file_name, MYF(0))) != NULL))
+   {
+     m_next_pos.m_file_pos= m_thd->binlog_next_event_pos.pos;
+   }
+   else
+   {
+     /* Error, problem copying etc. */
+     m_next_pos.m_file_name= NULL;
+     m_next_pos.m_file_pos= 0;
+   }
+
    DBUG_RETURN(error);
 }
 
@@ -199,6 +239,10 @@ injector::transaction::binlog_pos inject
    return m_start_pos;			
 }
 
+injector::transaction::binlog_pos injector::transaction::next_pos() const
+{
+   return m_next_pos;
+}
 
 /*
   injector - member definitions

=== modified file 'sql/rpl_injector.h'
--- a/sql/rpl_injector.h	2011-09-28 09:12:47 +0000
+++ b/sql/rpl_injector.h	2012-03-09 16:56:10 +0000
@@ -241,14 +241,30 @@ public:
       /*
         Get the position for the start of the transaction.
 
-        Returns the position in the binary log of the first event in this
-        transaction. If no event is yet written, the position where the event
-        *will* be written is returned. This position is known, since a
-        new_transaction() will lock the binary log and prevent any other
-        writes to the binary log.
+        This is the current 'tail of Binlog' at the time the transaction
+        was started.  The first event recorded by the transaction may
+        be at this, or some subsequent position.  The first event recorded
+        by the transaction will not be before this position.
       */
       binlog_pos start_pos() const;
 
+      /*
+        Get the next position after the end of the transaction
+
+        This call is only valid after a transaction has been committed.
+        It returns the next Binlog position after the committed transaction.
+        It is guaranteed that no other events will be recorded between the
+        COMMIT event of the Binlog transaction, and this position.
+        Note that this position may be in a different log file to the COMMIT
+        event.
+
+        If the commit had an error, or the transaction was empty and nothing
+        was binlogged then the next_pos will have a NULL file_name(), and
+        0 file_pos().
+
+      */
+      binlog_pos next_pos() const;
+
     private:
       /* Only the injector may construct these object */
       transaction(MYSQL_BIN_LOG *, THD *);
@@ -261,6 +277,13 @@ public:
           o.m_start_pos= tmp;
         }
 
+        /* std::swap(m_end_pos, o.m_end_pos); */
+        {
+          binlog_pos const tmp= m_next_pos;
+          m_next_pos= o.m_next_pos;
+          o.m_next_pos= tmp;
+        }
+
         /* std::swap(m_thd, o.m_thd); */
         {
           THD* const tmp= m_thd;
@@ -333,6 +356,7 @@ public:
 
 
       binlog_pos m_start_pos;
+      binlog_pos m_next_pos;
       THD *m_thd;
     };
 

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2012-03-06 14:29:42 +0000
+++ b/sql/sql_class.cc	2012-03-09 16:56:10 +0000
@@ -930,6 +930,9 @@ THD::THD(bool enable_plugins)
   m_binlog_invoker= FALSE;
   memset(&invoker_user, 0, sizeof(invoker_user));
   memset(&invoker_host, 0, sizeof(invoker_host));
+
+  binlog_next_event_pos.file_name= NULL;
+  binlog_next_event_pos.pos= 0;
 }
 
 
@@ -1418,6 +1421,8 @@ THD::~THD()
   if (m_enable_plugins)
     plugin_thdvar_cleanup(this);
 
+  clear_next_event_pos();
+
   DBUG_PRINT("info", ("freeing security context"));
   main_security_ctx.destroy();
   my_free(db);
@@ -4538,3 +4543,30 @@ void COPY_INFO::set_function_defaults(TA
     }
   DBUG_VOID_RETURN;
 }
+
+void THD::set_next_event_pos(const char* _filename, ulonglong _pos)
+{
+  char*& filename= binlog_next_event_pos.file_name;
+  if (filename == NULL)
+  {
+    /* First time, allocate maximal buffer */
+    filename= (char*) my_malloc(FN_REFLEN+1, MYF(MY_WME));
+    if (filename == NULL) return;
+  }
+
+  assert(strlen(_filename) <= FN_REFLEN);
+  strcpy(filename, _filename);
+  filename[ FN_REFLEN ]= 0;
+
+  binlog_next_event_pos.pos= _pos;
+};
+
+void THD::clear_next_event_pos()
+{
+  if (binlog_next_event_pos.file_name != NULL)
+  {
+    my_free(binlog_next_event_pos.file_name);
+  }
+  binlog_next_event_pos.file_name= NULL;
+  binlog_next_event_pos.pos= 0;
+};

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2012-03-06 14:29:42 +0000
+++ b/sql/sql_class.h	2012-03-09 16:56:10 +0000
@@ -2348,6 +2348,15 @@ public:
   /* container for handler's private per-connection data */
   Ha_data ha_data[MAX_HA];
 
+  /*
+    Position of first event in Binlog
+    *after* last event written by this
+    thread.
+  */
+  event_coordinates binlog_next_event_pos;
+  void set_next_event_pos(const char* _filename, ulonglong _pos);
+  void clear_next_event_pos();
+
 #ifndef MYSQL_CLIENT
   int binlog_setup_trx_data();
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (frazer.clement:3744 to 3745) Bug#54854Frazer Clement12 Mar