mariadb/mysql-test/t/mysqlbinlog_base64.test
unknown 6f6951d218 Fix for BUG#25628: "mysqlbinlog crashes while processing binary logs".
mysqlbinlog prints all row-based events of a single statement as a
single "BINLOG" statement containing the concatenation of those events.
Big (i.e. >64k) concatenations of row-based events
(e.g. Write_rows_log_event) caused mysqlbinlog's IO_CACHE to overflow
to a temporary file but the IO_CACHE had not been inited with
open_cached_file(), so it tried to create a temporary file in
an uninitialized directory (thus failing to create, then to write;
some OS errors were printed, and it finally segfaulted).
After fixing this, it appeared that mysqlbinlog was printing only
a piece of big concatenations of row-based events (it printed
at most the size of the IO_CACHE's buffer i.e. 64k); that caused data
loss at restore. We fix and test that.
Last, mysqlbinlog's printouts looked a bit strange with the informative
header (#-prefixed) of groupped Rows_log_event all on one line,
so we insert \n. After that, a small bug in the --hexdump code appeared
(only if the string to hex-print had its length a multiple of 16),
we fix it.



client/mysqlbinlog.cc:
  if we write to IO_CACHE more than can fit into its memory buffer,
  it will try to overflow into a file; for that to work, IO_CACHE
  must be inited via open_cached_file().
mysql-test/r/mysqlbinlog_base64.result:
  result update
mysql-test/t/mysqlbinlog_base64.test:
  test for BUG#25628: test that mysqlbinlog does not have OS errors
  with big concatenations of row-based events
  (e.g. Write_rows_log_event), and prints those concatenations entirely
  (testing by piping the output back into the server and comparing data).
mysys/mf_iocache2.c:
  my_b_copy_to_file() had a problem: it assumed that bytes_in_cache
  are all the bytes to copy to the file, while it only tells how many
  bytes are in the buffer; so the code forgot to copy what had already
  overflown into a temporary file. Thus any big event was printed only
  partially by mysqlbinlog (loss of data at restore). The fix is
  inspired by MYSQL_BIN_LOG::write_cache().
sql/log_event.cc:
  Several Table_map/Write_rows events generated by one single statement
  get groupped together in mysqlbinlog's output; it printed things like
  #718 7:30:51 server id 12 end_log_pos 988      Write_rows: table id 17#718 7:30:51 server id 12 #718 7:30:51 server id 12  end_log_pos 988      Write_rows: table id 17#718 7:30:51 server id 12 end_log_pos 1413 <cut>
  It didn't look nice to have printouts glued like this without line
  breaks. Adding a line break.
  Doing this, when using --hexdump the result was:
  #718 7:30:51 server id 12 end_log_pos 988
  # <hexdump output>
  # Write_rows: table id 17
  which is correct; unfortunately if the hex dump had only full lines
  (i.e the string to print in hex had its length a multiple of 16),
  then the # in front of Write_rows was not printed. Fixed.
sql/log_event.h:
  removing strcpy() (one less function call).
  If we write to IO_CACHE more than can fit into its memory buffer,
  it will try to overflow into a file; for that to work, IO_CACHE
  must be inited via open_cached_file().
  open_cached_file(), like init_io_cache(), can fail; we make sure to
  catch this constructor's problem via the init_ok() method.
2007-02-23 22:23:54 +01:00

67 lines
1.6 KiB
Text

-- source include/have_binlog_format_row.inc
#
# Write different events to binlog
#
create table t1 (a int);
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
update t1 set a=a+2 where a=2;
update t1 set a=a+2 where a=3;
create table t2 (word varchar(20));
load data infile '../std_data_ln/words.dat' into table t2;
#
# Save binlog
#
flush logs;
--exec $MYSQL_BINLOG --hexdump $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
#
# Clear database and restore from binlog
#
drop table t1;
drop table t2;
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
#
# Verify that all binlog events have been executed
#
select * from t1;
select * from t2;
#
# Verify that events larger than the default IO_CACHE buffer
# are handled correctly (BUG#25628).
#
flush logs;
drop table t2;
create table t2 (word varchar(20));
load data infile '../std_data_ln/words.dat' into table t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
select count(*) from t2;
flush logs;
--exec $MYSQL_BINLOG --hexdump $MYSQLTEST_VARDIR/log/master-bin.000003 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
#
# Verify that all binlog events have been executed
#
select count(*) from t2;
#
# Test cleanup
#
--exec rm $MYSQLTEST_VARDIR/tmp/mysqlbinlog_base64.sql
drop table t1;
drop table t2;