List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:June 1 2006 1:20pm
Subject:bk commit into 5.0 tree (cmiller:1.2162) BUG#16206
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of cmiller. When cmiller does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2162 06/06/01 09:20:20 cmiller@zippy.(none) +5 -0
  Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit 
  	mode
  
  This is a modification of serg's and guilhem's suggestion in the bug report,
  in that it also causes the transaction log to be written to disc.

  sql/log_event.h
    1.124 06/06/01 09:20:15 cmiller@zippy.(none) +5 -0
    Add the INVISIBLE_COMMIT static member.  It is initialized later, in log.cc .
    
    Add also a header for a parameterless Query_log_event constructor.

  sql/log_event.cc
    1.205 06/06/01 09:20:15 cmiller@zippy.(none) +20 -3
    Add a new parameterless Query_log_event constructor, so we can create an 
    impotent but meaningful INVISIBLE_COMMIT static member.

  sql/log.cc
    1.189 06/06/01 09:20:15 cmiller@zippy.(none) +36 -14
    Fill a new Query_log_event member, INVISIBLE_COMMIT, with a static instance 
    that represents that we are autocomitting and should flush out the transaction
    log.
    
    Test for this instance later in the log .write function.

  mysql-test/t/bdb.test
    1.52 06/06/01 09:20:14 cmiller@zippy.(none) +35 -0
    Add test

  mysql-test/r/bdb.result
    1.50 06/06/01 09:20:14 cmiller@zippy.(none) +34 -0
    Add result.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	cmiller
# Host:	zippy.(none)
# Root:	/home/cmiller/work/mysql/mysql-5.0__bug16206

--- 1.188/sql/log.cc	2006-03-31 04:47:59 -05:00
+++ 1.189/sql/log.cc	2006-06-01 09:20:15 -04:00
@@ -36,6 +36,10 @@
 MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log;
 ulong sync_binlog_counter= 0;
 
+/* For use in signaling to flush the log when autocomitting. */
+static Query_log_event invisible_commit = Query_log_event();
+Query_log_event *Query_log_event::INVISIBLE_COMMIT = &invisible_commit;
+
 static bool test_if_number(const char *str,
 			   long *res, bool allow_wildcards);
 static bool binlog_init();
@@ -94,7 +98,9 @@
 {
   int error=0;
   DBUG_ENTER("binlog_end_trans");
-  if (end_ev)
+
+  /* NULL denotes ROLLBACK with nothing to replicate */
+  if (end_ev != NULL)
     error= mysql_bin_log.write(thd, trans_log, end_ev);
 
   statistic_increment(binlog_cache_use, &LOCK_status);
@@ -126,14 +132,20 @@
   DBUG_ASSERT(mysql_bin_log.is_open() &&
      (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))));
 
-  if (!my_b_tell(trans_log))
+  if (my_b_tell(trans_log) == 0)
   {
     // we're here because trans_log was flushed in MYSQL_LOG::log()
     DBUG_RETURN(0);
   }
-  Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
-  qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
-  DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
+
+  if (all)
+  {
+    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
+    qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
+    DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
+  } 
+  else
+    DBUG_RETURN(binlog_end_trans(thd, trans_log, Query_log_event::INVISIBLE_COMMIT));
 }
 
 static int binlog_rollback(THD *thd, bool all)
@@ -161,7 +173,7 @@
     error= binlog_end_trans(thd, trans_log, &qev);
   }
   else
-    error= binlog_end_trans(thd, trans_log, 0);
+    error= binlog_end_trans(thd, trans_log, NULL);
   DBUG_RETURN(error);
 }
 
@@ -1799,6 +1811,7 @@
     - We only come here if there is something in the cache.
     - The thing in the cache is always a complete transaction
     - 'cache' needs to be reinitialized after this functions returns.
+    - 'commit_event' may be INVISIBLE_COMMIT when we're autocommitting.
 
   IMPLEMENTATION
     - To support transaction over replication, we wrap the transaction
@@ -1813,6 +1826,9 @@
   DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)");
   VOID(pthread_mutex_lock(&LOCK_log));
 
+  /* NULL would represent nothing to replicate after ROLLBACK */
+  DBUG_ASSERT(commit_event != NULL);
+
   if (likely(is_open()))                       // Should always be true
   {
     uint length;
@@ -1858,8 +1874,11 @@
       DBUG_EXECUTE_IF("half_binlogged_transaction", goto DBUG_skip_commit;);
     } while ((length=my_b_fill(cache)));
 
-    if (commit_event->write(&log_file))
-      goto err;
+    if (commit_event != Query_log_event::INVISIBLE_COMMIT)
+    {
+      if (commit_event->write(&log_file))
+        goto err;
+    } 
 #ifndef DBUG_OFF
 DBUG_skip_commit:
 #endif
@@ -1881,14 +1900,17 @@
       If the commit_event is not Xid_log_event (then it's a Query_log_event)
       rotate binlog, if necessary.
     */
-    if (commit_event->get_type_code() == XID_EVENT)
+    if (commit_event != Query_log_event::INVISIBLE_COMMIT)
     {
-      pthread_mutex_lock(&LOCK_prep_xids);
-      prepared_xids++;
-      pthread_mutex_unlock(&LOCK_prep_xids);
+      if (commit_event->get_type_code() == XID_EVENT)
+      {
+        pthread_mutex_lock(&LOCK_prep_xids);
+        prepared_xids++;
+        pthread_mutex_unlock(&LOCK_prep_xids);
+      }
+      else
+        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
     }
-    else
-      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
   }
   VOID(pthread_mutex_unlock(&LOCK_log));
 

--- 1.204/sql/log_event.cc	2006-03-21 08:35:44 -05:00
+++ 1.205/sql/log_event.cc	2006-06-01 09:20:15 -04:00
@@ -638,7 +638,7 @@
   ulong data_len;
   int result=0;
   char buf[LOG_EVENT_MINIMAL_HEADER_LEN];
-  DBUG_ENTER("read_log_event");
+  DBUG_ENTER("read_log_event(IO_CACHE*, String*, pthread_mutex_t*)");
 
   if (log_lock)
     pthread_mutex_lock(log_lock);
@@ -708,12 +708,14 @@
 Log_event* Log_event::read_log_event(IO_CACHE* file,
 				     pthread_mutex_t* log_lock,
                                      const Format_description_log_event *description_event)
+{
+  DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, pthread_mutex_t *, Format_description_log_event *)");
 #else
 Log_event* Log_event::read_log_event(IO_CACHE* file,
                                      const Format_description_log_event *description_event)
-#endif
 {
-  DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, Format_description_log_event *");
+  DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, Format_description_log_event *)");
+#endif
   DBUG_ASSERT(description_event != 0);
   char head[LOG_EVENT_MINIMAL_HEADER_LEN];
   /*
@@ -1227,6 +1229,21 @@
                           (uint) (start-start_of_status)) ||
           my_b_safe_write(file, (db) ? (byte*) db : (byte*)"", db_len + 1) ||
           my_b_safe_write(file, (byte*) query, q_len)) ? 1 : 0;
+}
+
+
+/*
+  Query_log_event::Query_log_event()
+ 
+  The simplest constructor that could possibly work.  This is used for
+  creating static objects that have a special meaning and are invisible
+  to the log.  
+
+  See Query_log_event::INVISIBLE_COMMIT for an example of its usage.
+*/
+Query_log_event::Query_log_event()
+  :Log_event(), data_buf(0)
+{
 }
 
 

--- 1.123/sql/log_event.h	2006-02-25 10:46:25 -05:00
+++ 1.124/sql/log_event.h	2006-06-01 09:20:15 -04:00
@@ -606,6 +606,7 @@
     the slave's data is modified.
   */
   virtual int exec_event(struct st_relay_log_info* rli);
+
 #endif /* HAVE_REPLICATION */
   virtual const char* get_db()
   {
@@ -766,6 +767,7 @@
   char charset[6];
   uint time_zone_len; /* 0 means uninited */
   const char *time_zone_str;
+  static Query_log_event *INVISIBLE_COMMIT;
 
 #ifndef MYSQL_CLIENT
 
@@ -783,6 +785,9 @@
   void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0);
 #endif
 
+  /* Constructor for creating a static object with a special meaning. */
+  Query_log_event();
+  
   Query_log_event(const char* buf, uint event_len,
                   const Format_description_log_event *description_event,
                   Log_event_type event_type);

--- 1.49/mysql-test/r/bdb.result	2006-01-06 11:34:51 -05:00
+++ 1.50/mysql-test/r/bdb.result	2006-06-01 09:20:14 -04:00
@@ -1928,4 +1928,38 @@
 commit;
 alter table t1 add primary key(a);
 drop table t1;
+set autocommit=1;
+reset master;
+create table bug16206 (a int) engine=         blackhole;
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+show binlog events;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+f	n	Format_desc	1	n	Server ver: VERSION, Binlog ver: 4
+f	n	Query	1	n	use `test`; create table bug16206 (a int) engine=         blackhole
+f	n	Query	1	n	use `test`; insert into bug16206 values(1)
+f	n	Query	1	n	use `test`; insert into bug16206 values(2)
+drop table bug16206;
+reset master;
+create table bug16206 (a int) engine=         bdb;
+insert into bug16206 values(0);
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+insert into bug16206 values(3);
+show binlog events;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+f	n	Format_desc	1	n	Server ver: VERSION, Binlog ver: 4
+f	n	Query	1	n	use `test`; create table bug16206 (a int) engine=         bdb
+f	n	Query	1	n	use `test`; insert into bug16206 values(0)
+f	n	Query	1	n	use `test`; insert into bug16206 values(1)
+f	n	Query	1	n	use `test`; BEGIN
+f	n	Query	1	n	use `test`; insert into bug16206 values(2)
+f	n	Query	1	n	use `test`; COMMIT
+f	n	Query	1	n	use `test`; insert into bug16206 values(3)
+drop table bug16206;
+set autocommit=0;
 End of 5.0 tests

--- 1.51/mysql-test/t/bdb.test	2006-01-06 11:34:51 -05:00
+++ 1.52/mysql-test/t/bdb.test	2006-06-01 09:20:14 -04:00
@@ -1019,4 +1019,39 @@
 alter table t1 add primary key(a);
 drop table t1;
 
+
+#
+# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode
+#
+set autocommit=1;
+
+let $VERSION=`select version()`;
+
+reset master;
+create table bug16206 (a int) engine=         blackhole;
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+--replace_result $VERSION VERSION
+--replace_column 1 f 2 n 5 n
+show binlog events;
+drop table bug16206;
+
+reset master;
+create table bug16206 (a int) engine=         bdb;
+insert into bug16206 values(0);
+insert into bug16206 values(1);
+start transaction;
+insert into bug16206 values(2);
+commit;
+insert into bug16206 values(3);
+--replace_result $VERSION VERSION
+--replace_column 1 f 2 n 5 n
+show binlog events;
+drop table bug16206;
+
+set autocommit=0;
+
+
 --echo End of 5.0 tests
Thread
bk commit into 5.0 tree (cmiller:1.2162) BUG#16206Chad MILLER1 Jun