Commit 1c157094 authored by unknown's avatar unknown
Browse files

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.


mysql-test/r/bdb.result:
  Add result.
mysql-test/t/bdb.test:
  Add test
sql/log.cc:
  Create a log-committing event that itself won't be written to the log when 
  we're in autocommit mode.
sql/log_event.cc:
  Add a new subclass of Query_log_event that doesn't write itself to the log, for
  cases where we only want to flush out the transaction and not also write about
  this event.
sql/log_event.h:
  Add a new subclass of Query_log_event that doesn't write itself to the log, for
  cases where we only want to flush out the transaction and not also write about
  this event.
parent 168cad46
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -1928,4 +1928,38 @@ create table t1 (a int) engine=bdb;
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
+35 −0
Original line number Diff line number Diff line
@@ -1019,4 +1019,39 @@ commit;
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
+17 −5
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
MYSQL_LOG mysql_log, mysql_slow_log, mysql_bin_log;
ulong sync_binlog_counter= 0;

static Muted_query_log_event invisible_commit;

static bool test_if_number(const char *str,
			   long *res, bool allow_wildcards);
static bool binlog_init();
@@ -94,7 +96,9 @@ static int binlog_end_trans(THD *thd, IO_CACHE *trans_log, Log_event *end_ev)
{
  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,15 +130,20 @@ static int binlog_commit(THD *thd, bool all)
  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);
  }
  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, &invisible_commit));
}

static int binlog_rollback(THD *thd, bool all)
{
@@ -1813,6 +1822,9 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
  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;
+27 −0
Original line number Diff line number Diff line
@@ -1229,6 +1229,18 @@ bool Query_log_event::write(IO_CACHE* file)
          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.  
*/
Query_log_event::Query_log_event()
  :Log_event(), data_buf(0)
{
}


/*
  Query_log_event::Query_log_event()
@@ -1875,6 +1887,21 @@ Default database: '%s'. Query: '%s'",
#endif


/**************************************************************************
	Muted_query_log_event methods
**************************************************************************/

#ifndef MYSQL_CLIENT
/*
  Muted_query_log_event::Muted_query_log_event()
*/
Muted_query_log_event::Muted_query_log_event()
  :Query_log_event()
{
}
#endif


/**************************************************************************
	Start_log_event_v3 methods
**************************************************************************/
+21 −0
Original line number Diff line number Diff line
@@ -783,6 +783,7 @@ class Query_log_event: public Log_event
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info= 0);
#endif

  Query_log_event();
  Query_log_event(const char* buf, uint event_len,
                  const Format_description_log_event *description_event,
                  Log_event_type event_type);
@@ -806,6 +807,26 @@ class Query_log_event: public Log_event
  /* Writes derived event-specific part of post header. */
};


/*****************************************************************************

  Muted Query Log Event class

  Pretends to Log SQL queries, but doesn't actually do so.

 ****************************************************************************/
class Muted_query_log_event: public Query_log_event
{
public:
#ifndef MYSQL_CLIENT
  Muted_query_log_event();

  bool write(IO_CACHE* file) { return(false); };
  virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
#endif
};


#ifdef HAVE_REPLICATION

/*****************************************************************************