diff options
67 files changed, 3034 insertions, 1243 deletions
diff --git a/.bzrignore b/.bzrignore index 0a28dc4af94..170e29c6af6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -336,6 +336,7 @@ client/rpl_record_old.h client/rpl_tblmap.h client/rpl_tblmap.cc client/rpl_utility.h +client/rpl_utility.cc client/select_test client/sql_string.cpp client/ssl_test @@ -672,6 +673,8 @@ libmysqld/unireg.cc libmysqld/discover_xt.cc libmysqld/ha_pbxt.cc libmysqld/myxt_xt.cc +libmysqld/rpl_reporting.cc +libmysqld/rpl_utility.cc libmysqltest/*.ds? libmysqltest/*.vcproj libmysqltest/mytest.c diff --git a/client/Makefile.am b/client/Makefile.am index f3f964ace7b..8abf33dc3e2 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -63,7 +63,8 @@ mysqlbinlog_SOURCES = mysqlbinlog.cc \ $(top_srcdir)/mysys/my_bit.c \ $(top_srcdir)/mysys/my_bitmap.c \ $(top_srcdir)/mysys/my_vle.c \ - $(top_srcdir)/mysys/base64.c + $(top_srcdir)/mysys/base64.c \ + $(top_srcdir)/mysys/checksum.c mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) mysqldump_SOURCES= mysqldump.c \ @@ -106,6 +107,7 @@ sql_src=log_event.h mysql_priv.h rpl_constants.h \ log_event.cc my_decimal.h my_decimal.cc \ log_event_old.h log_event_old.cc \ rpl_record_old.h rpl_record_old.cc \ + rpl_utility.h rpl_utility.cc \ sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc strings_src=decimal.c strings_def.h diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 9e4ef2a4c2d..16fd7150c0c 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -83,6 +83,7 @@ static const char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool force_if_open_opt= 1; +static my_bool opt_verify_binlog_checksum= 1; static ulonglong offset = 0; static const char* host = 0; static int port= 0; @@ -163,7 +164,8 @@ Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len, event_buf[event_len]= 0; if (!(event= Log_event::read_log_event((const char*) event_buf, event_len, - error_msg, glob_description_event))) + error_msg, glob_description_event, + opt_verify_binlog_checksum))) { my_free(event_buf, MYF(0)); return 0; @@ -1310,6 +1312,9 @@ that may lead to an endless loop.", "Used to reserve file descriptors for use by this program.", &open_files_limit, &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, + {"verify-binlog-checksum", 'c', "Verify checksum binlog events.", + (uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"rewrite-db", OPT_REWRITE_DB, "Updates to a database with a different name than the original. \ Example: rewrite-db='from->to'.", @@ -1708,7 +1713,18 @@ static Exit_status check_master_version() "Master reported NULL for the version."); goto err; } - + /* + Make a notice to the server that this client + is checksum-aware. It does not need the first fake Rotate + necessary checksummed. + That preference is specified below. + */ + if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'")) + { + error("Could not notify master about checksum awareness." + "Master returned '%s'", mysql_error(mysql)); + goto err; + } delete glob_description_event; switch (*version) { case '3': @@ -1837,7 +1853,8 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, { if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , len - 1, &error_msg, - glob_description_event))) + glob_description_event, + opt_verify_binlog_checksum))) { error("Could not construct log event object: %s", error_msg); DBUG_RETURN(ERROR_STOP); @@ -2065,7 +2082,8 @@ static Exit_status check_header(IO_CACHE* file, Format_description_log_event *new_description_event; my_b_seek(file, tmp_pos); /* seek back to event's start */ if (!(new_description_event= (Format_description_log_event*) - Log_event::read_log_event(file, glob_description_event))) + Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum))) /* EOF can't be hit here normally, so it's a real error */ { error("Could not read a Format_description_log_event event at " @@ -2098,7 +2116,8 @@ static Exit_status check_header(IO_CACHE* file, { Log_event *ev; my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!(ev= Log_event::read_log_event(file, glob_description_event))) + if (!(ev= Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum))) { /* EOF can't be hit here normally, so it's a real error */ error("Could not read a Rotate_log_event event at offset %llu;" @@ -2211,7 +2230,8 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, char llbuff[21]; my_off_t old_off = my_b_tell(file); - Log_event* ev = Log_event::read_log_event(file, glob_description_event); + Log_event* ev = Log_event::read_log_event(file, glob_description_event, + opt_verify_binlog_checksum); if (!ev) { /* @@ -2390,4 +2410,4 @@ void *sql_alloc(size_t size) #include "sql_string.cc" #include "sql_list.cc" #include "rpl_filter.cc" - +#include "rpl_utility.cc" diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index acf2dca9882..e68aa8a1df8 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -138,7 +138,8 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc ../sql/partition_info.cc ../sql/sql_connect.cc ../sql/scheduler.cc ../sql/event_parse_data.cc - ../sql/create_options.cc + ../sql/create_options.cc ../sql/rpl_utility.cc + ../sql/rpl_reporting.cc ${GEN_SOURCES} ${LIB_SOURCES}) diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index ef17a0a6923..37b93e8bd8f 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -55,7 +55,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ item_geofunc.cc item_subselect.cc item_row.cc\ item_xmlfunc.cc \ key.cc lock.cc log.cc sql_state.c \ - log_event.cc rpl_record.cc \ + log_event.cc rpl_record.cc rpl_utility.cc rpl_reporting.cc \ log_event_old.cc rpl_record_old.cc \ protocol.cc net_serv.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ diff --git a/mysql-test/collections/mysql-next-mr-wl2540.push b/mysql-test/collections/mysql-next-mr-wl2540.push new file mode 100644 index 00000000000..2eb41427687 --- /dev/null +++ b/mysql-test/collections/mysql-next-mr-wl2540.push @@ -0,0 +1,6 @@ +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_checksum --mysqld=--binlog-checksum=CRC32 --vardir=var-rpl_binlog_checksum --suite=binlog,rpl --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-test-list=collections/disabled-per-push.list +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 diff --git a/mysql-test/collections/mysql-trunk.daily b/mysql-test/collections/mysql-trunk.daily new file mode 100644 index 00000000000..47d189a2c65 --- /dev/null +++ b/mysql-test/collections/mysql-trunk.daily @@ -0,0 +1,7 @@ +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --vardir=var-n_mix --mysqld=--binlog-format=mixed +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --vardir=var-ps_row --ps-protocol --mysqld=--binlog-format=row +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --vardir=var-emebbed --embedded +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --vardir=var-funcs_1 --suite=funcs_1 +perl mysql-test-run.pl --timer --force --parallel=auto --comment=rpl_ndb_row --vardir=var-rpl_ndb_row --mysqld=--binlog-format=row --suite=rpl_ndb,ndb +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --vardir=var-rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog --skip-ndb +perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_checksum --mysqld=--binlog-checksum=CRC32 --vardir=var-rpl_binlog_checksum --suite=binlog,rpl diff --git a/mysql-test/collections/mysql-trunk.weekly b/mysql-test/collections/mysql-trunk.weekly new file mode 100644 index 00000000000..7186ad422b0 --- /dev/null +++ b/mysql-test/collections/mysql-trunk.weekly @@ -0,0 +1,2 @@ +perl mysql-test-run.pl --timer --force --comment=1st --experimental=collections/default.experimental 1st +perl mysql-test-run.pl --timer --force --comment=all_binlog_checksum --experimental=collections/default.experimental --mysqld=--binlog-checksum=CRC32 --vardir=var-all_binlog_checksum --suite=main,binlog,innodb,federated,rpl,sys_vars,perfschema diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index fd6ba1c17fa..4a12bba3eb2 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -83,17 +83,22 @@ set @bcs = @@binlog_cache_size; set global binlog_cache_size=4096; reset master; -create table t1 (a int) engine=innodb; +create table t1 (a int, b char(255)) engine=innodb; + +flush status; +show status like "binlog_cache_use"; -let $1=400; +let $1=100; disable_query_log; begin; while ($1) { - eval insert into t1 values( $1 ); + eval insert into t1 values( $1, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ); dec $1; } commit; +--echo *** the following must show the counter value = 1 *** +show status like "binlog_cache_use"; enable_query_log; --source include/show_binlog_events.inc diff --git a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test index 96c85e024e9..c7e7a491ce1 100644 --- a/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test +++ b/mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test @@ -311,6 +311,7 @@ select get_lock("a",10); begin; insert into t1 values(8); insert into t2 select * from t1; + disconnect con3; connection con4; diff --git a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test index 06253c5defb..5cbda2d591f 100644 --- a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test +++ b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test @@ -15,6 +15,7 @@ create table t3 (a int) engine=merge union(t1); create table t4 (a int); # We force the slave to open t3 (because we want to try confusing him) with this : insert into t4 select * from t3; +--let $rename_event_pos= query_get_value(SHOW MASTER STATUS, Position, 1) rename table t1 to t5, t2 to t1; # RENAME may have confused the master (this is a known bug): so FLUSH tables, # first don't write it to the binlog, to test the NO_WRITE_TO_BINLOG keyword. diff --git a/mysql-test/extra/rpl_tests/rpl_reset_slave.test b/mysql-test/extra/rpl_tests/rpl_reset_slave.test index 04ab8751e39..182fde40193 100644 --- a/mysql-test/extra/rpl_tests/rpl_reset_slave.test +++ b/mysql-test/extra/rpl_tests/rpl_reset_slave.test @@ -10,6 +10,9 @@ -- source include/master-slave.inc sync_slave_with_master; +--disable_query_log +call mtr.add_suppression('Slave I/O: Get master BINLOG_CHECKSUM failed with error'); +--enable_query_log let $status_items= Master_User, Master_Host; source include/show_slave_status.inc; diff --git a/mysql-test/include/binlog_start_pos.inc b/mysql-test/include/binlog_start_pos.inc index f6d1c4c68a3..add5a42a426 100644 --- a/mysql-test/include/binlog_start_pos.inc +++ b/mysql-test/include/binlog_start_pos.inc @@ -11,16 +11,18 @@ # Format_description_log_event length = # 19 /* event common header */ + # 57 /* misc stuff in the Format description header */ + -# number of events. +# number of events + +# 1 /* Checksum algorithm */ + +# 4 /* CRC32 length */ # # With current number of events = 160, # -# binlog_start_pos = 4 + 19 + 57 + 160 = 240. +# binlog_start_pos = 4 + 19 + 57 + 160 + 1 + 4 = 245. # ############################################################################## -let $binlog_start_pos=240; +let $binlog_start_pos=245; --disable_query_log -SET @binlog_start_pos=240; +SET @binlog_start_pos=245; --enable_query_log diff --git a/mysql-test/include/have_binlog_checksum_off.inc b/mysql-test/include/have_binlog_checksum_off.inc new file mode 100644 index 00000000000..c7c444c8785 --- /dev/null +++ b/mysql-test/include/have_binlog_checksum_off.inc @@ -0,0 +1,4 @@ +if (`select variable_value not like 'NONE' from information_schema.GLOBAL_VARIABLES + where variable_name='binlog_checksum'`){ + skip Can not run the test when server activated checksumming; +} diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 39ba623f247..caa07b6d5ae 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -209,6 +209,9 @@ INSERT INTO global_suppressions VALUES ("Slave I/O: Get master clock failed with error:.*"), ("Slave I/O: Get master COLLATION_SERVER failed with error:.*"), ("Slave I/O: Get master TIME_ZONE failed with error:.*"), + ("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum on master.*"), + ("Slave I/O: Get master BINLOG_CHECKSUM failed with error.*"), + ("Slave I/O: Notifying master by SET @master_binlog_checksum= @@global.binlog_checksum failed with error.*"), ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/include/show_binlog_events2.inc b/mysql-test/include/show_binlog_events2.inc index 96e42e93f90..c32d12537fd 100644 --- a/mysql-test/include/show_binlog_events2.inc +++ b/mysql-test/include/show_binlog_events2.inc @@ -1,4 +1,4 @@ ---let $binlog_start=240 +--let $binlog_start=245 --replace_result $binlog_start <binlog_start> --replace_column 2 # 5 # --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ diff --git a/mysql-test/r/mysqldump-max.result b/mysql-test/r/mysqldump-max.result index cc5fe207800..6722f308358 100644 --- a/mysql-test/r/mysqldump-max.result +++ b/mysql-test/r/mysqldump-max.result @@ -334,10 +334,10 @@ DROP TABLE t1; DROP TABLE t2; SHOW BINLOG EVENTS LIMIT 6,3; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 658 Query 1 726 BEGIN -master-bin.000001 726 Query 1 823 use `test`; INSERT INTO t2 VALUES (1,0), (2,0) -master-bin.000001 823 Xid 1 850 COMMIT /* XID */ --- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=850; +master-bin.000001 663 Query 1 731 BEGIN +master-bin.000001 731 Query 1 828 use `test`; INSERT INTO t2 VALUES (1,0), (2,0) +master-bin.000001 828 Xid 1 855 COMMIT /* XID */ +-- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=855; SELECT * FROM t1 ORDER BY a; a 1 diff --git a/mysql-test/suite/binlog/r/binlog_checksum.result b/mysql-test/suite/binlog/r/binlog_checksum.result new file mode 100644 index 00000000000..44024456720 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_checksum.result @@ -0,0 +1,23 @@ +set @save_binlog_checksum = @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 1; +reset master; +must be master-bin.000001 +show binary logs; +Log_name File_size +master-bin.000001 # +create table t1 (a int); +flush logs; +drop table t1; +show binlog events from <binlog_start>; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; create table t1 (a int) +master-bin.000001 # Rotate # # master-bin.000002;pos=4 +show tables; +Tables_in_test +t1 +drop table t1; +set @@global.binlog_checksum = @save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; +End of the tests diff --git a/mysql-test/suite/binlog/r/binlog_killed.result b/mysql-test/suite/binlog/r/binlog_killed.result index 72fda535b6f..c71640a31e0 100644 --- a/mysql-test/suite/binlog/r/binlog_killed.result +++ b/mysql-test/suite/binlog/r/binlog_killed.result @@ -6,6 +6,11 @@ get_lock("a", 20) 1 reset master; insert into t2 values (null, null), (null, get_lock("a", 10)); +kill query ID; +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog")) +is not null; +set @result= 2 - 1 - 1; select @result /* must be zero either way */; @result 0 @@ -84,18 +89,19 @@ a b select @b /* must be 1 at the end of a stmt calling bug27563() */; @b 1 -must have the update query event more to FD +must have the update query event on the 3th line show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # User var # # @`b`=0 master-bin.000001 # Query # # use `test`; update t4 set b=b + bug27563(b) +*** a proof the query is binlogged with an error *** select (@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null; (@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null 1 -select 0 /* must return 0 to mean the killed query is in */; +select 0 /* must return 0 to mean the killed update is in */; 0 0 select RELEASE_LOCK("a"); @@ -120,7 +126,7 @@ count(*) select @b /* must be 1 at the end of a stmt calling bug27563() */; @b 1 -must have the delete query event more to FD +must have the delete query event on the 3th line show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # User var # # @`b`=0 @@ -131,7 +137,7 @@ is not null; (@a:=load_file("MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null 1 -select 0 /* must return 0 to mean the killed query is in */; +select 0 /* must return 0 to mean the killed delete is in */; 0 0 select RELEASE_LOCK("a"); diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index 1678f8add58..5401e6de24e 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -260,10 +260,18 @@ master-bin.000001 # Query # # use `test`; drop table t1 set @bcs = @@binlog_cache_size; set global binlog_cache_size=4096; reset master; -create table t1 (a int) engine=innodb; +create table t1 (a int, b char(255)) engine=innodb; +flush status; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 0 +*** the following must show the counter value = 1 *** +Variable_name Value +Binlog_cache_use 1 show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; create table t1 (a int) engine=innodb +master-bin.000001 # Query # # use `test`; create table t1 (a int, b char(255)) engine=innodb +master-bin.000001 # Query # # use `test`; flush status master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F @@ -465,606 +473,6 @@ master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Rotate # # master-bin.000002;pos=4 drop table t1; diff --git a/mysql-test/suite/binlog/r/binlog_stm_binlog.result b/mysql-test/suite/binlog/r/binlog_stm_binlog.result index 92531d9fb54..020f2d068fb 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_stm_binlog.result @@ -168,411 +168,119 @@ master-bin.000001 # Query # # use `test`; drop table t1 set @bcs = @@binlog_cache_size; set global binlog_cache_size=4096; reset master; -create table t1 (a int) engine=innodb; +create table t1 (a int, b char(255)) engine=innodb; +flush status; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 0 +*** the following must show the counter value = 1 *** +Variable_name Value +Binlog_cache_use 1 show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; create table t1 (a int) engine=innodb +master-bin.000001 # Query # # use `test`; create table t1 (a int, b char(255)) engine=innodb +master-bin.000001 # Query # # use `test`; flush status master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; insert into t1 values( 400 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 399 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 398 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 397 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 396 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 395 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 394 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 393 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 392 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 391 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 390 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 389 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 388 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 387 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 386 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 385 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 384 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 383 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 382 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 381 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 380 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 379 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 378 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 377 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 376 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 375 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 374 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 373 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 372 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 371 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 370 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 369 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 368 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 367 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 366 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 365 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 364 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 363 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 362 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 361 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 360 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 359 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 358 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 357 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 356 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 355 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 354 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 353 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 352 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 351 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 350 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 349 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 348 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 347 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 346 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 345 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 344 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 343 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 342 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 341 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 340 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 339 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 338 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 337 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 336 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 335 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 334 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 333 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 332 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 331 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 330 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 329 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 328 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 327 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 326 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 325 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 324 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 323 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 322 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 321 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 320 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 319 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 318 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 317 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 316 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 315 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 314 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 313 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 312 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 311 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 310 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 309 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 308 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 307 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 306 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 305 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 304 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 303 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 302 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 301 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 300 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 299 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 298 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 297 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 296 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 295 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 294 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 293 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 292 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 291 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 290 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 289 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 288 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 287 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 286 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 285 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 284 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 283 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 282 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 281 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 280 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 279 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 278 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 277 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 276 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 275 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 274 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 273 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 272 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 271 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 270 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 269 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 268 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 267 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 266 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 265 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 264 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 263 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 262 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 261 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 260 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 259 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 258 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 257 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 256 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 255 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 254 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 253 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 252 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 251 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 250 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 249 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 248 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 247 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 246 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 245 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 244 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 243 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 242 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 241 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( <binlog_start> ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 239 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 238 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 237 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 236 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 235 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 234 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 233 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 232 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 231 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 230 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 229 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 228 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 227 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 226 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 225 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 224 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 223 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 222 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 221 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 220 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 219 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 218 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 217 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 216 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 215 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 214 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 213 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 212 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 211 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 210 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 209 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 208 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 207 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 206 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 205 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 204 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 203 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 202 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 201 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 200 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 199 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 198 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 197 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 196 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 195 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 194 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 193 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 192 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 191 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 190 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 189 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 188 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 187 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 186 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 185 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 184 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 183 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 182 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 181 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 180 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 179 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 178 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 177 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 176 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 175 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 174 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 173 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 172 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 171 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 170 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 169 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 168 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 167 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 166 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 165 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 164 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 163 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 162 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 161 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 160 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 159 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 158 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 157 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 156 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 155 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 154 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 153 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 152 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 151 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 150 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 149 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 148 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 147 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 146 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 145 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 144 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 143 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 142 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 141 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 140 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 139 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 138 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 137 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 136 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 135 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 134 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 133 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 132 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 131 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 130 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 129 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 128 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 127 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 126 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 125 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 124 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 123 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 122 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 121 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 120 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 119 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 118 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 117 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 116 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 115 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 114 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 113 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 112 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 111 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 110 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 109 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 108 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 107 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 106 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 105 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 104 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 103 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 102 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 101 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 100 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 99 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 98 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 97 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 96 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 95 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 94 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 93 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 92 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 91 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 90 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 89 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 88 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 87 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 86 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 85 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 84 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 83 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 82 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 81 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 80 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 79 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 78 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 77 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 76 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 75 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 74 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 73 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 72 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 71 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 70 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 69 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 68 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 67 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 66 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 65 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 64 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 63 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 62 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 61 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 60 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 59 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 58 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 57 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 56 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 55 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 54 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 53 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 52 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 51 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 50 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 49 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 48 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 47 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 46 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 45 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 44 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 43 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 42 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 41 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 40 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 39 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 38 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 37 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 36 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 35 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 34 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 33 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 32 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 31 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 30 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 29 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 28 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 27 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 26 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 25 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 24 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 23 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 22 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 21 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 20 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 19 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 18 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 17 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 16 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 15 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 14 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 13 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 12 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 11 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 10 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 9 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 8 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 7 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 6 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 5 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 4 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 3 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 2 ) -master-bin.000001 # Query # # use `test`; insert into t1 values( 1 ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 100, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 99, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 98, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 97, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 96, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 95, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 94, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 93, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 92, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 91, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 90, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 89, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 88, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 87, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 86, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 85, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 84, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 83, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 82, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 81, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 80, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 79, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 78, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 77, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 76, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 75, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 74, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 73, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 72, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 71, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 70, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 69, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 68, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 67, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 66, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 65, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 64, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 63, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 62, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 61, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 60, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 59, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 58, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 57, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 56, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 55, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 54, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 53, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 52, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 51, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 50, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 49, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 48, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 47, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 46, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 45, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 44, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 43, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 42, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 41, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 40, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 39, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 38, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 37, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 36, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 35, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 34, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 33, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 32, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 31, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 30, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 29, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 28, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 27, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 26, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 25, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 24, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 23, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 22, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 21, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 20, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 19, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 18, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 17, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 16, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 15, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 14, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 13, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 12, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 11, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 10, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 9, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 8, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 7, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 6, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 5, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 4, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 3, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 2, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) +master-bin.000001 # Query # # use `test`; insert into t1 values( 1, 'just to fill void to make transaction occupying at least two buffers of the trans cache' ) master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Rotate # # master-bin.000002;pos=4 drop table t1; diff --git a/mysql-test/suite/binlog/t/binlog_checksum.test b/mysql-test/suite/binlog/t/binlog_checksum.test new file mode 100644 index 00000000000..7ecb9308f70 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_checksum.test @@ -0,0 +1,37 @@ +source include/have_innodb.inc; +source include/have_log_bin.inc; + +# +# WL#2540 replication event checksum +# +# Objectives of the test are: +# to demo binlog events with CRC32 checksum in them and +# to prove show binlog events and mysqlbinlog are capable to handle +# the checksum. +# + +set @save_binlog_checksum = @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 1; +let $MYSQLD_DATADIR= `select @@datadir`; + +reset master; +--echo must be master-bin.000001 +--source include/show_binary_logs.inc + +create table t1 (a int); +flush logs; +drop table t1; + +--source include/show_binlog_events.inc +--exec $MYSQL_BINLOG -c $MYSQLD_DATADIR/master-bin.000001 | $MYSQL +show tables; + +# clean-up + +drop table t1; +set @@global.binlog_checksum = @save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; + +--echo End of the tests diff --git a/mysql-test/suite/binlog/t/binlog_killed.test b/mysql-test/suite/binlog/t/binlog_killed.test index a2bd7d8095a..f0938d9f6b4 100644 --- a/mysql-test/suite/binlog/t/binlog_killed.test +++ b/mysql-test/suite/binlog/t/binlog_killed.test @@ -40,10 +40,15 @@ send insert into t2 values (null, null), (null, get_lock("a", 10)); connection con1; -disable_abort_on_error; -disable_query_log; -disable_result_log; +--disable_abort_on_error +--disable_warnings + +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where info like "%insert into t2 values%" and state like 'User lock'; +--source include/wait_condition.inc +--replace_regex /[0-9]+/ID/ eval kill query $ID; connection con2; @@ -52,20 +57,23 @@ reap; let $rows= `select count(*) from t2 /* must be 2 or 0 */`; let $MYSQLD_DATADIR= `select @@datadir`; -let $start_pos= `select @binlog_start_pos + 28`; ---exec $MYSQL_BINLOG --force-if-open --start-position=$start_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog + +--let $binlog_killed_pos=query_get_value(SHOW BINLOG EVENTS, Pos, 3) +--let $binlog_killed_end_log_pos=query_get_value(SHOW BINLOG EVENTS, End_log_pos, 3) +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--disable_result_log eval select (@a:=load_file("$MYSQLTEST_VARDIR/tmp/kill_query_calling_sp.binlog")) is not null; +--enable_result_log --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR let $error_code= `select @a like "%#%error_code=0%" /* must return 1 or 0*/`; let $insert_binlogged= `select @a like "%insert into%" /* must return 1 or 0 */`; -eval set @result= $rows- $error_code - $insert_binlogged; +eval set @result= $rows - $error_code - $insert_binlogged; -enable_abort_on_error; -enable_query_log; -enable_result_log; +--enable_warnings +--enable_abort_on_error select @result /* must be zero either way */; @@ -259,19 +267,21 @@ connection con2; reap; select * from t4 order by b /* must be (1,1), (1,2) */; select @b /* must be 1 at the end of a stmt calling bug27563() */; ---echo must have the update query event more to FD +--echo must have the update query event on the 3th line source include/show_binlog_events.inc; +--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 3) +--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 3) -# a proof the query is binlogged with an error +--echo *** a proof the query is binlogged with an error *** ---exec $MYSQL_BINLOG --force-if-open --start-position=106 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval select (@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null; --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; -eval select $error_code /* must return 0 to mean the killed query is in */; +eval select $error_code /* must return 0 to mean the killed update is in */; # cleanup for the sub-case connection con1; @@ -305,19 +315,21 @@ connection con2; reap; select count(*) from t4 /* must be 1 */; select @b /* must be 1 at the end of a stmt calling bug27563() */; ---echo must have the delete query event more to FD +--echo must have the delete query event on the 3th line source include/show_binlog_events.inc; +--let $binlog_killed_pos= query_get_value(SHOW BINLOG EVENTS, Pos, 3) +--let $binlog_killed_end_log_pos= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 3) # a proof the query is binlogged with an error ---exec $MYSQL_BINLOG --force-if-open --start-position=106 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog +--exec $MYSQL_BINLOG --force-if-open --start-position=$binlog_killed_pos --stop-position=$binlog_killed_end_log_pos $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval select (@a:=load_file("$MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog")) is not null; --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; -eval select $error_code /* must return 0 to mean the killed query is in */; +eval select $error_code /* must return 0 to mean the killed delete is in */; # cleanup for the sub-case connection con1; diff --git a/mysql-test/suite/innodb_plugin/r/binlog_consistent.result b/mysql-test/suite/innodb_plugin/r/binlog_consistent.result index 428b828d699..09cbbd98fac 100644 --- a/mysql-test/suite/innodb_plugin/r/binlog_consistent.result +++ b/mysql-test/suite/innodb_plugin/r/binlog_consistent.result @@ -3,11 +3,11 @@ RESET MASTER; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb; SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 375 +master-bin.000001 380 SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value binlog_snapshot_file master-bin.000001 -binlog_snapshot_position 375 +binlog_snapshot_position 380 BEGIN; INSERT INTO t1 VALUES (0, ""); # Connection con1 @@ -38,10 +38,10 @@ a b SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value binlog_snapshot_file master-bin.000001 -binlog_snapshot_position 674 +binlog_snapshot_position 679 SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 861 +master-bin.000001 866 SELECT * FROM t2 ORDER BY a; a 2 @@ -60,40 +60,40 @@ a b SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value binlog_snapshot_file master-bin.000001 -binlog_snapshot_position 674 +binlog_snapshot_position 679 SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000002 240 +master-bin.000002 245 COMMIT; SHOW STATUS LIKE 'binlog_snapshot_%'; Variable_name Value binlog_snapshot_file master-bin.000002 -binlog_snapshot_position 240 +binlog_snapshot_position 245 SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000002 240 +master-bin.000002 245 SHOW BINLOG EVENTS; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 4 Format_desc 1 240 Server ver: #, Binlog ver: # -master-bin.000001 240 Query 1 375 use `test`; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb -master-bin.000001 375 Query 1 487 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=myisam -master-bin.000001 487 Query 1 555 BEGIN -master-bin.000001 555 Query 1 647 use `test`; INSERT INTO t1 VALUES (0, "") -master-bin.000001 647 Xid 1 674 COMMIT /* XID */ -master-bin.000001 674 Query 1 742 BEGIN -master-bin.000001 742 Query 1 834 use `test`; INSERT INTO t1 VALUES (4, "") -master-bin.000001 834 Xid 1 861 COMMIT /* XID */ -master-bin.000001 861 Query 1 929 BEGIN -master-bin.000001 929 Query 1 1021 use `test`; INSERT INTO t1 VALUES (1, "") -master-bin.000001 1021 Xid 1 1048 COMMIT /* XID */ -master-bin.000001 1048 Query 1 1116 BEGIN -master-bin.000001 1116 Query 1 1213 use `test`; INSERT INTO t1 VALUES (2, "first") -master-bin.000001 1213 Query 1 1301 use `test`; INSERT INTO t2 VALUES (2) -master-bin.000001 1301 Query 1 1399 use `test`; INSERT INTO t1 VALUES (2, "second") -master-bin.000001 1399 Xid 1 1426 COMMIT /* XID */ -master-bin.000001 1426 Query 1 1494 BEGIN -master-bin.000001 1494 Query 1 1586 use `test`; INSERT INTO t1 VALUES (3, "") -master-bin.000001 1586 Query 1 1674 use `test`; INSERT INTO t2 VALUES (3) -master-bin.000001 1674 Xid 1 1701 COMMIT /* XID */ -master-bin.000001 1701 Rotate 1 1745 master-bin.000002;pos=4 +master-bin.000001 4 Format_desc 1 245 Server ver: #, Binlog ver: # +master-bin.000001 245 Query 1 380 use `test`; CREATE TABLE t1 (a INT, b VARCHAR(100), PRIMARY KEY (a,b)) ENGINE=innodb +master-bin.000001 380 Query 1 492 use `test`; CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=myisam +master-bin.000001 492 Query 1 560 BEGIN +master-bin.000001 560 Query 1 652 use `test`; INSERT INTO t1 VALUES (0, "") +master-bin.000001 652 Xid 1 679 COMMIT /* XID */ +master-bin.000001 679 Query 1 747 BEGIN +master-bin.000001 747 Query 1 839 use `test`; INSERT INTO t1 VALUES (4, "") +master-bin.000001 839 Xid 1 866 COMMIT /* XID */ +master-bin.000001 866 Query 1 934 BEGIN +master-bin.000001 934 Query 1 1026 use `test`; INSERT INTO t1 VALUES (1, "") +master-bin.000001 1026 Xid 1 1053 COMMIT /* XID */ +master-bin.000001 1053 Query 1 1121 BEGIN +master-bin.000001 1121 Query 1 1218 use `test`; INSERT INTO t1 VALUES (2, "first") +master-bin.000001 1218 Query 1 1306 use `test`; INSERT INTO t2 VALUES (2) +master-bin.000001 1306 Query 1 1404 use `test`; INSERT INTO t1 VALUES (2, "second") +master-bin.000001 1404 Xid 1 1431 COMMIT /* XID */ +master-bin.000001 1431 Query 1 1499 BEGIN +master-bin.000001 1499 Query 1 1591 use `test`; INSERT INTO t1 VALUES (3, "") +master-bin.000001 1591 Query 1 1679 use `test`; INSERT INTO t2 VALUES (3) +master-bin.000001 1679 Xid 1 1706 COMMIT /* XID */ +master-bin.000001 1706 Rotate 1 1750 master-bin.000002;pos=4 DROP TABLE t1,t2; diff --git a/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos.result b/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos.result index bfeb2474edb..79ade2acec7 100644 --- a/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos.result +++ b/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos.result @@ -30,6 +30,6 @@ a 1 2 3 -InnoDB: Last MySQL binlog file position 0 901, file name ./master-bin.000001 +InnoDB: Last MySQL binlog file position 0 906, file name ./master-bin.000001 SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos_no_optimize_thread.result b/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos_no_optimize_thread.result index a1c31cd411f..e6ea24a67bd 100644 --- a/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos_no_optimize_thread.result +++ b/mysql-test/suite/innodb_plugin/r/group_commit_binlog_pos_no_optimize_thread.result @@ -31,6 +31,6 @@ a 1 2 3 -InnoDB: Last MySQL binlog file position 0 901, file name ./master-bin.000001 +InnoDB: Last MySQL binlog file position 0 906, file name ./master-bin.000001 SET DEBUG_SYNC= 'RESET'; DROP TABLE t1; diff --git a/mysql-test/suite/rpl/extension/README.checksum b/mysql-test/suite/rpl/extension/README.checksum new file mode 100644 index 00000000000..1adcaff49ca --- /dev/null +++ b/mysql-test/suite/rpl/extension/README.checksum @@ -0,0 +1,23 @@ +Binlog checksum testing +======================= + +1. How it works. +The script copies a <suite> to directory <suite>_checksum, +collects test case names for t/ directory (except tests from +disabled def), randomly choose 90% of tests and add them +to disabled.def. +It means that mtr will run only 10% of random tests from each +suite. +At end the script run mtr: +./mysql-test-run.pl --suite=aaa_checksum,bbb_checksum \ + --mysqld=--binlog-checksum=CRC32 arg1 ... argN + +aaa,bbb - suite names from --suite option +arg1,argN - other command-line arguments of checksum.pl + +2. The options: + +--suite=suite1,suite2. Mandatory option. The list of suites for + binlog checksum testing. + +--percent=N, where N is 1..99. Percent of running tests. diff --git a/mysql-test/suite/rpl/extension/checksum.pl b/mysql-test/suite/rpl/extension/checksum.pl new file mode 100644 index 00000000000..60dca18c8f8 --- /dev/null +++ b/mysql-test/suite/rpl/extension/checksum.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl + +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +use File::Basename; +use File::Copy qw(copy); +use File::Spec qw(catdir); +use File::Path; +use IO::File; +use strict; + +# Constants and variables with default values +my $suites; +my $suffix = "_checksum"; +my $percent_random_test = 10; +my $mtr_script; +my @mtr_argv; +my @mtr_suites; + +# Check some arguments +foreach my $arg ( @ARGV ) +{ + if ($arg =~ m/\-\-suite\=(.+)/i) + { + $suites = $1; + } + elsif ($arg =~ m/\-\-percent\=(\d{1,2})/i) + { + $percent_random_test= $1; + } + else + { + push(@mtr_argv, $arg); + } + +} +if (! defined( $suites ) ) +{ + die("The script requires --suite argument"); +} + +print "#################################################################\n"; +print "# Binlog checksum testing\n"; +print "# Run randomly $percent_random_test\% of tests from following suites: $suites\n"; +print "#################################################################\n"; + +# Set extension directory +my $ext_dir= dirname(File::Spec->rel2abs($0)); +# Set mysql-test directory +my $mysql_test_dir= $ext_dir; +$mysql_test_dir =~ s/(\/|\\)suite(\/|\\)rpl(\/|\\)extension$//; + +# Main loop +foreach my $src_suite (split(",", $suites)) +{ + $src_suite=~ s/ //g; + my $dest_suite= $src_suite . $suffix; + push( @mtr_suites, $dest_suite); + print "Creating suite $dest_suite\n"; + # *** Set platform-independent pathes *** + # Set source directory of suite + my $src_suite_dir = File::Spec->catdir($mysql_test_dir, "suite", $src_suite); + # Set destination directory of suite + my $dest_suite_dir = File::Spec->catdir($mysql_test_dir, "suite", $dest_suite); + print "Copying files\n\tfrom '$src_suite_dir'\n\tto '$dest_suite_dir'\n"; + dircopy($src_suite_dir, $dest_suite_dir); + my $test_case_dir= File::Spec->catdir($dest_suite_dir, "t"); + # Read disabled.def + my %disabled = (); + print "Read disabled.def\n"; + my $fh = new IO::File File::Spec->catdir($test_case_dir, "disabled.def"), "r"; + if ( defined $fh ) + { + my @lines = <$fh>; + undef $fh; + foreach my $line ( @lines ) + { + if ($line =~ m/^([a-zA-Z0-9_]+).+\:.+/i) + { + $disabled{$1}= 1; + } + } + } + # Read test case list + my %tests = (); + print "Generate test case list\n"; + opendir my ($dh), $test_case_dir or die "Could not open dir '$test_case_dir': $!"; + for my $entry (readdir $dh) + { + if ( $entry =~ m/^([a-zA-Z0-9_]+)\.test$/i ) + { + my $test= $1; + if ( ! defined( $disabled{$test}) ) + { + $tests{$test}= 1; + } + } + } + closedir($dh); + # + my @excluded = (); + my $excluded_test= int((((100 - $percent_random_test)/100) * scalar( keys %tests ))); + while ( $excluded_test > 0 ) + { + my @cases = keys %tests; + my $test = $cases[int(rand(scalar(@cases)))]; + push ( @excluded, $test . "\t\t: Excluded for $dest_suite\n" ); + delete $tests{$test}; + $excluded_test--; + } + my $fh = new IO::File File::Spec->catdir($test_case_dir, "disabled.def"), O_WRONLY|O_APPEND; + if (defined $fh) { + print $fh join ("", sort @excluded); + undef $fh; + } + print "\t" . join("\n\t", sort keys %tests) . "\n"; + +} + +# Set path to mtr with arguments +my $mtr_script = "perl " . File::Spec->catdir($mysql_test_dir, "mysql-test-run.pl") . + " --suite=" . join(",", @mtr_suites) . " " . + " --mysqld=--binlog-checksum=CRC32 " . + join (" ", @mtr_argv); + +print "Run $mtr_script\n"; +system( $mtr_script ); + +sub dircopy +{ + my ($from_dir, $to_dir)= @_; + mkdir $to_dir if (! -e $to_dir); + opendir my($dh), $from_dir or die "Could not open dir '$from_dir': $!"; + for my $entry (readdir $dh) + { + next if $entry =~ /^(\.|\.\.)$/; + my $source = File::Spec->catdir($from_dir, $entry); + my $destination = File::Spec->catdir($to_dir, $entry); + if (-d $source) + { + mkdir $destination or die "mkdir '$destination' failed: $!" if not -e $destination; + dircopy($source, $destination); + } + else + { + copy($source, $destination) or die "copy '$source' to '$destination' failed: $!"; + } + } + closedir $dh; + return; +} diff --git a/mysql-test/suite/rpl/r/rpl_change_master.result b/mysql-test/suite/rpl/r/rpl_change_master.result index 6674ab168ef..1b1f040b726 100644 --- a/mysql-test/suite/rpl/r/rpl_change_master.result +++ b/mysql-test/suite/rpl/r/rpl_change_master.result @@ -1,5 +1,6 @@ include/master-slave.inc [connection master] +call mtr.add_suppression("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum"); create table t1(n int); select * from t1; n diff --git a/mysql-test/suite/rpl/r/rpl_checksum.result b/mysql-test/suite/rpl/r/rpl_checksum.result new file mode 100644 index 00000000000..c28a863f024 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_checksum.result @@ -0,0 +1,126 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression('Slave can not handle replication events with the checksum that master is configured to log'); +call mtr.add_suppression('Replication event checksum verification failed'); +call mtr.add_suppression('Relay log write failure: could not queue event from master'); +call mtr.add_suppression('Master is configured to log replication events with checksum, but will not send such events to slaves that cannot process them'); +set @master_save_binlog_checksum= @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +select @@global.binlog_checksum as 'must be CRC32 because of the command line option'; +must be CRC32 because of the command line option +CRC32 +select @@session.binlog_checksum as 'no session var'; +ERROR HY000: Variable 'binlog_checksum' is a GLOBAL variable +select @@global.master_verify_checksum as 'must be zero because of default'; +must be zero because of default +0 +select @@session.master_verify_checksum as 'no session var'; +ERROR HY000: Variable 'master_verify_checksum' is a GLOBAL variable +set @slave_save_binlog_checksum= @@global.binlog_checksum; +set @save_slave_sql_verify_checksum = @@global.slave_sql_verify_checksum; +select @@global.slave_sql_verify_checksum as 'must be one because of default'; +must be one because of default +1 +select @@session.slave_sql_verify_checksum as 'no session var'; +ERROR HY000: Variable 'slave_sql_verify_checksum' is a GLOBAL variable +show binary logs; +Log_name File_size +master-bin.000001 # +set @@global.binlog_checksum = NONE; +*** must be rotations seen *** +show binary logs; +Log_name File_size +master-bin.000001 # +master-bin.000002 # +set @@global.binlog_checksum = default; +set @@global.binlog_checksum = CRC32; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; +set @@global.binlog_checksum = ADLER32; +ERROR 42000: Variable 'checksum' can't be set to the value of 'ADLER32' +set @@global.master_verify_checksum = 2; +ERROR 42000: Variable 'master_verify_checksum' can't be set to the value of '2' +set @@global.slave_sql_verify_checksum = 0; +set @@global.slave_sql_verify_checksum = default; +set @@global.slave_sql_verify_checksum = 2; +ERROR 42000: Variable 'slave_sql_verify_checksum' can't be set to the value of '2' +set @@global.binlog_checksum = NONE; +create table t1 (a int); +flush logs; +flush logs; +flush logs; +flush logs; +flush logs; +flush logs; +select count(*) as zero from t1; +zero +0 +include/stop_slave.inc +set @@global.binlog_checksum = CRC32; +insert into t1 values (1) /* will not be applied on slave due to simulation */; +set @@global.debug='d,simulate_slave_unaware_checksum'; +start slave; +include/wait_for_slave_io_to_stop.inc +*** Got IO thread error code: 1236, text: Got fatal error 1236 from master when reading data from binary log: 'Slave can not handle replication events with the checksum that master is configured to log' *** +select count(*) as zero from t1; +zero +0 +set @@global.debug=''; +include/start_slave.inc +set @@global.master_verify_checksum = 1; +set @@session.debug='d,simulate_checksum_test_failure'; +show binlog events; +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +set @@session.debug=''; +set @@global.master_verify_checksum = default; +include/stop_slave.inc +create table t2 (a int); +set @@global.debug='d,simulate_checksum_test_failure'; +start slave io_thread; +include/wait_for_slave_io_to_stop.inc +*** Got IO thread error code: 1595, text: Relay log write failure: could not queue event from master *** +set @@global.debug=''; +start slave io_thread; +include/wait_for_slave_param.inc [Read_Master_Log_Pos] +set @@global.slave_sql_verify_checksum = 1; +set @@global.debug='d,simulate_checksum_test_failure'; +start slave sql_thread; +include/wait_for_slave_sql_to_stop.inc +*** Got SQL thread error code: 1593, text: Error initializing relay log position: I/O error reading event at position 4 *** +set @@global.debug=''; +include/start_slave.inc +select count(*) as 'must be zero' from t2; +must be zero +0 +stop slave; +reset slave; +set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE"); +flush logs; +set @@global.binlog_checksum= CRC32; +reset master; +flush logs; +create table t3 (a int, b char(5)); +include/start_slave.inc +select count(*) as 'must be zero' from t3; +must be zero +0 +include/stop_slave.inc +change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; +flush logs; +reset master; +insert into t3 value (1, @@global.binlog_checksum); +include/start_slave.inc +flush logs; +select count(*) as 'must be one' from t3; +must be one +1 +set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE"); +insert into t3 value (1, @@global.binlog_checksum); +drop table t1, t2, t3; +set @@global.binlog_checksum = @master_save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; +set @@global.binlog_checksum = @slave_save_binlog_checksum; +set @@global.slave_sql_verify_checksum = @save_slave_sql_verify_checksum; +End of tests +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_checksum_cache.result b/mysql-test/suite/rpl/r/rpl_checksum_cache.result new file mode 100644 index 00000000000..9508e94e7f2 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_checksum_cache.result @@ -0,0 +1,119 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement: insert into t2 set data=repeat.*'a', @act_size.*"); +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement: insert into t1 values.* NAME_CONST.*'n',.*, @data .*"); +set @save_binlog_cache_size = @@global.binlog_cache_size; +set @save_binlog_checksum = @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.binlog_cache_size = 4096; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 1; +include/stop_slave.inc +include/start_slave.inc +flush status; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 0 +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 0 +drop table if exists t1; +create table t1 (a int PRIMARY KEY, b CHAR(32)) engine=innodb; +create procedure test.p_init (n int, size int) +begin +while n > 0 do +select round(RAND() * size) into @act_size; +set @data = repeat('a', @act_size); +insert into t1 values(n, @data ); +set n= n-1; +end while; +end| +begin; +call test.p_init(4000, 32); +commit; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 1 +*** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +include/diff_tables.inc [master:test.t1, slave:test.t1] +begin; +delete from t1; +commit; +flush status; +create table t2(a int auto_increment primary key, data VARCHAR(12288)) ENGINE=Innodb; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 1 +*** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +include/diff_tables.inc [master:test.t2, slave:test.t2] +begin; +delete from t2; +commit; +flush status; +create table t3(a int auto_increment primary key, data VARCHAR(8192)) engine=innodb; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 1 +*** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +include/diff_tables.inc [master:test.t3, slave:test.t3] +begin; +delete from t3; +commit; +flush status; +create procedure test.p1 (n int) +begin +while n > 0 do +case (select (round(rand()*100) % 3) + 1) +when 1 then +select round(RAND() * 32) into @act_size; +set @data = repeat('a', @act_size); +insert into t1 values(n, @data); +when 2 then +begin +select round(8192 + RAND() * 4096) into @act_size; +insert into t2 set data=repeat('a', @act_size); +end; +when 3 then +begin +select round(3686.4000 + RAND() * 819.2000) into @act_size; +insert into t3 set data= repeat('a', @act_size); +end; +end case; +set n= n-1; +end while; +end| +set autocommit= 0; +begin; +call test.p1(1000); +commit; +show status like "binlog_cache_use"; +Variable_name Value +Binlog_cache_use 1 +*** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; +Variable_name Value +Binlog_cache_disk_use 1 +include/diff_tables.inc [master:test.t1, slave:test.t1] +include/diff_tables.inc [master:test.t2, slave:test.t2] +include/diff_tables.inc [master:test.t3, slave:test.t3] +begin; +delete from t1; +delete from t2; +delete from t3; +commit; +drop table t1, t2, t3; +set @@global.binlog_cache_size = @save_binlog_cache_size; +set @@global.binlog_checksum = @save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; +drop procedure test.p_init; +drop procedure test.p1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_corruption.result b/mysql-test/suite/rpl/r/rpl_corruption.result new file mode 100644 index 00000000000..b42b7161c30 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_corruption.result @@ -0,0 +1,49 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression('Found invalid event in binary log'); +call mtr.add_suppression('Slave I/O: Relay log write failure: could not queue event from master'); +call mtr.add_suppression('event read from binlog did not pass crc check'); +call mtr.add_suppression('Replication event checksum verification failed'); +SET @old_master_verify_checksum = @@master_verify_checksum; +# 1. Creating test table/data and set corruption position for testing +* insert/update/delete rows in table t1 * +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c VARCHAR(100)); +include/stop_slave.inc +# 2. Corruption in master binlog and SHOW BINLOG EVENTS +SET GLOBAL debug="+d,corrupt_read_log_event_char"; +SHOW BINLOG EVENTS; +ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Wrong offset or I/O error +SET GLOBAL debug="-d,corrupt_read_log_event_char"; +# 3. Master read a corrupted event from binlog and send the error to slave +SET GLOBAL debug="+d,corrupt_read_log_event2"; +START SLAVE IO_THREAD; +include/wait_for_slave_io_error.inc [errno=1236] +SET GLOBAL debug="-d,corrupt_read_log_event2"; +# 4. Master read a corrupted event from binlog and send it to slave +SET GLOBAL master_verify_checksum=0; +SET GLOBAL debug="+d,corrupt_read_log_event2"; +START SLAVE IO_THREAD; +include/wait_for_slave_io_error.inc [errno=1595] +SET GLOBAL debug="-d,corrupt_read_log_event2"; +SET GLOBAL debug= ""; +SET GLOBAL master_verify_checksum=1; +# 5. Slave. Corruption in network +SET GLOBAL debug="+d,corrupt_queue_event"; +START SLAVE IO_THREAD; +include/wait_for_slave_io_error.inc [errno=1595] +SET GLOBAL debug="-d,corrupt_queue_event"; +# 6. Slave. Corruption in relay log +SET GLOBAL debug="+d,corrupt_read_log_event_char"; +START SLAVE; +include/wait_for_slave_sql_error.inc [errno=1593] +SET GLOBAL debug="-d,corrupt_read_log_event_char"; +SET GLOBAL debug= ""; +# 7. Seek diff for tables on master and slave +include/start_slave.inc +include/diff_tables.inc [master:test.t1, slave:test.t1] +# 8. Clean up +SET GLOBAL debug= ""; +SET GLOBAL master_verify_checksum = @old_master_verify_checksum; +DROP TABLE t1; +SET GLOBAL debug= ""; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_rotate_logs.result b/mysql-test/suite/rpl/r/rpl_rotate_logs.result index e41f56c0a71..08c9323d897 100644 --- a/mysql-test/suite/rpl/r/rpl_rotate_logs.result +++ b/mysql-test/suite/rpl/r/rpl_rotate_logs.result @@ -69,7 +69,7 @@ insert into temp_table values ("testing temporary tables part 2"); create table t3 (n int); select count(*) from t3 where n >= 4; count(*) -100 +90 create table t4 select * from temp_table; show binary logs; Log_name File_size @@ -88,7 +88,7 @@ include/check_slave_is_running.inc lock tables t3 read; select count(*) from t3 where n >= 4; count(*) -100 +90 unlock tables; drop table if exists t1,t2,t3,t4; End of 4.1 tests diff --git a/mysql-test/suite/rpl/r/rpl_row_conflicts.result b/mysql-test/suite/rpl/r/rpl_row_conflicts.result index 7ad0c06448e..025e2ee4a77 100644 --- a/mysql-test/suite/rpl/r/rpl_row_conflicts.result +++ b/mysql-test/suite/rpl/r/rpl_row_conflicts.result @@ -22,7 +22,7 @@ a [on slave] ---- Wait until slave stops with an error ---- include/wait_for_slave_sql_error.inc [errno=1062] -Last_SQL_Error = Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log master-bin.000001, end_log_pos 480 (expected "duplicate key" error) +Last_SQL_Error = Could not execute Write_rows event on table test.t1; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log master-bin.000001, end_log_pos 485 (expected "duplicate key" error) SELECT * FROM t1; a 1 diff --git a/mysql-test/suite/rpl/t/rpl_change_master.test b/mysql-test/suite/rpl/t/rpl_change_master.test index 65af5e72865..36db1de8d40 100644 --- a/mysql-test/suite/rpl/t/rpl_change_master.test +++ b/mysql-test/suite/rpl/t/rpl_change_master.test @@ -3,6 +3,7 @@ # I/O thread left (some old bug fixed in 4.0.17) source include/master-slave.inc; +call mtr.add_suppression("Slave I/O: The slave I/O thread stops because a fatal error is encountered when it tried to SET @master_binlog_checksum"); connection master; # Make SQL slave thread advance a bit diff --git a/mysql-test/suite/rpl/t/rpl_checksum-master.opt b/mysql-test/suite/rpl/t/rpl_checksum-master.opt new file mode 100644 index 00000000000..a6e99a9fd5a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum-master.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test new file mode 100644 index 00000000000..430a663cda2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum.test @@ -0,0 +1,247 @@ +# WL2540 replication events checksum +# Testing configuration parameters + +--source include/master-slave.inc +--source include/have_debug.inc +--source include/have_binlog_format_mixed.inc + +call mtr.add_suppression('Slave can not handle replication events with the checksum that master is configured to log'); +call mtr.add_suppression('Replication event checksum verification failed'); +# due to C failure simulation +call mtr.add_suppression('Relay log write failure: could not queue event from master'); +call mtr.add_suppression('Master is configured to log replication events with checksum, but will not send such events to slaves that cannot process them'); + +# A. read/write access to the global vars: +# binlog_checksum master_verify_checksum slave_sql_verify_checksum + +connection master; + +set @master_save_binlog_checksum= @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; + +select @@global.binlog_checksum as 'must be CRC32 because of the command line option'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.binlog_checksum as 'no session var'; + +select @@global.master_verify_checksum as 'must be zero because of default'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.master_verify_checksum as 'no session var'; + +connection slave; + +set @slave_save_binlog_checksum= @@global.binlog_checksum; +set @save_slave_sql_verify_checksum = @@global.slave_sql_verify_checksum; + +select @@global.slave_sql_verify_checksum as 'must be one because of default'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.slave_sql_verify_checksum as 'no session var'; + +connection master; + +source include/show_binary_logs.inc; +set @@global.binlog_checksum = NONE; +--echo *** must be rotations seen *** +source include/show_binary_logs.inc; + +set @@global.binlog_checksum = default; + +# testing lack of side-effects in non-effective update of binlog_checksum: +set @@global.binlog_checksum = CRC32; +set @@global.binlog_checksum = CRC32; + +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; + +--error ER_WRONG_VALUE_FOR_VAR +set @@global.binlog_checksum = ADLER32; +--error ER_WRONG_VALUE_FOR_VAR +set @@global.master_verify_checksum = 2; # the var is of bool type + +connection slave; + +set @@global.slave_sql_verify_checksum = 0; +set @@global.slave_sql_verify_checksum = default; +--error ER_WRONG_VALUE_FOR_VAR +set @@global.slave_sql_verify_checksum = 2; # the var is of bool type + +# +# B. Old Slave to New master conditions +# +# while master does not send a checksum-ed binlog the Old Slave can +# work with the New Master + +connection master; + +set @@global.binlog_checksum = NONE; +create table t1 (a int); + +# testing that binlog rotation preserves opt_binlog_checksum value +flush logs; +flush logs; +flush logs; + +sync_slave_with_master; +#connection slave; +# checking that rotation on the slave side leaves slave stable +flush logs; +flush logs; +flush logs; +select count(*) as zero from t1; + +source include/stop_slave.inc; + +connection master; +set @@global.binlog_checksum = CRC32; +insert into t1 values (1) /* will not be applied on slave due to simulation */; + +# instruction to the dump thread +### set @@global.debug='d,simulate_slave_unaware_checksum'; # merge todo: +/- d syntax fails in my clone + +connection slave; +set @@global.debug='d,simulate_slave_unaware_checksum'; # merge todo: +/- d syntax fails in my clone +start slave; +source include/wait_for_slave_io_to_stop.inc; + +let $errno= query_get_value(SHOW SLAVE STATUS, Last_IO_Errno, 1); +let $error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); +--echo *** Got IO thread error code: $errno, text: $error *** + +select count(*) as zero from t1; + +###connection master; +set @@global.debug=''; # merge todo: +/- d syntax fails in my clone + +connection slave; +source include/start_slave.inc; + +# +# C. checksum failure simulations +# + +# C1. Failure by a client thread +connection master; +set @@global.master_verify_checksum = 1; +set @@session.debug='d,simulate_checksum_test_failure'; # merge todo deploy +/- syntax +--error ER_ERROR_WHEN_EXECUTING_COMMAND +show binlog events; +set @@session.debug=''; # merge todo: +/- d syntax fails in my clone +set @@global.master_verify_checksum = default; + +#connection master; +sync_slave_with_master; + +connection slave; +source include/stop_slave.inc; + +connection master; +create table t2 (a int); +let $pos_master= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; + +# C2. Failure by IO thread +# instruction to io thread +set @@global.debug='d,simulate_checksum_test_failure'; # merge todo deploy +/- syntax +start slave io_thread; +source include/wait_for_slave_io_to_stop.inc; +let $errno= query_get_value(SHOW SLAVE STATUS, Last_IO_Errno, 1); +let $error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); +--echo *** Got IO thread error code: $errno, text: $error *** +set @@global.debug=''; # todo: merge + +# to make IO thread re-read it again w/o the failure +start slave io_thread; +let $slave_param= Read_Master_Log_Pos; +let $slave_param_value= $pos_master; +source include/wait_for_slave_param.inc; + +# C3. Failure by SQL thread +# instruction to sql thread; +set @@global.slave_sql_verify_checksum = 1; + +set @@global.debug='d,simulate_checksum_test_failure'; # merge todo deploy +/- syntax + +start slave sql_thread; +source include/wait_for_slave_sql_to_stop.inc; +let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +--echo *** Got SQL thread error code: $errno, text: $error *** + +# resuming SQL thread to parse out the event w/o the failure + +set @@global.debug=''; +source include/start_slave.inc; + +connection master; +sync_slave_with_master; + +#connection slave; +select count(*) as 'must be zero' from t2; + +# +# D. Reset slave, Change-Master, Binlog & Relay-log rotations with +# random value on binlog_checksum on both master and slave +# +connection slave; +stop slave; +reset slave; + +# randomize slave server's own checksum policy +set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE"); +flush logs; + +connection master; +set @@global.binlog_checksum= CRC32; +reset master; +flush logs; +create table t3 (a int, b char(5)); + +connection slave; +source include/start_slave.inc; + +connection master; +sync_slave_with_master; + +#connection slave; +select count(*) as 'must be zero' from t3; +source include/stop_slave.inc; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; + +connection master; +flush logs; +reset master; +insert into t3 value (1, @@global.binlog_checksum); + +connection slave; +source include/start_slave.inc; +flush logs; + +connection master; +sync_slave_with_master; + +#connection slave; +select count(*) as 'must be one' from t3; + +connection master; +set @@global.binlog_checksum= IF(floor((rand()*1000)%2), "CRC32", "NONE"); +insert into t3 value (1, @@global.binlog_checksum); +sync_slave_with_master; + +#connection slave; + +#clean-up + +connection master; +drop table t1, t2, t3; +set @@global.binlog_checksum = @master_save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; + +#connection slave; +sync_slave_with_master; +set @@global.binlog_checksum = @slave_save_binlog_checksum; +set @@global.slave_sql_verify_checksum = @save_slave_sql_verify_checksum; + +--echo End of tests + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_checksum_cache.test b/mysql-test/suite/rpl/t/rpl_checksum_cache.test new file mode 100644 index 00000000000..5667d599aff --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_checksum_cache.test @@ -0,0 +1,255 @@ +-- source include/have_innodb.inc +-- source include/master-slave.inc + +--disable_warnings +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement: insert into t2 set data=repeat.*'a', @act_size.*"); +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement: insert into t1 values.* NAME_CONST.*'n',.*, @data .*"); +--enable_warnings + +connection master; +set @save_binlog_cache_size = @@global.binlog_cache_size; +set @save_binlog_checksum = @@global.binlog_checksum; +set @save_master_verify_checksum = @@global.master_verify_checksum; +set @@global.binlog_cache_size = 4096; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 1; + +# restart slave to force the dump thread to verify events (on master side) +connection slave; +source include/stop_slave.inc; +source include/start_slave.inc; + +connection master; + +# +# Testing a critical part of checksum handling dealing with transaction cache. +# The cache's buffer size is set to be less than the transaction's footprint +# in binlog. +# +# To verify combined buffer-by-buffer read out of the file and fixing crc per event +# there are the following parts: +# +# 1. the event size is much less than the cache's buffer +# 2. the event size is bigger than the cache's buffer +# 3. the event size if approximately the same as the cache's buffer +# 4. all in above + +# +# 1. the event size is much less than the cache's buffer +# + +flush status; +show status like "binlog_cache_use"; +show status like "binlog_cache_disk_use"; +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# parameter to ensure the test slightly varies binlog content +# between different invocations +# +let $deviation_size=32; +eval create table t1 (a int PRIMARY KEY, b CHAR($deviation_size)) engine=innodb; + +# Now we are going to create transaction which is long enough so its +# transaction binlog will be flushed to disk... + +delimiter |; +create procedure test.p_init (n int, size int) +begin + while n > 0 do + select round(RAND() * size) into @act_size; + set @data = repeat('a', @act_size); + insert into t1 values(n, @data ); + set n= n-1; + end while; +end| + +delimiter ;| + +let $1 = 4000; # PB2 can run it slow to time out on following sync_slave_with_master:s + +begin; +--disable_warnings +# todo: check if it is really so. +#+Note 1592 Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: Statement uses a system function whose value may differ on slave. +eval call test.p_init($1, $deviation_size); +--enable_warnings +commit; + +show status like "binlog_cache_use"; +--echo *** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; + +sync_slave_with_master; + +let $diff_tables=master:test.t1, slave:test.t1; +source include/diff_tables.inc; + +# undoing changes with verifying the above once again +connection master; + +begin; +delete from t1; +commit; + +sync_slave_with_master; + + +# +# 2. the event size is bigger than the cache's buffer +# +connection master; + +flush status; +let $t2_data_size= `select 3 * @@global.binlog_cache_size`; +let $t2_aver_size= `select 2 * @@global.binlog_cache_size`; +let $t2_max_rand= `select 1 * @@global.binlog_cache_size`; + +eval create table t2(a int auto_increment primary key, data VARCHAR($t2_data_size)) ENGINE=Innodb; +let $1=100; +--disable_query_log +begin; +while ($1) +{ + eval select round($t2_aver_size + RAND() * $t2_max_rand) into @act_size; + set @data = repeat('a', @act_size); + insert into t2 set data = @data; + dec $1; +} +commit; +--enable_query_log +show status like "binlog_cache_use"; +--echo *** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; + +sync_slave_with_master; + +let $diff_tables=master:test.t2, slave:test.t2; +source include/diff_tables.inc; + +# undoing changes with verifying the above once again +connection master; + +begin; +delete from t2; +commit; + +sync_slave_with_master; + +# +# 3. the event size if approximately the same as the cache's buffer +# + +connection master; + +flush status; +let $t3_data_size= `select 2 * @@global.binlog_cache_size`; +let $t3_aver_size= `select (9 * @@global.binlog_cache_size) / 10`; +let $t3_max_rand= `select (2 * @@global.binlog_cache_size) / 10`; + +eval create table t3(a int auto_increment primary key, data VARCHAR($t3_data_size)) engine=innodb; + +let $1= 300; +--disable_query_log +begin; +while ($1) +{ + eval select round($t3_aver_size + RAND() * $t3_max_rand) into @act_size; + insert into t3 set data= repeat('a', @act_size); + dec $1; +} +commit; +--enable_query_log +show status like "binlog_cache_use"; +--echo *** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; + +sync_slave_with_master; + +let $diff_tables=master:test.t3, slave:test.t3; +source include/diff_tables.inc; + +# undoing changes with verifying the above once again +connection master; + +begin; +delete from t3; +commit; + +sync_slave_with_master; + + +# +# 4. all in above +# + +connection master; +flush status; + +delimiter |; +eval create procedure test.p1 (n int) +begin + while n > 0 do + case (select (round(rand()*100) % 3) + 1) + when 1 then + select round(RAND() * $deviation_size) into @act_size; + set @data = repeat('a', @act_size); + insert into t1 values(n, @data); + when 2 then + begin + select round($t2_aver_size + RAND() * $t2_max_rand) into @act_size; + insert into t2 set data=repeat('a', @act_size); + end; + when 3 then + begin + select round($t3_aver_size + RAND() * $t3_max_rand) into @act_size; + insert into t3 set data= repeat('a', @act_size); + end; + end case; + set n= n-1; + end while; +end| +delimiter ;| + +let $1= 1000; +set autocommit= 0; +begin; +--disable_warnings +eval call test.p1($1); +--enable_warnings +commit; + +show status like "binlog_cache_use"; +--echo *** binlog_cache_disk_use must be non-zero *** +show status like "binlog_cache_disk_use"; + +sync_slave_with_master; + +let $diff_tables=master:test.t1, slave:test.t1; +source include/diff_tables.inc; + +let $diff_tables=master:test.t2, slave:test.t2; +source include/diff_tables.inc; + +let $diff_tables=master:test.t3, slave:test.t3; +source include/diff_tables.inc; + + +connection master; + +begin; +delete from t1; +delete from t2; +delete from t3; +commit; + +drop table t1, t2, t3; +set @@global.binlog_cache_size = @save_binlog_cache_size; +set @@global.binlog_checksum = @save_binlog_checksum; +set @@global.master_verify_checksum = @save_master_verify_checksum; +drop procedure test.p_init; +drop procedure test.p1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_corruption-master.opt b/mysql-test/suite/rpl/t/rpl_corruption-master.opt new file mode 100644 index 00000000000..2612c17aa67 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption-master.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 --master-verify-checksum=1 diff --git a/mysql-test/suite/rpl/t/rpl_corruption-slave.opt b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt new file mode 100644 index 00000000000..b32a52403c2 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption-slave.opt @@ -0,0 +1 @@ +--binlog-checksum=CRC32 --slave-sql-verify-checksum=1 diff --git a/mysql-test/suite/rpl/t/rpl_corruption.test b/mysql-test/suite/rpl/t/rpl_corruption.test new file mode 100644 index 00000000000..aeeae199c02 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_corruption.test @@ -0,0 +1,131 @@ +############################################################ +# Author: Serge Kozlov <serge.kozlov@oracle.com> +# Date: 17 Oct 2010 +# Purpose: WL#5064 Testing with corrupted events. +# The test emulates the corruption at the vary stages +# of replication: +# - in binlog file +# - in network +# - in relay log +############################################################ + +--source include/have_debug.inc +--source include/master-slave.inc + +# Block legal errors for MTR +call mtr.add_suppression('Found invalid event in binary log'); +call mtr.add_suppression('Slave I/O: Relay log write failure: could not queue event from master'); +call mtr.add_suppression('event read from binlog did not pass crc check'); +call mtr.add_suppression('Replication event checksum verification failed'); + +SET @old_master_verify_checksum = @@master_verify_checksum; + +# Creating test table/data and set corruption position for testing +--echo # 1. Creating test table/data and set corruption position for testing +--connection master +--echo * insert/update/delete rows in table t1 * +# Corruption algorithm modifies only the first event and +# then will be reset. To avoid checking always the first event +# from binlog (usually it is FD) we randomly execute different +# statements and set position for corruption inside events. + +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b VARCHAR(10), c VARCHAR(100)); +--disable_query_log +let $i=`SELECT 3+CEILING(10*RAND())`; +let $j=1; +let $pos=0; +while ($i) { + eval INSERT INTO t1 VALUES ($j, 'a', NULL); + if (`SELECT RAND() > 0.7`) + { + eval UPDATE t1 SET c = REPEAT('a', 20) WHERE a = $j; + } + if (`SELECT RAND() > 0.8`) + { + eval DELETE FROM t1 WHERE a = $j; + } + if (!$pos) { + let $pos= query_get_value(SHOW MASTER STATUS, Position, 1); + --sync_slave_with_master + --source include/stop_slave.inc + --disable_query_log + --connection master + } + dec $i; + inc $j; +} +--enable_query_log + +# Emulate corruption in binlog file when SHOW BINLOG EVENTS is executing +--echo # 2. Corruption in master binlog and SHOW BINLOG EVENTS +SET GLOBAL debug="+d,corrupt_read_log_event_char"; +--echo SHOW BINLOG EVENTS; +--disable_query_log +send_eval SHOW BINLOG EVENTS FROM $pos; +--enable_query_log +--error ER_ERROR_WHEN_EXECUTING_COMMAND +reap; +SET GLOBAL debug="-d,corrupt_read_log_event_char"; + +# Emulate corruption on master with crc checking on master +--echo # 3. Master read a corrupted event from binlog and send the error to slave +SET GLOBAL debug="+d,corrupt_read_log_event2"; +--connection slave +START SLAVE IO_THREAD; +let $slave_io_errno= 1236; +--source include/wait_for_slave_io_error.inc +--connection master +SET GLOBAL debug="-d,corrupt_read_log_event2"; + +# Emulate corruption on master without crc checking on master +--echo # 4. Master read a corrupted event from binlog and send it to slave +--connection master +SET GLOBAL master_verify_checksum=0; +SET GLOBAL debug="+d,corrupt_read_log_event2"; +--connection slave +START SLAVE IO_THREAD; +let $slave_io_errno= 1595; +--source include/wait_for_slave_io_error.inc +--connection master +SET GLOBAL debug="-d,corrupt_read_log_event2"; +SET GLOBAL debug= ""; +SET GLOBAL master_verify_checksum=1; + +# Emulate corruption in network +--echo # 5. Slave. Corruption in network +--connection slave +SET GLOBAL debug="+d,corrupt_queue_event"; +START SLAVE IO_THREAD; +let $slave_io_errno= 1595; +--source include/wait_for_slave_io_error.inc +SET GLOBAL debug="-d,corrupt_queue_event"; + +# Emulate corruption in relay log +--echo # 6. Slave. Corruption in relay log +SET GLOBAL debug="+d,corrupt_read_log_event_char"; +START SLAVE; +let $slave_sql_errno= 1593; +--source include/wait_for_slave_sql_error.inc +SET GLOBAL debug="-d,corrupt_read_log_event_char"; +SET GLOBAL debug= ""; + +# Start normal replication and compare same table on master +# and slave +--echo # 7. Seek diff for tables on master and slave +--connection slave +--source include/start_slave.inc +--connection master +--sync_slave_with_master +let $diff_tables= master:test.t1, slave:test.t1; +--source include/diff_tables.inc + +# Clean up +--echo # 8. Clean up +--connection master +SET GLOBAL debug= ""; +SET GLOBAL master_verify_checksum = @old_master_verify_checksum; +DROP TABLE t1; +--sync_slave_with_master +SET GLOBAL debug= ""; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test index a8c7c2c1f5b..035f8fa9fbf 100644 --- a/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test +++ b/mysql-test/suite/rpl/t/rpl_known_bugs_detection.test @@ -4,11 +4,14 @@ # imitate the bug, so it has to stop). source include/have_debug.inc; +# because of pretend_version_50034_in_binlog the test can't run with checksum +source include/have_binlog_checksum_off.inc; source include/master-slave.inc; # Currently only statement-based-specific bugs are here -- source include/have_binlog_format_mixed_or_statement.inc + # # This is to test that slave properly detects if # master may suffer from: diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.test b/mysql-test/suite/rpl/t/rpl_rotate_logs.test index 68a3a20b501..1413bf5a16b 100644 --- a/mysql-test/suite/rpl/t/rpl_rotate_logs.test +++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test @@ -142,7 +142,10 @@ select * from t2; connection master; create temporary table temp_table (a char(80) not null); insert into temp_table values ("testing temporary tables part 2"); -let $1=100; + +# the nummber of produced logs is sensitive to whether checksum is NONE or CRC32 +# the value of 90 makes it even +let $1=90; create table t3 (n int); disable_query_log; diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test index 15f98916485..fff457b2e55 100644 --- a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test +++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test @@ -12,7 +12,7 @@ create table t1(n int); sync_slave_with_master; stop slave; connection master; -let $1=5000; +let $1=2500; disable_query_log; while ($1) { diff --git a/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test b/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test index 65093319fbe..a245b054ebd 100644 --- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test +++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test @@ -37,8 +37,10 @@ stop slave; # get the master binlog pos from the epoch, from the _other_ "master", server2 connection server2; --replace_result $the_epoch <the_epoch> +--disable_result_log eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1) FROM mysql.ndb_binlog_index WHERE epoch = $the_epoch ; +--enable_result_log let $the_pos= `SELECT @the_pos` ; let $the_file= `SELECT @the_file` ; diff --git a/mysql-test/suite/sys_vars/r/binlog_checksum_basic.result b/mysql-test/suite/sys_vars/r/binlog_checksum_basic.result new file mode 100644 index 00000000000..2821a4a7e63 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/binlog_checksum_basic.result @@ -0,0 +1,14 @@ +set @save_binlog_checksum= @@global.binlog_checksum; +set @@global.binlog_checksum = default; +select @@global.binlog_checksum as 'must be NONE by default'; +must be NONE by default +NONE +select @@session.binlog_checksum as 'no session var'; +ERROR HY000: Variable 'binlog_checksum' is a GLOBAL variable +set @@global.binlog_checksum = CRC32; +set @@global.binlog_checksum = CRC32; +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; +set @@global.binlog_checksum = ADLER32; +ERROR 42000: Variable 'checksum' can't be set to the value of 'ADLER32' +set @@global.binlog_checksum = @save_binlog_checksum; diff --git a/mysql-test/suite/sys_vars/r/master_verify_checksum_basic.result b/mysql-test/suite/sys_vars/r/master_verify_checksum_basic.result new file mode 100644 index 00000000000..83a1283c358 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/master_verify_checksum_basic.result @@ -0,0 +1,11 @@ +set @save_master_verify_checksum = @@global.master_verify_checksum; +select @@global.master_verify_checksum as 'must be zero because of default'; +must be zero because of default +0 +select @@session.master_verify_checksum as 'no session var'; +ERROR HY000: Variable 'master_verify_checksum' is a GLOBAL variable +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; +set @@global.master_verify_checksum = 2; +ERROR 42000: Variable 'master_verify_checksum' can't be set to the value of '2' +set @@global.master_verify_checksum = @save_master_verify_checksum; diff --git a/mysql-test/suite/sys_vars/r/slave_sql_verify_checksum_basic.result b/mysql-test/suite/sys_vars/r/slave_sql_verify_checksum_basic.result new file mode 100644 index 00000000000..cd80381239a --- /dev/null +++ b/mysql-test/suite/sys_vars/r/slave_sql_verify_checksum_basic.result @@ -0,0 +1,11 @@ +set @save_slave_sql_verify_checksum = @@global.slave_sql_verify_checksum; +select @@global.slave_sql_verify_checksum as 'must be one because of default'; +must be one because of default +1 +select @@session.slave_sql_verify_checksum as 'no session var'; +ERROR HY000: Variable 'slave_sql_verify_checksum' is a GLOBAL variable +set @@global.slave_sql_verify_checksum = 0; +set @@global.slave_sql_verify_checksum = default; +set @@global.slave_sql_verify_checksum = 2; +ERROR 42000: Variable 'slave_sql_verify_checksum' can't be set to the value of '2' +set @@global.slave_sql_verify_checksum = @save_slave_sql_verify_checksum; diff --git a/mysql-test/suite/sys_vars/t/binlog_checksum_basic.test b/mysql-test/suite/sys_vars/t/binlog_checksum_basic.test new file mode 100644 index 00000000000..fb3d8e33fa1 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/binlog_checksum_basic.test @@ -0,0 +1,25 @@ +--source include/not_embedded.inc + +# suite/rpl/t/rpl_checksum.test contains similar testing of +# all checksum related system variables. + +set @save_binlog_checksum= @@global.binlog_checksum; +set @@global.binlog_checksum = default; + +select @@global.binlog_checksum as 'must be NONE by default'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.binlog_checksum as 'no session var'; + + +# testing lack of side-effects in non-effective update of binlog_checksum: +set @@global.binlog_checksum = CRC32; +set @@global.binlog_checksum = CRC32; + +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; + +--error ER_WRONG_VALUE_FOR_VAR +set @@global.binlog_checksum = ADLER32; + +# cleanup +set @@global.binlog_checksum = @save_binlog_checksum; diff --git a/mysql-test/suite/sys_vars/t/master_verify_checksum_basic.test b/mysql-test/suite/sys_vars/t/master_verify_checksum_basic.test new file mode 100644 index 00000000000..b70040ff2a2 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/master_verify_checksum_basic.test @@ -0,0 +1,19 @@ +--source include/not_embedded.inc + +# suite/rpl/t/rpl_checksum.test contains similar testing of +# all checksum related system variables. + +set @save_master_verify_checksum = @@global.master_verify_checksum; + +select @@global.master_verify_checksum as 'must be zero because of default'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.master_verify_checksum as 'no session var'; + +set @@global.master_verify_checksum = 0; +set @@global.master_verify_checksum = default; + +--error ER_WRONG_VALUE_FOR_VAR +set @@global.master_verify_checksum = 2; # the var is of bool type + +# cleanup +set @@global.master_verify_checksum = @save_master_verify_checksum; diff --git a/mysql-test/suite/sys_vars/t/slave_sql_verify_checksum_basic.test b/mysql-test/suite/sys_vars/t/slave_sql_verify_checksum_basic.test new file mode 100644 index 00000000000..3eb4f4b4e6d --- /dev/null +++ b/mysql-test/suite/sys_vars/t/slave_sql_verify_checksum_basic.test @@ -0,0 +1,18 @@ +--source include/not_embedded.inc + +# suite/rpl/t/rpl_checksum.test contains similar testing of +# all checksum related system variables. + +set @save_slave_sql_verify_checksum = @@global.slave_sql_verify_checksum; + +select @@global.slave_sql_verify_checksum as 'must be one because of default'; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +select @@session.slave_sql_verify_checksum as 'no session var'; + +set @@global.slave_sql_verify_checksum = 0; +set @@global.slave_sql_verify_checksum = default; +--error ER_WRONG_VALUE_FOR_VAR +set @@global.slave_sql_verify_checksum = 2; # the var is of bool type + +# cleanup +set @@global.slave_sql_verify_checksum = @save_slave_sql_verify_checksum; diff --git a/sql/log.cc b/sql/log.cc index 22f6b5a75a4..36152be3337 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -68,6 +68,7 @@ static LEX_STRING const write_error_msg= { C_STRING_WITH_LEN("error writing to the binary log") }; static my_bool opt_optimize_thread_scheduling= TRUE; +ulong binlog_checksum_options; #ifndef DBUG_OFF static ulong opt_binlog_dbug_fsync_sleep= 0; #endif @@ -2546,6 +2547,8 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG() group_commit_queue(0), group_commit_queue_busy(FALSE), num_commits(0), num_group_commits(0), is_relay_log(0), + checksum_alg_reset(BINLOG_CHECKSUM_ALG_UNDEF), + relay_log_checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF), description_event_for_exec(0), description_event_for_queue(0) { /* @@ -2781,10 +2784,23 @@ bool MYSQL_BIN_LOG::open(const char *log_name, as we won't be able to reset it later */ if (io_cache_type == WRITE_CACHE) - s.flags|= LOG_EVENT_BINLOG_IN_USE_F; + s.flags |= LOG_EVENT_BINLOG_IN_USE_F; + s.checksum_alg= is_relay_log ? + /* relay-log */ + /* inherit master's A descriptor if one has been received */ + (relay_log_checksum_alg= + (relay_log_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ? + relay_log_checksum_alg : + /* otherwise use slave's local preference of RL events verification */ + (opt_slave_sql_verify_checksum == 0) ? + (uint8) BINLOG_CHECKSUM_ALG_OFF : binlog_checksum_options): + /* binlog */ + binlog_checksum_options; + DBUG_ASSERT(s.checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); if (!s.is_valid()) goto err; s.dont_set_created= null_created_arg; + s.pre_55_writing_direct(); if (s.write(&log_file)) goto err; bytes_written+= s.data_written; @@ -2816,6 +2832,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, /* Don't set log_pos in event header */ description_event_for_queue->set_artificial_event(); + description_event_for_queue->pre_55_writing_direct(); if (description_event_for_queue->write(&log_file)) goto err; bytes_written+= description_event_for_queue->data_written; @@ -3955,8 +3972,16 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock) We log the whole file name for log file as the user may decide to change base names at some point. */ - Rotate_log_event r(new_name+dirname_length(new_name), - 0, LOG_EVENT_OFFSET, is_relay_log ? Rotate_log_event::RELAY_LOG : 0); + Rotate_log_event r(new_name+dirname_length(new_name), 0, LOG_EVENT_OFFSET, + is_relay_log ? Rotate_log_event::RELAY_LOG : 0); + /* + The current relay-log's closing Rotate event must have checksum + value computed with an algorithm of the last relay-logged FD event. + */ + if (is_relay_log) + r.checksum_alg= relay_log_checksum_alg; + r.pre_55_writing_direct(); + DBUG_ASSERT(!is_relay_log || relay_log_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); if(DBUG_EVALUATE_IF("fault_injection_new_file_rotate_event", (error=close_on_error=TRUE), FALSE) || (error= r.write(&log_file))) { @@ -3977,7 +4002,12 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock) old_name=name; name=0; // Don't free name close(LOG_CLOSE_TO_BE_OPENED | LOG_CLOSE_INDEX); - + if (log_type == LOG_BIN && checksum_alg_reset != BINLOG_CHECKSUM_ALG_UNDEF) + { + DBUG_ASSERT(!is_relay_log); + DBUG_ASSERT(binlog_checksum_options != checksum_alg_reset); + binlog_checksum_options= checksum_alg_reset; + } /* Note that at this point, log_state != LOG_CLOSED (important for is_open()). */ @@ -4056,6 +4086,7 @@ bool MYSQL_BIN_LOG::append(Log_event* ev) Log_event::write() is smart enough to use my_b_write() or my_b_append() depending on the kind of cache we have. */ + ev->pre_55_writing_direct(); if (ev->write(&log_file)) { error=1; @@ -4451,6 +4482,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, { /* Write directly to log file. */ pthread_mutex_lock(&LOCK_log); + pending->pre_55_writing_direct(); if (pending->write(&log_file)) { pthread_mutex_unlock(&LOCK_log); @@ -4493,6 +4525,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) { THD *thd= event_info->thd; bool error= 1; + uint16 cache_type; DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)"); if (thd->binlog_evt_union.do_union) @@ -4596,8 +4629,11 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } + event_info->pre_55_writing_direct(); } + cache_type= event_info->cache_type; + /* No check for auto events flag here - this write method should never be called if auto-events are enabled @@ -4611,7 +4647,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) if (with_annotate && *with_annotate) { DBUG_ASSERT(event_info->get_type_code() == TABLE_MAP_EVENT); - Annotate_rows_log_event anno(thd); + Annotate_rows_log_event anno(thd, cache_type); /* Annotate event should be written not more than once */ *with_annotate= 0; if (anno.write(file)) @@ -4625,10 +4661,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) { if (!thd->current_stmt_binlog_row_based) { + if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, - thd->first_successful_insert_id_in_prev_stmt_for_binlog); + thd->first_successful_insert_id_in_prev_stmt_for_binlog, + cache_type); if (e.write(file)) goto err_unlock; } @@ -4639,13 +4677,14 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) nb_elements())); Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT, thd->auto_inc_intervals_in_cur_stmt_for_binlog. - minimum()); + minimum(), cache_type); if (e.write(file)) goto err_unlock; } if (thd->rand_used) { - Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2); + Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2, + cache_type); if (e.write(file)) goto err_unlock; } @@ -4660,7 +4699,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) user_var_event->value, user_var_event->length, user_var_event->type, - user_var_event->charset_number); + user_var_event->charset_number, + cache_type); if (e.write(file)) goto err_unlock; } @@ -4816,6 +4856,8 @@ int MYSQL_BIN_LOG::rotate_and_purge(uint flags) #ifdef HAVE_REPLICATION check_purge= true; #endif + if (flags & RP_BINLOG_CHECKSUM_ALG_CHANGE) + checksum_alg_reset= BINLOG_CHECKSUM_ALG_UNDEF; // done } if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_unlock(&LOCK_log); @@ -4844,6 +4886,33 @@ uint MYSQL_BIN_LOG::next_file_id() } +/** + Calculate checksum of possibly a part of an event containing at least + the whole common header. + + @param buf the pointer to trans cache's buffer + @param off the offset of the beginning of the event in the buffer + @param event_len no-checksum length of the event + @param length the current size of the buffer + + @param crc [in-out] the checksum + + Event size in incremented by @c BINLOG_CHECKSUM_LEN. + + @return 0 or number of unprocessed yet bytes of the event excluding + the checksum part. +*/ + static ulong fix_log_event_crc(uchar *buf, uint off, uint event_len, + uint length, ha_checksum *crc) +{ + ulong ret; + uchar *event_begin= buf + off; + + ret= length >= off + event_len ? 0 : off + event_len - length; + *crc= my_checksum(*crc, event_begin, event_len - ret); + return ret; +} + /* Write the contents of a cache to the binary log. @@ -4855,7 +4924,11 @@ uint MYSQL_BIN_LOG::next_file_id() DESCRIPTION Write the contents of the cache to the binary log. The cache will be reset as a READ_CACHE to be able to read the contents from it. - */ + + Reading from the trans cache with possible (per @c binlog_checksum_options) + adding checksum value and then fixing the length and the end_log_pos of + events prior to fill in the binlog cache. +*/ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) { @@ -4863,8 +4936,17 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) return ER_ERROR_ON_WRITE; uint length= my_b_bytes_in_cache(cache), group, carry, hdr_offs; + ulong remains= 0; // part of unprocessed yet netto length of the event long val; + ulong end_log_pos_inc= 0; // each event processed adds BINLOG_CHECKSUM_LEN 2 t uchar header[LOG_EVENT_HEADER_LEN]; + ha_checksum crc= 0, crc_0= 0; // assignments to keep compiler happy + my_bool do_checksum= (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF); + uchar buf[BINLOG_CHECKSUM_LEN]; + + // while there is just one alg the following must hold: + DBUG_ASSERT(!do_checksum || + binlog_checksum_options == BINLOG_CHECKSUM_ALG_CRC32); /* The events in the buffer have incorrect end_log_pos data @@ -4882,6 +4964,8 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) group= (uint)my_b_tell(&log_file); hdr_offs= carry= 0; + if (do_checksum) + crc= crc_0= my_checksum(0L, NULL, 0); do { @@ -4895,12 +4979,21 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) DBUG_ASSERT(carry < LOG_EVENT_HEADER_LEN); /* assemble both halves */ - memcpy(&header[carry], (char *)cache->read_pos, LOG_EVENT_HEADER_LEN - carry); + memcpy(&header[carry], (char *)cache->read_pos, + LOG_EVENT_HEADER_LEN - carry); /* fix end_log_pos */ - val= uint4korr(&header[LOG_POS_OFFSET]) + group; + val= uint4korr(&header[LOG_POS_OFFSET]) + group + + (end_log_pos_inc+= (do_checksum ? BINLOG_CHECKSUM_LEN : 0)); int4store(&header[LOG_POS_OFFSET], val); + if (do_checksum) + { + ulong len= uint4korr(&header[EVENT_LEN_OFFSET]); + /* fix len */ + int4store(&header[EVENT_LEN_OFFSET], len + BINLOG_CHECKSUM_LEN); + } + /* write the first half of the split header */ if (my_b_write(&log_file, header, carry)) return ER_ERROR_ON_WRITE; @@ -4910,11 +5003,20 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) copy fixed second half of header to cache so the correct version will be written later. */ - memcpy((char *)cache->read_pos, &header[carry], LOG_EVENT_HEADER_LEN - carry); + memcpy((char *)cache->read_pos, &header[carry], + LOG_EVENT_HEADER_LEN - carry); /* next event header at ... */ - hdr_offs = uint4korr(&header[EVENT_LEN_OFFSET]) - carry; + hdr_offs= uint4korr(&header[EVENT_LEN_OFFSET]) - carry - + (do_checksum ? BINLOG_CHECKSUM_LEN : 0); + if (do_checksum) + { + DBUG_ASSERT(crc == crc_0 && remains == 0); + crc= my_checksum(crc, header, carry); + remains= uint4korr(header + EVENT_LEN_OFFSET) - carry - + BINLOG_CHECKSUM_LEN; + } carry= 0; } @@ -4929,6 +5031,25 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) very next iteration, just "eventually"). */ + /* crc-calc the whole buffer */ + if (do_checksum && hdr_offs >= length) + { + + DBUG_ASSERT(remains != 0 && crc != crc_0); + + crc= my_checksum(crc, cache->read_pos, length); + remains -= length; + if (my_b_write(&log_file, cache->read_pos, length)) + return ER_ERROR_ON_WRITE; + if (remains == 0) + { + int4store(buf, crc); + if (my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) + return ER_ERROR_ON_WRITE; + crc= crc_0; + } + } + while (hdr_offs < length) { /* @@ -4936,6 +5057,26 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) we get the rest. */ + if (do_checksum) + { + if (remains != 0) + { + /* + finish off with remains of the last event that crawls + from previous into the current buffer + */ + DBUG_ASSERT(crc != crc_0); + crc= my_checksum(crc, cache->read_pos, hdr_offs); + int4store(buf, crc); + remains -= hdr_offs; + DBUG_ASSERT(remains == 0); + if (my_b_write(&log_file, cache->read_pos, hdr_offs) || + my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) + return ER_ERROR_ON_WRITE; + crc= crc_0; + } + } + if (hdr_offs + LOG_EVENT_HEADER_LEN > length) { carry= length - hdr_offs; @@ -4945,17 +5086,38 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) else { /* we've got a full event-header, and it came in one piece */ - - uchar *log_pos= (uchar *)cache->read_pos + hdr_offs + LOG_POS_OFFSET; + uchar *ev= (uchar *)cache->read_pos + hdr_offs; + uint event_len= uint4korr(ev + EVENT_LEN_OFFSET); // netto len + uchar *log_pos= ev + LOG_POS_OFFSET; /* fix end_log_pos */ - val= uint4korr(log_pos) + group; + val= uint4korr(log_pos) + group + + (end_log_pos_inc += (do_checksum ? BINLOG_CHECKSUM_LEN : 0)); int4store(log_pos, val); + /* fix CRC */ + if (do_checksum) + { + /* fix length */ + int4store(ev + EVENT_LEN_OFFSET, event_len + BINLOG_CHECKSUM_LEN); + remains= fix_log_event_crc(cache->read_pos, hdr_offs, event_len, + length, &crc); + if (my_b_write(&log_file, ev, + remains == 0 ? event_len : length - hdr_offs)) + return ER_ERROR_ON_WRITE; + if (remains == 0) + { + int4store(buf, crc); + if (my_b_write(&log_file, buf, BINLOG_CHECKSUM_LEN)) + return ER_ERROR_ON_WRITE; + crc= crc_0; // crc is complete + } + } + /* next event header at ... */ - log_pos= (uchar *)cache->read_pos + hdr_offs + EVENT_LEN_OFFSET; - hdr_offs += uint4korr(log_pos); + hdr_offs += event_len; // incr by the netto len + DBUG_ASSERT(!do_checksum || remains == 0 || hdr_offs >= length); } } @@ -4973,14 +5135,17 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) /* Write data to the binary log file */ DBUG_EXECUTE_IF("fail_binlog_write_1", errno= 28; return ER_ERROR_ON_WRITE;); - if (my_b_write(&log_file, cache->read_pos, length)) - return ER_ERROR_ON_WRITE; + if (!do_checksum) + if (my_b_write(&log_file, cache->read_pos, length)) + return ER_ERROR_ON_WRITE; status_var_add(thd->status_var.binlog_bytes_written, length); cache->read_pos=cache->read_end; // Mark buffer used up } while ((length= my_b_fill(cache))); DBUG_ASSERT(carry == 0); + DBUG_ASSERT(!do_checksum || remains == 0); + DBUG_ASSERT(!do_checksum || crc == crc_0); return 0; // All OK } @@ -5024,6 +5189,7 @@ bool MYSQL_BIN_LOG::write_incident_already_locked(THD *thd) if (likely(is_open())) { + ev.pre_55_writing_direct(); error= ev.write(&log_file); status_var_add(thd->status_var.binlog_bytes_written, ev.data_written); } @@ -5414,6 +5580,7 @@ MYSQL_BIN_LOG::write_transaction(group_commit_entry *entry) binlog_trx_data *trx_data= entry->trx_data; IO_CACHE *cache= &trx_data->trans_log; + entry->begin_event->pre_55_writing_direct(); if (entry->begin_event->write(&log_file)) return ER_ERROR_ON_WRITE; status_var_add(entry->thd->status_var.binlog_bytes_written, @@ -5433,13 +5600,18 @@ MYSQL_BIN_LOG::write_transaction(group_commit_entry *entry) if (write_cache(entry->thd, cache)) return ER_ERROR_ON_WRITE; + entry->end_event->pre_55_writing_direct(); if (entry->end_event->write(&log_file)) return ER_ERROR_ON_WRITE; status_var_add(entry->thd->status_var.binlog_bytes_written, entry->end_event->data_written); - if (entry->incident_event && entry->incident_event->write(&log_file)) - return ER_ERROR_ON_WRITE; + if (entry->incident_event) + { + entry->incident_event->pre_55_writing_direct(); + if (entry->incident_event->write(&log_file)) + return ER_ERROR_ON_WRITE; + } if (cache->error) // Error on read return ER_ERROR_ON_READ; @@ -5503,6 +5675,12 @@ void MYSQL_BIN_LOG::close(uint exiting) (exiting & LOG_CLOSE_STOP_EVENT)) { Stop_log_event s; + // the checksumming rule for relay-log case is similar to Rotate + s.checksum_alg= is_relay_log ? + relay_log_checksum_alg : binlog_checksum_options; + DBUG_ASSERT(!is_relay_log || + relay_log_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); + s.pre_55_writing_direct(); s.write(&log_file); bytes_written+= s.data_written; signal_update(); @@ -6590,7 +6768,8 @@ int TC_LOG_BINLOG::open(const char *opt_name) goto err; } - if ((ev= Log_event::read_log_event(&log, 0, &fdle)) && + if ((ev= Log_event::read_log_event(&log, 0, &fdle, + opt_master_verify_checksum)) && ev->get_type_code() == FORMAT_DESCRIPTION_EVENT && ev->flags & LOG_EVENT_BINLOG_IN_USE_F) { @@ -6729,7 +6908,9 @@ int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) fdle->flags&= ~LOG_EVENT_BINLOG_IN_USE_F; // abort on the first error - while ((ev= Log_event::read_log_event(log,0,fdle)) && ev->is_valid()) + while ((ev= Log_event::read_log_event(log, 0, fdle, + opt_master_verify_checksum)) + && ev->is_valid()) { if (ev->get_type_code() == XID_EVENT) { @@ -6809,6 +6990,32 @@ mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file) #endif /* INNODB_COMPATIBILITY_HOOKS */ +static void +binlog_checksum_update(MYSQL_THD thd, struct st_mysql_sys_var *var, + void *var_ptr, const void *save) +{ + ulong value= *((ulong *)var_ptr); + + pthread_mutex_lock(mysql_bin_log.get_log_lock()); + if(mysql_bin_log.is_open()) + { + uint flags= RP_FORCE_ROTATE | RP_LOCK_LOG_IS_ALREADY_LOCKED | + (binlog_checksum_options != (uint) value? + RP_BINLOG_CHECKSUM_ALG_CHANGE : 0); + if (flags & RP_BINLOG_CHECKSUM_ALG_CHANGE) + mysql_bin_log.checksum_alg_reset= (uint8) value; + mysql_bin_log.rotate_and_purge(flags); + } + else + { + binlog_checksum_options= value; + } + DBUG_ASSERT((ulong) binlog_checksum_options == value); + DBUG_ASSERT(mysql_bin_log.checksum_alg_reset == BINLOG_CHECKSUM_ALG_UNDEF); + pthread_mutex_unlock(mysql_bin_log.get_log_lock()); +} + + static int show_binlog_vars(THD *thd, SHOW_VAR *var, char *buff) { mysql_bin_log.set_status_variables(thd); @@ -6835,6 +7042,18 @@ static MYSQL_SYSVAR_BOOL( NULL, 1); +static MYSQL_SYSVAR_ENUM( + checksum, + binlog_checksum_options, + PLUGIN_VAR_RQCMDARG, + "Type of BINLOG_CHECKSUM_ALG. Include checksum for " + "log events in the binary log. Possible values are NONE and CRC32; " + "default is NONE.", + NULL, + binlog_checksum_update, + BINLOG_CHECKSUM_ALG_OFF, + &binlog_checksum_typelib); + #ifndef DBUG_OFF static MYSQL_SYSVAR_ULONG( dbug_fsync_sleep, @@ -6852,6 +7071,7 @@ static MYSQL_SYSVAR_ULONG( static struct st_mysql_sys_var *binlog_sys_vars[]= { MYSQL_SYSVAR(optimize_thread_scheduling), + MYSQL_SYSVAR(checksum), #ifndef DBUG_OFF MYSQL_SYSVAR(dbug_fsync_sleep), #endif diff --git a/sql/log.h b/sql/log.h index 503e94df981..6437046b17b 100644 --- a/sql/log.h +++ b/sql/log.h @@ -403,7 +403,41 @@ public: /* This is relay log */ bool is_relay_log; - + uint8 checksum_alg_reset; // to contain a new value when binlog is rotated + /* + Holds the last seen in Relay-Log FD's checksum alg value. + The initial value comes from the slave's local FD that heads + the very first Relay-Log file. In the following the value may change + with each received master's FD_m. + Besides to be used in verification events that IO thread receives + (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd), + the value specifies if/how to compute checksum for slave's local events + and the first fake Rotate (R_f^1) coming from the master. + R_f^1 needs logging checksum-compatibly with the RL's heading FD_s. + + Legends for the checksum related comments: + + FD - Format-Description event, + R - Rotate event + R_f - the fake Rotate event + E - an arbirary event + + The underscore indexes for any event + `_s' indicates the event is generated by Slave + `_m' - by Master + + Two special underscore indexes of FD: + FD_q - Format Description event for queuing (relay-logging) + FD_e - Format Description event for executing (relay-logging) + + Upper indexes: + E^n - n:th event is a sequence + + RL - Relay Log + (A) - checksum algorithm descriptor value + FD.(A) - the value of (A) in FD + */ + uint8 relay_log_checksum_alg; /* These describe the log's format. This is used only for relay logs. _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's diff --git a/sql/log_event.cc b/sql/log_event.cc index 0259ff762ad..b31c991b9f3 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -38,6 +38,31 @@ #include <base64.h> #include <my_bitmap.h> + +/** + BINLOG_CHECKSUM variable. +*/ +const char *binlog_checksum_type_names[]= { + "NONE", + "CRC32", + NullS +}; + +unsigned int binlog_checksum_type_length[]= { + sizeof("NONE") - 1, + sizeof("CRC32") - 1, + 0 +}; + +TYPELIB binlog_checksum_typelib= +{ + array_elements(binlog_checksum_type_names) - 1, "", + binlog_checksum_type_names, + binlog_checksum_type_length +}; + + + #define log_cs &my_charset_latin1 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"") @@ -51,6 +76,24 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +/* + replication event checksum is introduced in the following "checksum-home" version. + The checksum-aware servers extract FD's version to decide whether the FD event + carries checksum info. + + TODO: correct the constant when it has been determined + (which main tree to push and when) +*/ +const uchar checksum_version_split_mysql[3]= {5, 6, 1}; +const ulong checksum_version_product_mysql= + (checksum_version_split_mysql[0] * 256 + + checksum_version_split_mysql[1]) * 256 + + checksum_version_split_mysql[2]; +const uchar checksum_version_split_mariadb[3]= {5, 2, 5}; +const ulong checksum_version_product_mariadb= + (checksum_version_split_mariadb[0] * 256 + + checksum_version_split_mariadb[1]) * 256 + + checksum_version_split_mariadb[2]; #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); @@ -610,7 +653,6 @@ static void print_set_option(IO_CACHE* file, uint32 bits_changed, } } #endif - /************************************************************************** Log_event methods (= the parent class of all events) **************************************************************************/ @@ -666,7 +708,9 @@ const char* Log_event::get_type_str() #ifndef MYSQL_CLIENT Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) - :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), thd(thd_arg) + :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg), + cache_type(EVENT_INVALID_CACHE), crc(0), thd(thd_arg), + checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF) { server_id= thd->server_id; when= thd->start_time; @@ -683,7 +727,8 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) Log_event::Log_event() :temp_buf(0), exec_time(0), flags(0), cache_stmt(0), - thd(0) + cache_type(EVENT_INVALID_CACHE), crc(0), + thd(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF) { server_id= ::server_id; /* @@ -702,7 +747,8 @@ Log_event::Log_event() Log_event::Log_event(const char* buf, const Format_description_log_event* description_event) - :temp_buf(0), cache_stmt(0) + :temp_buf(0), cache_stmt(0), cache_type(EVENT_INVALID_CACHE), + crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF) { #ifndef MYSQL_CLIENT thd = 0; @@ -887,6 +933,106 @@ void Log_event::init_show_field_list(List<Item>* field_list) field_list->push_back(new Item_empty_string("Info", 20)); } +/** + A decider of whether to trigger checksum computation or not. + To be invoked in Log_event::write() stack. + The decision is positive + + S,M) if it's been marked for checksumming with @c checksum_alg + + M) otherwise, if @@global.binlog_checksum is not NONE and the event is + directly written to the binlog file. + The to-be-cached event decides at @c write_cache() time. + + Otherwise the decision is negative. + + @note A side effect of the method is altering Log_event::checksum_alg + it the latter was undefined at calling. + + @return true (positive) or false (negative) +*/ +my_bool Log_event::need_checksum() +{ + DBUG_ENTER("Log_event::need_checksum"); + my_bool ret; + extern ulong binlog_checksum_options; + /* + few callers of Log_event::write + (incl FD::write, FD constructing code on the slave side, Rotate relay log + and Stop event) + provides their checksum alg preference through Log_event::checksum_alg. + */ + ret= (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ? + (checksum_alg != BINLOG_CHECKSUM_ALG_OFF) : + ((binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF) && + (cache_type == Log_event::EVENT_NO_CACHE))? binlog_checksum_options : + FALSE; + + /* + FD calls the methods before data_written has been calculated. + The following invariant claims if the current is not the first + call (and therefore data_written is not zero) then `ret' must be + TRUE. It may not be null because FD is always checksummed. + */ + + DBUG_ASSERT(get_type_code() != FORMAT_DESCRIPTION_EVENT || ret || + data_written == 0); + + if (checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF) + checksum_alg= ret ? // calculated value stored + binlog_checksum_options : (uint8) BINLOG_CHECKSUM_ALG_OFF; + + DBUG_ASSERT(!ret || + ((checksum_alg == binlog_checksum_options || + /* + Stop event closes the relay-log and its checksum alg + preference is set by the caller can be different + from the server's binlog_checksum_options. + */ + get_type_code() == STOP_EVENT || + /* + Rotate:s can be checksummed regardless of the server's + binlog_checksum_options. That applies to both + the local RL's Rotate and the master's Rotate + which IO thread instantiates via queue_binlog_ver_3_event. + */ + get_type_code() == ROTATE_EVENT + || /* FD is always checksummed */ + get_type_code() == FORMAT_DESCRIPTION_EVENT) && + checksum_alg != BINLOG_CHECKSUM_ALG_OFF)); + + DBUG_ASSERT(checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); + + DBUG_ASSERT(((get_type_code() != ROTATE_EVENT && + get_type_code() != STOP_EVENT) || + get_type_code() != FORMAT_DESCRIPTION_EVENT) || + cache_type == Log_event::EVENT_NO_CACHE); + + DBUG_RETURN(ret); +} + +bool Log_event::wrapper_my_b_safe_write(IO_CACHE* file, const uchar* buf, ulong size) +{ + if (need_checksum() && size != 0) + crc= my_checksum(crc, buf, size); + + return my_b_safe_write(file, buf, size); +} + +bool Log_event::write_footer(IO_CACHE* file) +{ + /* + footer contains the checksum-algorithm descriptor + followed by the checksum value + */ + if (need_checksum()) + { + uchar buf[BINLOG_CHECKSUM_LEN]; + int4store(buf, crc); + return (my_b_safe_write(file, (uchar*) buf, sizeof(buf))); + } + return 0; +} /* Log_event::write() @@ -896,11 +1042,18 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) { uchar header[LOG_EVENT_HEADER_LEN]; ulong now; + bool ret; DBUG_ENTER("Log_event::write_header"); /* Store number of bytes that will be written by this event */ data_written= event_data_length + sizeof(header); + if (need_checksum()) + { + crc= my_checksum(0L, NULL, 0); + data_written += BINLOG_CHECKSUM_LEN; + } + /* log_pos != 0 if this is relay-log event. In this case we should not change the position @@ -959,9 +1112,36 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) int4store(header+ SERVER_ID_OFFSET, server_id); int4store(header+ EVENT_LEN_OFFSET, data_written); int4store(header+ LOG_POS_OFFSET, log_pos); - int2store(header+ FLAGS_OFFSET, flags); - - DBUG_RETURN(my_b_safe_write(file, header, sizeof(header)) != 0); + /* + recording checksum of FD event computed with dropped + possibly active LOG_EVENT_BINLOG_IN_USE_F flag. + Similar step at verication: the active flag is dropped before + checksum computing. + */ + if (header[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT || + !need_checksum() || !(flags & LOG_EVENT_BINLOG_IN_USE_F)) + { + int2store(header+ FLAGS_OFFSET, flags); + ret= wrapper_my_b_safe_write(file, header, sizeof(header)) != 0; + } + else + { + ret= (wrapper_my_b_safe_write(file, header, FLAGS_OFFSET) != 0); + if (!ret) + { + flags &= ~LOG_EVENT_BINLOG_IN_USE_F; + int2store(header + FLAGS_OFFSET, flags); + crc= my_checksum(crc, header + FLAGS_OFFSET, sizeof(flags)); + flags |= LOG_EVENT_BINLOG_IN_USE_F; + int2store(header + FLAGS_OFFSET, flags); + ret= (my_b_safe_write(file, header + FLAGS_OFFSET, sizeof(flags)) != 0); + } + if (!ret) + ret= (wrapper_my_b_safe_write(file, header + FLAGS_OFFSET + sizeof(flags), + sizeof(header) + - (FLAGS_OFFSET + sizeof(flags))) != 0); + } + DBUG_RETURN( ret); } @@ -971,11 +1151,13 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) */ int Log_event::read_log_event(IO_CACHE* file, String* packet, - pthread_mutex_t* log_lock) + pthread_mutex_t* log_lock, + uint8 checksum_alg_arg) { ulong data_len; int result=0; char buf[LOG_EVENT_MINIMAL_HEADER_LEN]; + uchar ev_offset= packet->length(); DBUG_ENTER("Log_event::read_log_event"); if (log_lock) @@ -1033,6 +1215,31 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, (file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO)); /* Implicit goto end; */ } + else + { + /* Corrupt the event for Dump thread*/ + DBUG_EXECUTE_IF("corrupt_read_log_event2", + uchar *debug_event_buf_c = (uchar*) packet->ptr() + ev_offset; + if (debug_event_buf_c[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT) + { + int debug_cor_pos = rand() % (data_len + sizeof(buf) - BINLOG_CHECKSUM_LEN); + debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos]; + DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event: byte on position %d", debug_cor_pos)); + DBUG_SET("-d,corrupt_read_log_event2"); + } + ); + /* + CRC verification of the Dump thread + */ + if (opt_master_verify_checksum && + event_checksum_test((uchar*) packet->ptr() + ev_offset, + data_len + sizeof(buf), + checksum_alg_arg)) + { + result= LOG_READ_CHECKSUM_FAILURE; + goto end; + } + } } end: @@ -1058,11 +1265,13 @@ end: Log_event* Log_event::read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, const Format_description_log_event - *description_event) + *description_event, + my_bool crc_check) #else Log_event* Log_event::read_log_event(IO_CACHE* file, const Format_description_log_event - *description_event) + *description_event, + my_bool crc_check) #endif { DBUG_ENTER("Log_event::read_log_event"); @@ -1126,7 +1335,7 @@ failed my_b_read")); error = "read error"; goto err; } - if ((res= read_log_event(buf, data_len, &error, description_event))) + if ((res= read_log_event(buf, data_len, &error, description_event, crc_check))) res->register_temp_buf(buf, TRUE); err: @@ -1159,9 +1368,11 @@ err: Log_event* Log_event::read_log_event(const char* buf, uint event_len, const char **error, - const Format_description_log_event *description_event) + const Format_description_log_event *description_event, + my_bool crc_check) { Log_event* ev; + uint8 alg; DBUG_ENTER("Log_event::read_log_event(char*,...)"); DBUG_ASSERT(description_event != 0); DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version)); @@ -1177,6 +1388,60 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, } uint event_type= (uchar)buf[EVENT_TYPE_OFFSET]; + // all following START events in the current file are without checksum + if (event_type == START_EVENT_V3) + (const_cast< Format_description_log_event *>(description_event))->checksum_alg= BINLOG_CHECKSUM_ALG_OFF; + /* + CRC verification by SQL and Show-Binlog-Events master side. + The caller has to provide @description_event->checksum_alg to + be the last seen FD's (A) descriptor. + If event is FD the descriptor is in it. + Notice, FD of the binlog can be only in one instance and therefore + Show-Binlog-Events executing master side thread needs just to know + the only FD's (A) value - whereas RL can contain more. + In the RL case, the alg is kept in FD_e (@description_event) which is reset + to the newer read-out event after its execution with possibly new alg descriptor. + Therefore in a typical sequence of RL: + {FD_s^0, FD_m, E_m^1} E_m^1 + will be verified with (A) of FD_m. + + See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg docs + lines (log.h). + + Notice, a pre-checksum FD version forces alg := BINLOG_CHECKSUM_ALG_UNDEF. + */ + alg= (event_type != FORMAT_DESCRIPTION_EVENT) ? + description_event->checksum_alg : get_checksum_alg(buf, event_len); + // Emulate the corruption during reading an event + DBUG_EXECUTE_IF("corrupt_read_log_event_char", + if (event_type != FORMAT_DESCRIPTION_EVENT) + { + char *debug_event_buf_c = (char *)buf; + int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN); + debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos]; + DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event(char*,...): byte on position %d", debug_cor_pos)); + DBUG_SET("-d,corrupt_read_log_event_char"); + } + ); + if (crc_check && + event_checksum_test((uchar *) buf, event_len, alg)) + { +#ifdef MYSQL_CLIENT + *error= "Event crc check failed! Most likely there is event corruption."; + if (force_opt) + { + ev= new Unknown_log_event(buf, description_event); + DBUG_RETURN(ev); + } + else + DBUG_RETURN(NULL); +#else + *error= ER(ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE); + sql_print_error("%s", ER(ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE)); + DBUG_RETURN(NULL); +#endif + } + if (event_type > description_event->number_of_event_types && event_type != FORMAT_DESCRIPTION_EVENT) { @@ -1215,6 +1480,11 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, event_type= description_event->event_type_permutation[event_type]; } + if (alg != BINLOG_CHECKSUM_ALG_UNDEF && + (event_type == FORMAT_DESCRIPTION_EVENT || + alg != BINLOG_CHECKSUM_ALG_OFF)) + event_len= event_len - BINLOG_CHECKSUM_LEN; + switch(event_type) { case QUERY_EVENT: ev = new Query_log_event(buf, event_len, description_event, QUERY_EVENT); @@ -1309,6 +1579,14 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, } } + if (ev) + { + ev->checksum_alg= alg; + if (ev->checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + ev->checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + ev->crc= uint4korr(buf + (event_len)); + } + DBUG_PRINT("read_event", ("%s(type_code: %d; event_len: %d)", ev ? ev->get_type_str() : "<unknown>", buf[EVENT_TYPE_OFFSET], @@ -1363,6 +1641,18 @@ void Log_event::print_header(IO_CACHE* file, my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id, llstr(log_pos,llbuff)); + /* print the checksum */ + + if (checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + { + char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx " + size_t const bytes_written= + my_snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong) crc); + my_b_printf(file, "%s ", get_type(&binlog_checksum_typelib, checksum_alg)); + my_b_printf(file, checksum_buf, bytes_written); + } + /* mysqlbinlog --hexdump */ if (print_event_info->hexdump_from) { @@ -2028,6 +2318,9 @@ void Log_event::print_base64(IO_CACHE* file, if (print_event_info->verbose) { Rows_log_event *ev= NULL; + if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF && + checksum_alg != BINLOG_CHECKSUM_ALG_OFF) + size-= BINLOG_CHECKSUM_LEN; // checksum is displayed through the header if (ptr[4] == TABLE_MAP_EVENT) { @@ -2390,12 +2683,13 @@ bool Query_log_event::write(IO_CACHE* file) event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len; return (write_header(file, event_length) || - my_b_safe_write(file, (uchar*) buf, QUERY_HEADER_LEN) || + wrapper_my_b_safe_write(file, (uchar*) buf, QUERY_HEADER_LEN) || write_post_header_for_derived(file) || - my_b_safe_write(file, (uchar*) start_of_status, + wrapper_my_b_safe_write(file, (uchar*) start_of_status, (uint) (start-start_of_status)) || - my_b_safe_write(file, (db) ? (uchar*) db : (uchar*)"", db_len + 1) || - my_b_safe_write(file, (uchar*) query, q_len)) ? 1 : 0; + wrapper_my_b_safe_write(file, (db) ? (uchar*) db : (uchar*)"", db_len + 1) || + wrapper_my_b_safe_write(file, (uchar*) query, q_len) || + write_footer(file)) ? 1 : 0; } /** @@ -3623,7 +3917,8 @@ bool Start_log_event_v3::write(IO_CACHE* file) created= when= get_time(); int4store(buff + ST_CREATED_OFFSET,created); return (write_header(file, sizeof(buff)) || - my_b_safe_write(file, (uchar*) buff, sizeof(buff))); + wrapper_my_b_safe_write(file, (uchar*) buff, sizeof(buff)) || + write_footer(file)); } #endif @@ -3725,6 +4020,7 @@ int Start_log_event_v3::do_apply_event(Relay_log_info const *rli) old 4.0 (binlog version 2) is not supported; it should not be used for replication with 5.0. + @param server_ver a string containing the server version. */ Format_description_log_event:: @@ -3740,9 +4036,9 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) common_header_len= LOG_EVENT_HEADER_LEN; number_of_event_types= LOG_EVENT_TYPES; /* we'll catch my_malloc() error in is_valid() */ - post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8), + post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8) + + BINLOG_CHECKSUM_ALG_DESC_LEN, MYF(0)); - /* This long list of assignments is not beautiful, but I see no way to make it nicer, as the right members are #defines, not array members, so @@ -3866,6 +4162,7 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) break; } calc_server_version_split(); + checksum_alg= (uint8) BINLOG_CHECKSUM_ALG_UNDEF; } @@ -3900,14 +4197,26 @@ Format_description_log_event(const char* buf, if ((common_header_len=buf[ST_COMMON_HEADER_LEN_OFFSET]) < OLD_HEADER_LEN) DBUG_VOID_RETURN; /* sanity check */ number_of_event_types= - event_len-(LOG_EVENT_MINIMAL_HEADER_LEN+ST_COMMON_HEADER_LEN_OFFSET+1); + event_len - (LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET + 1); DBUG_PRINT("info", ("common_header_len=%d number_of_event_types=%d", common_header_len, number_of_event_types)); /* If alloc fails, we'll detect it in is_valid() */ + post_header_len= (uint8*) my_memdup((uchar*)buf+ST_COMMON_HEADER_LEN_OFFSET+1, number_of_event_types* - sizeof(*post_header_len), MYF(0)); + sizeof(*post_header_len), + MYF(0)); calc_server_version_split(); + if (!is_version_before_checksum(&server_version_split)) + { + /* the last bytes are the checksum alg desc and value (or value's room) */ + number_of_event_types -= BINLOG_CHECKSUM_ALG_DESC_LEN; + checksum_alg= post_header_len[number_of_event_types]; + } + else + { + checksum_alg= (uint8) BINLOG_CHECKSUM_ALG_UNDEF; + } /* In some previous versions, the events were given other event type @@ -4018,21 +4327,59 @@ Format_description_log_event(const char* buf, #ifndef MYSQL_CLIENT bool Format_description_log_event::write(IO_CACHE* file) { + bool ret; + bool no_checksum; /* We don't call Start_log_event_v3::write() because this would make 2 my_b_safe_write(). */ - uchar buff[FORMAT_DESCRIPTION_HEADER_LEN]; + uchar buff[FORMAT_DESCRIPTION_HEADER_LEN + BINLOG_CHECKSUM_ALG_DESC_LEN]; + size_t rec_size= sizeof(buff); int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version); memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN); if (!dont_set_created) created= when= get_time(); int4store(buff + ST_CREATED_OFFSET,created); buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN; - memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET+1, (uchar*) post_header_len, + memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET + 1, (uchar*) post_header_len, LOG_EVENT_TYPES); - return (write_header(file, sizeof(buff)) || - my_b_safe_write(file, buff, sizeof(buff))); + /* + if checksum is requested + record the checksum-algorithm descriptor next to + post_header_len vector which will be followed by the checksum value. + Master is supposed to trigger checksum computing by binlog_checksum_options, + slave does it via marking the event according to + FD_queue checksum_alg value. + */ + compile_time_assert(sizeof(BINLOG_CHECKSUM_ALG_DESC_LEN == 1)); +#ifndef DBUG_OFF + data_written= 0; // to prepare for need_checksum assert +#endif + buff[FORMAT_DESCRIPTION_HEADER_LEN]= need_checksum() ? + checksum_alg : (uint8) BINLOG_CHECKSUM_ALG_OFF; + /* + FD of checksum-aware server is always checksum-equipped, (V) is in, + regardless of @@global.binlog_checksum policy. + Thereby a combination of (A) == 0, (V) != 0 means + it's the checksum-aware server's FD event that heads checksum-free binlog + file. + Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case. + A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server + heading the checksummed binlog. + (A), (V) presence in FD of the checksum-aware server makes the event + 1 + 4 bytes bigger comparing to the former FD. + */ + + if ((no_checksum= (checksum_alg == BINLOG_CHECKSUM_ALG_OFF))) + { + checksum_alg= BINLOG_CHECKSUM_ALG_CRC32; // Forcing (V) room to fill anyway + } + ret= (write_header(file, rec_size) || + wrapper_my_b_safe_write(file, buff, rec_size) || + write_footer(file)); + if (no_checksum) + checksum_alg= BINLOG_CHECKSUM_ALG_OFF; + return ret; } #endif @@ -4128,6 +4475,30 @@ Format_description_log_event::do_shall_skip(Relay_log_info *rli) #endif +static inline void +do_server_version_split(char* version, + Format_description_log_event::master_version_split *split_versions) +{ + char *p= version, *r; + ulong number; + for (uint i= 0; i<=2; i++) + { + number= strtoul(p, &r, 10); + split_versions->ver[i]= (uchar) number; + DBUG_ASSERT(number < 256); // fit in uchar + p= r; + DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice + if (*r == '.') + p++; // skip the dot + } + if (strinstr(p, "MariaDB") != 0 || strinstr(p, "-maria-") != 0) + split_versions->kind= + Format_description_log_event::master_version_split::KIND_MARIADB; + else + split_versions->kind= + Format_description_log_event::master_version_split::KIND_MYSQL; +} + /** Splits the event's 'server_version' string into three numeric pieces stored @@ -4140,24 +4511,67 @@ Format_description_log_event::do_shall_skip(Relay_log_info *rli) */ void Format_description_log_event::calc_server_version_split() { - char *p= server_version, *r; - ulong number; - for (uint i= 0; i<=2; i++) - { - number= strtoul(p, &r, 10); - server_version_split[i]= (uchar)number; - DBUG_ASSERT(number < 256); // fit in uchar - p= r; - DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice - if (*r == '.') - p++; // skip the dot - } + do_server_version_split(server_version, &server_version_split); + DBUG_PRINT("info",("Format_description_log_event::server_version_split:" " '%s' %d %d %d", server_version, - server_version_split[0], - server_version_split[1], server_version_split[2])); + server_version_split.ver[0], + server_version_split.ver[1], server_version_split.ver[2])); +} + +static inline ulong +version_product(const Format_description_log_event::master_version_split* version_split) +{ + return ((version_split->ver[0] * 256 + version_split->ver[1]) * 256 + + version_split->ver[2]); } +/** + @return TRUE is the event's version is earlier than one that introduced + the replication event checksum. FALSE otherwise. +*/ +bool +Format_description_log_event::is_version_before_checksum(master_version_split + *version_split) +{ + return version_product(version_split) < + (version_split->kind == master_version_split::KIND_MARIADB ? + checksum_version_product_mariadb : checksum_version_product_mysql); +} + +/** + @param buf buffer holding serialized FD event + @param len netto (possible checksum is stripped off) length of the event buf + + @return the version-safe checksum alg descriptor where zero + designates no checksum, 255 - the orginator is + checksum-unaware (effectively no checksum) and the actuall + [1-254] range alg descriptor. +*/ +uint8 get_checksum_alg(const char* buf, ulong len) +{ + uint8 ret; + char version[ST_SERVER_VER_LEN]; + Format_description_log_event::master_version_split version_split; + + DBUG_ENTER("get_checksum_alg"); + DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT); + + memcpy(version, buf + + buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET] + + ST_SERVER_VER_OFFSET, ST_SERVER_VER_LEN); + version[ST_SERVER_VER_LEN - 1]= 0; + + do_server_version_split(version, &version_split); + ret= Format_description_log_event::is_version_before_checksum(&version_split) ? + (uint8) BINLOG_CHECKSUM_ALG_UNDEF : + * (uint8*) (buf + len - BINLOG_CHECKSUM_LEN - BINLOG_CHECKSUM_ALG_DESC_LEN); + DBUG_ASSERT(ret == BINLOG_CHECKSUM_ALG_OFF || + ret == BINLOG_CHECKSUM_ALG_UNDEF || + ret == BINLOG_CHECKSUM_ALG_CRC32); + DBUG_RETURN(ret); +} + /************************************************************************** Load_log_event methods @@ -5001,6 +5415,7 @@ Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg, DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg, llstr(pos_arg, buff), (ulong) flags)); #endif + cache_type= EVENT_NO_CACHE; if (flags & DUP_NAME) new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME)); if (flags & RELAY_LOG) @@ -5042,9 +5457,11 @@ bool Rotate_log_event::write(IO_CACHE* file) { char buf[ROTATE_HEADER_LEN]; int8store(buf + R_POS_OFFSET, pos); - return (write_header(file, ROTATE_HEADER_LEN + ident_len) || - my_b_safe_write(file, (uchar*)buf, ROTATE_HEADER_LEN) || - my_b_safe_write(file, (uchar*)new_log_ident, (uint) ident_len)); + return (write_header(file, ROTATE_HEADER_LEN + ident_len) || + wrapper_my_b_safe_write(file, (uchar*) buf, ROTATE_HEADER_LEN) || + wrapper_my_b_safe_write(file, (uchar*) new_log_ident, + (uint) ident_len) || + write_footer(file)); } #endif @@ -5213,7 +5630,8 @@ bool Intvar_log_event::write(IO_CACHE* file) buf[I_TYPE_OFFSET]= (uchar) type; int8store(buf + I_VAL_OFFSET, val); return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + wrapper_my_b_safe_write(file, buf, sizeof(buf)) || + write_footer(file)); } #endif @@ -5341,7 +5759,8 @@ bool Rand_log_event::write(IO_CACHE* file) int8store(buf + RAND_SEED1_OFFSET, seed1); int8store(buf + RAND_SEED2_OFFSET, seed2); return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + wrapper_my_b_safe_write(file, buf, sizeof(buf)) || + write_footer(file)); } #endif @@ -5443,8 +5862,9 @@ Xid_log_event(const char* buf, bool Xid_log_event::write(IO_CACHE* file) { DBUG_EXECUTE_IF("do_not_write_xid", return 0;); - return write_header(file, sizeof(xid)) || - my_b_safe_write(file, (uchar*) &xid, sizeof(xid)); + return (write_header(file, sizeof(xid)) || + wrapper_my_b_safe_write(file, (uchar*) &xid, sizeof(xid)) || + write_footer(file)); } #endif @@ -5663,10 +6083,11 @@ bool User_var_log_event::write(IO_CACHE* file) event_length= sizeof(buf)+ name_len + buf1_length + val_len; return (write_header(file, event_length) || - my_b_safe_write(file, (uchar*) buf, sizeof(buf)) || - my_b_safe_write(file, (uchar*) name, name_len) || - my_b_safe_write(file, (uchar*) buf1, buf1_length) || - my_b_safe_write(file, pos, val_len)); + wrapper_my_b_safe_write(file, (uchar*) buf, sizeof(buf)) || + wrapper_my_b_safe_write(file, (uchar*) name, name_len) || + wrapper_my_b_safe_write(file, (uchar*) buf1, buf1_length) || + wrapper_my_b_safe_write(file, pos, val_len) || + write_footer(file)); } #endif @@ -6424,8 +6845,9 @@ bool Append_block_log_event::write(IO_CACHE* file) uchar buf[APPEND_BLOCK_HEADER_LEN]; int4store(buf + AB_FILE_ID_OFFSET, file_id); return (write_header(file, APPEND_BLOCK_HEADER_LEN + block_len) || - my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || - my_b_safe_write(file, (uchar*) block, block_len)); + wrapper_my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) || + wrapper_my_b_safe_write(file, (uchar*) block, block_len) || + write_footer(file)); } #endif @@ -6579,7 +7001,8 @@ bool Delete_file_log_event::write(IO_CACHE* file) uchar buf[DELETE_FILE_HEADER_LEN]; int4store(buf + DF_FILE_ID_OFFSET, file_id); return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + wrapper_my_b_safe_write(file, buf, sizeof(buf)) || + write_footer(file)); } #endif @@ -6676,7 +7099,8 @@ bool Execute_load_log_event::write(IO_CACHE* file) uchar buf[EXEC_LOAD_HEADER_LEN]; int4store(buf + EL_FILE_ID_OFFSET, file_id); return (write_header(file, sizeof(buf)) || - my_b_safe_write(file, buf, sizeof(buf))); + wrapper_my_b_safe_write(file, buf, sizeof(buf)) || + write_footer(file)); } #endif @@ -6737,16 +7161,17 @@ int Execute_load_log_event::do_apply_event(Relay_log_info const *rli) fname); goto err; } - if (!(lev = (Load_log_event*)Log_event::read_log_event(&file, - (pthread_mutex_t*)0, - rli->relay_log.description_event_for_exec)) || + if (!(lev= (Load_log_event*) + Log_event::read_log_event(&file, + (pthread_mutex_t*)0, + rli->relay_log.description_event_for_exec, + opt_slave_sql_verify_checksum)) || lev->get_type_code() != NEW_LOAD_EVENT) { rli->report(ERROR_LEVEL, 0, "Error in Exec_load event: " "file '%s' appears corrupted", fname); goto err; } - lev->thd = thd; /* lev->do_apply_event should use rli only for errors i.e. should @@ -6909,7 +7334,7 @@ Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file) int4store(buf + 4, fn_pos_start); int4store(buf + 4 + 4, fn_pos_end); *(buf + 4 + 4 + 4)= (uchar) dup_handling; - return my_b_safe_write(file, buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); + return wrapper_my_b_safe_write(file, buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN); } #endif @@ -7876,11 +8301,11 @@ bool Rows_log_event::write_data_header(IO_CACHE *file) { int4store(buf + 0, m_table_id); int2store(buf + 4, m_flags); - return (my_b_safe_write(file, buf, 6)); + return (wrapper_my_b_safe_write(file, buf, 6)); }); int6store(buf + RW_MAPID_OFFSET, (ulonglong)m_table_id); int2store(buf + RW_FLAGS_OFFSET, m_flags); - return (my_b_safe_write(file, buf, ROWS_HEADER_LEN)); + return (wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN)); } bool Rows_log_event::write_data_body(IO_CACHE*file) @@ -7896,10 +8321,10 @@ bool Rows_log_event::write_data_body(IO_CACHE*file) DBUG_ASSERT(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf)); DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); - res= res || my_b_safe_write(file, sbuf, (size_t) (sbuf_end - sbuf)); + res= res || wrapper_my_b_safe_write(file, sbuf, (size_t) (sbuf_end - sbuf)); DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || my_b_safe_write(file, (uchar*) m_cols.bitmap, + res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); /* TODO[refactor write]: Remove the "down cast" here (and elsewhere). @@ -7908,11 +8333,11 @@ bool Rows_log_event::write_data_body(IO_CACHE*file) { DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); - res= res || my_b_safe_write(file, (uchar*) m_cols_ai.bitmap, + res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); } DBUG_DUMP("rows", m_rows_buf, data_size); - res= res || my_b_safe_write(file, m_rows_buf, (size_t) data_size); + res= res || wrapper_my_b_safe_write(file, m_rows_buf, (size_t) data_size); return res; @@ -7961,13 +8386,15 @@ void Rows_log_event::print_helper(FILE *file, **************************************************************************/ #ifndef MYSQL_CLIENT -Annotate_rows_log_event::Annotate_rows_log_event(THD *thd) +Annotate_rows_log_event::Annotate_rows_log_event(THD *thd, + uint16 cache_type_arg) : Log_event(thd, 0, true), m_save_thd_query_txt(0), m_save_thd_query_len(0) { m_query_txt= thd->query(); m_query_len= thd->query_length(); + cache_type= cache_type_arg; } #endif @@ -8015,7 +8442,7 @@ bool Annotate_rows_log_event::write_data_header(IO_CACHE *file) #ifndef MYSQL_CLIENT bool Annotate_rows_log_event::write_data_body(IO_CACHE *file) { - return my_b_safe_write(file, (uchar*) m_query_txt, m_query_len); + return wrapper_my_b_safe_write(file, (uchar*) m_query_txt, m_query_len); } #endif @@ -8590,11 +9017,11 @@ bool Table_map_log_event::write_data_header(IO_CACHE *file) { int4store(buf + 0, m_table_id); int2store(buf + 4, m_flags); - return (my_b_safe_write(file, buf, 6)); + return (wrapper_my_b_safe_write(file, buf, 6)); }); int6store(buf + TM_MAPID_OFFSET, (ulonglong)m_table_id); int2store(buf + TM_FLAGS_OFFSET, m_flags); - return (my_b_safe_write(file, buf, TABLE_MAP_HEADER_LEN)); + return (wrapper_my_b_safe_write(file, buf, TABLE_MAP_HEADER_LEN)); } bool Table_map_log_event::write_data_body(IO_CACHE *file) @@ -8618,15 +9045,15 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) uchar mbuf[sizeof(m_field_metadata_size)]; uchar *const mbuf_end= net_store_length(mbuf, m_field_metadata_size); - return (my_b_safe_write(file, dbuf, sizeof(dbuf)) || - my_b_safe_write(file, (const uchar*)m_dbnam, m_dblen+1) || - my_b_safe_write(file, tbuf, sizeof(tbuf)) || - my_b_safe_write(file, (const uchar*)m_tblnam, m_tbllen+1) || - my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) || - my_b_safe_write(file, m_coltype, m_colcnt) || - my_b_safe_write(file, mbuf, (size_t) (mbuf_end - mbuf)) || - my_b_safe_write(file, m_field_metadata, m_field_metadata_size), - my_b_safe_write(file, m_null_bits, (m_colcnt + 7) / 8)); + return (wrapper_my_b_safe_write(file, dbuf, sizeof(dbuf)) || + wrapper_my_b_safe_write(file, (const uchar*)m_dbnam, m_dblen+1) || + wrapper_my_b_safe_write(file, tbuf, sizeof(tbuf)) || + wrapper_my_b_safe_write(file, (const uchar*)m_tblnam, m_tbllen+1) || + wrapper_my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) || + wrapper_my_b_safe_write(file, m_coltype, m_colcnt) || + wrapper_my_b_safe_write(file, mbuf, (size_t) (mbuf_end - mbuf)) || + wrapper_my_b_safe_write(file, m_field_metadata, m_field_metadata_size), + wrapper_my_b_safe_write(file, m_null_bits, (m_colcnt + 7) / 8)); } #endif @@ -9966,13 +10393,25 @@ Incident_log_event::write_data_header(IO_CACHE *file) DBUG_PRINT("enter", ("m_incident: %d", m_incident)); uchar buf[sizeof(int16)]; int2store(buf, (int16) m_incident); - DBUG_RETURN(my_b_safe_write(file, buf, sizeof(buf))); +#ifndef MYSQL_CLIENT + DBUG_RETURN(wrapper_my_b_safe_write(file, buf, sizeof(buf))); +#else + DBUG_RETURN(my_b_safe_write(file, buf, sizeof(buf))); +#endif } bool Incident_log_event::write_data_body(IO_CACHE *file) { + uchar tmp[1]; DBUG_ENTER("Incident_log_event::write_data_body"); + tmp[0]= (uchar) m_message.length; + crc= my_checksum(crc, (uchar*) tmp, 1); + if (m_message.length > 0) + { + crc= my_checksum(crc, (uchar*) m_message.str, m_message.length); + // todo: report a bug on write_str accepts uint but treats it as uchar + } DBUG_RETURN(write_str(file, m_message.str, (uint) m_message.length)); } diff --git a/sql/log_event.h b/sql/log_event.h index 91a2ad9693c..53fc8f986b4 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -72,6 +72,7 @@ #define LOG_READ_MEM -5 #define LOG_READ_TRUNC -6 #define LOG_READ_TOO_LARGE -7 +#define LOG_READ_CHECKSUM_FAILURE -8 #define LOG_EVENT_OFFSET 4 @@ -525,6 +526,22 @@ struct sql_ex_info #endif #undef EXPECTED_OPTIONS /* You shouldn't use this one */ +enum enum_binlog_checksum_alg { + BINLOG_CHECKSUM_ALG_OFF= 0, // Events are without checksum though its generator + // is checksum-capable New Master (NM). + BINLOG_CHECKSUM_ALG_CRC32= 1, // CRC32 of zlib algorithm. + BINLOG_CHECKSUM_ALG_ENUM_END, // the cut line: valid alg range is [1, 0x7f]. + BINLOG_CHECKSUM_ALG_UNDEF= 255 // special value to tag undetermined yet checksum + // or events from checksum-unaware servers +}; + +#define CHECKSUM_CRC32_SIGNATURE_LEN 4 +/** + defined statically while there is just one alg implemented +*/ +#define BINLOG_CHECKSUM_LEN CHECKSUM_CRC32_SIGNATURE_LEN +#define BINLOG_CHECKSUM_ALG_DESC_LEN 1 /* 1 byte checksum alg descriptor */ + /** @enum Log_event_type @@ -923,6 +940,27 @@ public: uint16 flags; bool cache_stmt; + /* + The revid:alfranio.correia@sun.com-20091103190256-637o8qxlveikrt3i commit + ("WL#2687 WL#5072 BUG#40278 BUG#47175") in MySQL 5.5 changes the bool + cache_stmt into an enum cache_type. For the backport of WL#2540 binlog + event checksum, we need this event_type member to know if we are writing + directly to the log, or into a transaction cache. + + Until the cache_type stuff is merged, we temporarily partially backport + the cache_type member, only enough to be able to check if we are writing + directly to log or not. Once MySQL 5.5 is merged, this can be removed, and + replaced with the MySQL 5.5 code. + + Similarly, in MySQL 5.5 the decision on whether to write directly to log + or indirectly through cache is decided differently, and the + pre_55_writing_direct() (and all calls to it) are not needed and can be + removed once 5.5 is merged. + */ + enum enum_event_cache_type { EVENT_INVALID_CACHE, EVENT_STMT_CACHE, + EVENT_TRANSACTIONAL_CACHE, EVENT_NO_CACHE }; + uint16 cache_type; + void pre_55_writing_direct() { cache_type= EVENT_NO_CACHE; } /** A storage to cache the global system variable's value. @@ -930,6 +968,10 @@ public: */ ulong slave_exec_mode; + /** + Placeholder for event checksum while writing to binlog. + */ + ha_checksum crc; #ifndef MYSQL_CLIENT THD* thd; @@ -949,9 +991,10 @@ public: static Log_event* read_log_event(IO_CACHE* file, pthread_mutex_t* log_lock, const Format_description_log_event - *description_event); + *description_event, + my_bool crc_check); static int read_log_event(IO_CACHE* file, String* packet, - pthread_mutex_t* log_lock); + pthread_mutex_t* log_lock, uint8 checksum_alg_arg); /* init_show_field_list() prepares the column names and types for the output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG @@ -978,7 +1021,7 @@ public: /* avoid having to link mysqlbinlog against libpthread */ static Log_event* read_log_event(IO_CACHE* file, const Format_description_log_event - *description_event); + *description_event, my_bool crc_check); /* print*() functions are used by mysqlbinlog */ virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0; void print_timestamp(IO_CACHE* file, time_t *ts = 0); @@ -987,6 +1030,15 @@ public: void print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more); #endif + /* + The value is set by caller of FD constructor and + Log_event::write_header() for the rest. + In the FD case it's propagated into the last byte + of post_header_len[] at FD::write(). + On the slave side the value is assigned from post_header_len[last] + of the last seen FD event. + */ + uint8 checksum_alg; static void *operator new(size_t size) { @@ -1001,14 +1053,19 @@ public: /* Placement version of the above operators */ static void *operator new(size_t, void* ptr) { return ptr; } static void operator delete(void*, void*) { } + bool wrapper_my_b_safe_write(IO_CACHE* file, const uchar* buf, ulong data_length); #ifndef MYSQL_CLIENT bool write_header(IO_CACHE* file, ulong data_length); + bool write_footer(IO_CACHE* file); + my_bool need_checksum(); + virtual bool write(IO_CACHE* file) { - return (write_header(file, get_data_size()) || - write_data_header(file) || - write_data_body(file)); + return(write_header(file, get_data_size()) || + write_data_header(file) || + write_data_body(file) || + write_footer(file)); } virtual bool write_data_header(IO_CACHE* file) { return 0; } @@ -1058,7 +1115,7 @@ public: static Log_event* read_log_event(const char* buf, uint event_len, const char **error, const Format_description_log_event - *description_event); + *description_event, my_bool crc_check); /** Returns the human readable name of the given event type. */ @@ -2237,9 +2294,17 @@ public: */ uint8 common_header_len; uint8 number_of_event_types; - /* The list of post-headers' lengthes */ + /* + The list of post-headers' lengths followed + by the checksum alg decription byte + */ uint8 *post_header_len; - uchar server_version_split[3]; + struct master_version_split { + enum {KIND_MYSQL, KIND_MARIADB}; + int kind; + uchar ver[3]; + }; + master_version_split server_version_split; const uint8 *event_type_permutation; Format_description_log_event(uint8 binlog_ver, const char* server_ver=0); @@ -2271,7 +2336,7 @@ public: } void calc_server_version_split(); - + static bool is_version_before_checksum(master_version_split *version_split); protected: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) virtual int do_apply_event(Relay_log_info const *rli); @@ -2326,9 +2391,10 @@ public: uchar type; #ifndef MYSQL_CLIENT - Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) - :Log_event(thd_arg,0,0),val(val_arg),type(type_arg) - {} + Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg, + uint16 cache_type_arg) + :Log_event(thd_arg,0,0), val(val_arg), type(type_arg) + { cache_type= cache_type_arg; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ @@ -2402,9 +2468,10 @@ class Rand_log_event: public Log_event ulonglong seed2; #ifndef MYSQL_CLIENT - Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg) - :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg) - {} + Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg, + uint16 cache_type_arg) + :Log_event(thd_arg, 0, 0), seed1(seed1_arg), seed2(seed2_arg) + { cache_type= cache_type_arg; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ @@ -2448,7 +2515,8 @@ class Xid_log_event: public Log_event my_xid xid; #ifndef MYSQL_CLIENT - Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg,0,0), xid(x) {} + Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg, 0, 0), xid(x) + { cache_type= EVENT_NO_CACHE; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ @@ -2495,10 +2563,11 @@ public: #ifndef MYSQL_CLIENT User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg, char *val_arg, ulong val_len_arg, Item_result type_arg, - uint charset_number_arg) - :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg), - val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg) - { is_null= !val; } + uint charset_number_arg, + uint16 cache_type_arg) + :Log_event(thd_arg, 0, 0), name(name_arg), name_len(name_len_arg), val(val_arg), + val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg) + { is_null= !val; cache_type= cache_type_arg; } void pack_info(Protocol* protocol); #else void print(FILE* file, PRINT_EVENT_INFO* print_event_info); @@ -3010,7 +3079,7 @@ class Annotate_rows_log_event: public Log_event { public: #ifndef MYSQL_CLIENT - Annotate_rows_log_event(THD*); + Annotate_rows_log_event(THD*, uint16 cache_type_arg); #endif Annotate_rows_log_event(const char *buf, uint event_len, const Format_description_log_event*); @@ -4040,6 +4109,10 @@ bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos, const char **group_relay_log_name, ulonglong *relay_log_pos); +bool event_checksum_test(uchar *buf, ulong event_len, uint8 alg); +uint8 get_checksum_alg(const char* buf, ulong len); +extern TYPELIB binlog_checksum_typelib; + /** @} (end of group Replication) */ diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c18ade20d02..a549ec77c4a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1998,6 +1998,8 @@ extern ulong binlog_cache_size, open_files_limit; extern ulonglong max_binlog_cache_size; extern ulong max_binlog_size, max_relay_log_size; extern ulong opt_binlog_rows_event_max_size; +extern my_bool opt_master_verify_checksum; +extern my_bool opt_slave_sql_verify_checksum; extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size; extern ulong back_log; #endif /* MYSQL_SERVER */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9fd6d8c7022..272a11a4c81 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -560,6 +560,8 @@ my_bool opt_noacl; my_bool sp_automatic_privileges= 1; ulong opt_binlog_rows_event_max_size; +my_bool opt_master_verify_checksum= 0; +my_bool opt_slave_sql_verify_checksum= 1; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; TYPELIB binlog_format_typelib= { array_elements(binlog_format_names) - 1, "", @@ -4612,6 +4614,7 @@ int main(int argc, char **argv) #ifndef DBUG_OFF test_lc_time_sz(); + srand(time(NULL)); #endif /* @@ -6026,7 +6029,9 @@ enum options_mysqld OPT_SLOW_QUERY_LOG_FILE, OPT_IGNORE_BUILTIN_INNODB, OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, - OPT_DEFAULT_CHARACTER_SET_OLD + OPT_DEFAULT_CHARACTER_SET_OLD, + OPT_MASTER_VERIFY_CHECKSUM, + OPT_SLAVE_SQL_VERIFY_CHECKSUM }; @@ -6859,6 +6864,19 @@ thread is in the relay logs.", "not stop for operations that are idempotent. In STRICT mode, replication " "will stop on any unexpected difference between the master and the slave.", &slave_exec_mode_str, &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"master-verify-checksum", OPT_MASTER_VERIFY_CHECKSUM, + "Force checksum verification of logged events in binary log before " + "sending them to slaves or printing them in output of SHOW BINLOG EVENTS. " + "Disabled by default.", + &opt_master_verify_checksum, &opt_master_verify_checksum, + 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"slave-sql-verify-checksum", OPT_SLAVE_SQL_VERIFY_CHECKSUM, + "Force checksum verification of replication events after reading them " + "from relay log. Note: Events are always checksum-verified by slave on " + "receiving them from the network before writing them to the relay " + "log. Enabled by default.", + &opt_slave_sql_verify_checksum, &opt_slave_sql_verify_checksum, + 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, #endif {"slow-query-log", OPT_SLOW_LOG, "Enable/disable slow query log.", &opt_slow_log, diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 9b1b1f70784..99536b68cf6 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -244,7 +244,8 @@ static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg) for (;;) { Log_event* ev; - if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*) 0, 0))) + if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*) 0, 0, + opt_slave_sql_verify_checksum))) { if (log->error > 0) strmov(errmsg, "Binary log truncated in the middle of event"); @@ -418,7 +419,8 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, for (i = 0; i < 2; i++) { - if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0, 0))) + if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0, 0, + opt_slave_sql_verify_checksum))) { my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, "Error reading event in log '%s'", diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 47fc88c9a8a..eb5ee58e538 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -24,7 +24,8 @@ Master_info::Master_info() :Slave_reporting_capability("I/O"), - ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), inited(0), + ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), + checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF), inited(0), abort_slave(0),slave_running(0), slave_run_id(0) { diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index d63432545e5..5cac5284d9d 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -83,6 +83,12 @@ class Master_info : public Slave_reporting_capability Relay_log_info rli; uint port; uint connect_retry; + /* + to hold checksum alg in use until IO thread has received FD. + Initialized to novalue, then set to the queried from master + @@global.binlog_checksum and deactivated once FD has been received. + */ + uint8 checksum_alg_before_fd; #ifndef DBUG_OFF int events_till_disconnect; #endif diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index a2d0b1e4904..0886fd02004 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -175,6 +175,9 @@ a file name for --relay-log-index option", opt_relaylog_index_name); "use '--relay-log=%s' to avoid this problem.", ln); name_warning_sent= 1; } + + rli->relay_log.is_relay_log= TRUE; + /* note, that if open() fails, we'll still have index file open but a destructor will take care of that @@ -188,7 +191,6 @@ a file name for --relay-log-index option", opt_relaylog_index_name); sql_print_error("Failed in open_log() called from init_relay_log_info()"); DBUG_RETURN(1); } - rli->relay_log.is_relay_log= TRUE; } /* if file does not exist */ @@ -534,8 +536,9 @@ int init_relay_log_pos(Relay_log_info* rli,const char* log, Because of we have rli->data_lock and log_lock, we can safely read an event */ - if (!(ev=Log_event::read_log_event(rli->cur_log,0, - rli->relay_log.description_event_for_exec))) + if (!(ev= Log_event::read_log_event(rli->cur_log, 0, + rli->relay_log.description_event_for_exec, + opt_slave_sql_verify_checksum))) { DBUG_PRINT("info",("could not read event, rli->cur_log->error=%d", rli->cur_log->error)); diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 6058c473e9f..d4616723117 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -14,6 +14,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rpl_utility.h" + +#ifndef MYSQL_CLIENT #include "rpl_rli.h" /********************************************************************* @@ -224,3 +226,62 @@ table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table) return error; } + +#endif /* MYSQL_CLIENT */ + + +/** + @param even_buf point to the buffer containing serialized event + @param event_len length of the event accounting possible checksum alg + + @return TRUE if test fails + FALSE as success +*/ +bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg) +{ + bool res= FALSE; + uint16 flags= 0; // to store in FD's buffer flags orig value + + if (alg != BINLOG_CHECKSUM_ALG_OFF && alg != BINLOG_CHECKSUM_ALG_UNDEF) + { + ha_checksum incoming; + ha_checksum computed; + + if (event_buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) + { +#ifndef DBUG_OFF + int8 fd_alg= event_buf[event_len - BINLOG_CHECKSUM_LEN - + BINLOG_CHECKSUM_ALG_DESC_LEN]; +#endif + /* + FD event is checksummed and therefore verified w/o the binlog-in-use flag + */ + flags= uint2korr(event_buf + FLAGS_OFFSET); + if (flags & LOG_EVENT_BINLOG_IN_USE_F) + event_buf[FLAGS_OFFSET] &= ~LOG_EVENT_BINLOG_IN_USE_F; + /* + The only algorithm currently is CRC32. Zero indicates + the binlog file is checksum-free *except* the FD-event. + */ + DBUG_ASSERT(fd_alg == BINLOG_CHECKSUM_ALG_CRC32 || fd_alg == 0); + DBUG_ASSERT(alg == BINLOG_CHECKSUM_ALG_CRC32); + /* + Complile time guard to watch over the max number of alg + */ + compile_time_assert(BINLOG_CHECKSUM_ALG_ENUM_END <= 0x80); + } + incoming= uint4korr(event_buf + event_len - BINLOG_CHECKSUM_LEN); + computed= my_checksum(0L, NULL, 0); + /* checksum the event content but the checksum part itself */ + computed= my_checksum(computed, (const uchar*) event_buf, + event_len - BINLOG_CHECKSUM_LEN); + if (flags != 0) + { + /* restoring the orig value of flags of FD */ + DBUG_ASSERT(event_buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT); + event_buf[FLAGS_OFFSET]= flags; + } + res= !(computed == incoming); + } + return DBUG_EVALUATE_IF("simulate_checksum_test_failure", TRUE, res); +} diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index a872fa1f1e9..aee6927e127 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6249,3 +6249,7 @@ ER_UNKNOWN_OPTION eng "Unknown option '%-.64s'" ER_BAD_OPTION_VALUE eng "Incorrect value '%-.64s' for option '%-.64s'" +ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE + eng "Replication event checksum verification failed while reading from network." +ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE + eng "Replication event checksum verification failed while reading from a log file." diff --git a/sql/slave.cc b/sql/slave.cc index 63b7ce715c9..b042d463b1e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -937,6 +937,48 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) } /* + FD_q's (A) is set initially from RL's (A): FD_q.(A) := RL.(A). + It's necessary to adjust FD_q.(A) at this point because in the following + course FD_q is going to be dumped to RL. + Generally FD_q is derived from a received FD_m (roughly FD_q := FD_m) + in queue_event and the master's (A) is installed. + At one step with the assignment the Relay-Log's checksum alg is set to + a new value: RL.(A) := FD_q.(A). If the slave service is stopped + the last time assigned RL.(A) will be passed over to the restarting + service (to the current execution point). + RL.A is a "codec" to verify checksum in queue_event() almost all the time + the first fake Rotate event. + Starting from this point IO thread will executes the following checksum + warmup sequence of actions: + + FD_q.A := RL.A, + A_m^0 := master.@@global.binlog_checksum, + {queue_event(R_f): verifies(R_f, A_m^0)}, + {queue_event(FD_m): verifies(FD_m, FD_m.A), dump(FD_q), rotate(RL), + FD_q := FD_m, RL.A := FD_q.A)} + + See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg + docs lines (binlog.h). + In above A_m^0 - the value of master's + @@binlog_checksum determined in the upcoming handshake (stored in + mi->checksum_alg_before_fd). + + + After the warm-up sequence IO gets to "normal" checksum verification mode + to use RL.A in + + {queue_event(E_m): verifies(E_m, RL.A)} + + until it has received a new FD_m. + */ + mi->rli.relay_log.description_event_for_queue->checksum_alg= + mi->rli.relay_log.relay_log_checksum_alg; + + DBUG_ASSERT(mi->rli.relay_log.description_event_for_queue->checksum_alg != + BINLOG_CHECKSUM_ALG_UNDEF); + DBUG_ASSERT(mi->rli.relay_log.relay_log_checksum_alg != + BINLOG_CHECKSUM_ALG_UNDEF); + /* Compare the master and slave's clock. Do not die if master's clock is unavailable (very old master not supporting UNIX_TIMESTAMP()?). */ @@ -1175,6 +1217,103 @@ when it try to get the value of TIME_ZONE global variable from master."; } } + /* + Querying if master is capable to checksum and notifying it about own + CRC-awareness. The master's side instant value of @@global.binlog_checksum + is stored in the dump thread's uservar area as well as cached locally + to become known in consensus by master and slave. + */ + DBUG_EXECUTE_IF("simulate_slave_unaware_checksum", + mi->checksum_alg_before_fd= BINLOG_CHECKSUM_ALG_OFF; + goto past_checksum;); + { + int rc; + const char query[]= "SET @master_binlog_checksum= @@global.binlog_checksum"; + master_res= NULL; + mi->checksum_alg_before_fd= BINLOG_CHECKSUM_ALG_UNDEF; //initially undefined + /* + @c checksum_alg_before_fd is queried from master in this block. + If master is old checksum-unaware the value stays undefined. + Once the first FD will be received its alg descriptor will replace + the being queried one. + */ + rc= mysql_real_query(mysql, query, strlen(query)); + if (rc != 0) + { + if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; + + if (mysql_errno(mysql) == ER_UNKNOWN_SYSTEM_VARIABLE) + { + // this is tolerable as OM -> NS is supported + mi->report(WARNING_LEVEL, mysql_errno(mysql), + "Notifying master by %s failed with " + "error: %s", query, mysql_error(mysql)); + } + else + { + if (is_network_error(mysql_errno(mysql))) + { + mi->report(WARNING_LEVEL, mysql_errno(mysql), + "Notifying master by %s failed with " + "error: %s", query, mysql_error(mysql)); + mysql_free_result(mysql_store_result(mysql)); + goto network_err; + } + else + { + errmsg= "The slave I/O thread stops because a fatal error is encountered " + "when it tried to SET @master_binlog_checksum on master."; + err_code= ER_SLAVE_FATAL_ERROR; + sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); + mysql_free_result(mysql_store_result(mysql)); + goto err; + } + } + } + else + { + mysql_free_result(mysql_store_result(mysql)); + if (!mysql_real_query(mysql, + STRING_WITH_LEN("SELECT @master_binlog_checksum")) && + (master_res= mysql_store_result(mysql)) && + (master_row= mysql_fetch_row(master_res)) && + (master_row[0] != NULL)) + { + mi->checksum_alg_before_fd= (uint8) + find_type(master_row[0], &binlog_checksum_typelib, 1) - 1; + // valid outcome is either of + DBUG_ASSERT(mi->checksum_alg_before_fd == BINLOG_CHECKSUM_ALG_OFF || + mi->checksum_alg_before_fd == BINLOG_CHECKSUM_ALG_CRC32); + } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; + else if (is_network_error(mysql_errno(mysql))) + { + mi->report(WARNING_LEVEL, mysql_errno(mysql), + "Get master BINLOG_CHECKSUM failed with error: %s", mysql_error(mysql)); + goto network_err; + } + else + { + errmsg= "The slave I/O thread stops because a fatal error is encountered " + "when it tried to SELECT @master_binlog_checksum."; + err_code= ER_SLAVE_FATAL_ERROR; + sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); + mysql_free_result(mysql_store_result(mysql)); + goto err; + } + } + if (master_res) + { + mysql_free_result(master_res); + master_res= NULL; + } + } + +#ifndef DBUG_OFF +past_checksum: +#endif err: if (errmsg) { @@ -1191,6 +1330,11 @@ network_err: if (master_res) mysql_free_result(master_res); DBUG_RETURN(2); + +slave_killed_err: + if (master_res) + mysql_free_result(master_res); + DBUG_RETURN(2); } /* @@ -3384,10 +3528,15 @@ static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) */ if (mi->rli.relay_log.description_event_for_queue->binlog_version >= 4) { + DBUG_ASSERT(mi->rli.relay_log.description_event_for_queue->checksum_alg == + mi->rli.relay_log.relay_log_checksum_alg); + delete mi->rli.relay_log.description_event_for_queue; /* start from format 3 (MySQL 4.0) again */ mi->rli.relay_log.description_event_for_queue= new Format_description_log_event(3); + mi->rli.relay_log.description_event_for_queue->checksum_alg= + mi->rli.relay_log.relay_log_checksum_alg; } /* Rotate the relay log makes binlog format detection easier (at next slave @@ -3440,8 +3589,9 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, Append_block/Exec_load (the SQL thread needs the data, as that thread is not connected to the master). */ - Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg, - mi->rli.relay_log.description_event_for_queue); + Log_event *ev= + Log_event::read_log_event(buf, event_len, &errmsg, + mi->rli.relay_log.description_event_for_queue, 0); if (unlikely(!ev)) { sql_print_error("Read invalid event from master: '%s',\ @@ -3528,8 +3678,9 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, DBUG_ENTER("queue_binlog_ver_3_event"); /* read_log_event() will adjust log_pos to be end_log_pos */ - Log_event *ev = Log_event::read_log_event(buf,event_len, &errmsg, - mi->rli.relay_log.description_event_for_queue); + Log_event *ev= + Log_event::read_log_event(buf,event_len, &errmsg, + mi->rli.relay_log.description_event_for_queue, 0); if (unlikely(!ev)) { sql_print_error("Read invalid event from master: '%s',\ @@ -3555,6 +3706,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, inc_pos= event_len; break; } + if (unlikely(rli->relay_log.append(ev))) { delete ev; @@ -3616,7 +3768,68 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) ulong inc_pos; Relay_log_info *rli= &mi->rli; pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); + bool unlock_data_lock= TRUE; + /* + FD_q must have been prepared for the first R_a event + inside get_master_version_and_clock() + Show-up of FD:s affects checksum_alg at once because + that changes FD_queue. + */ + uint8 checksum_alg= mi->checksum_alg_before_fd != BINLOG_CHECKSUM_ALG_UNDEF ? + mi->checksum_alg_before_fd : + mi->rli.relay_log.relay_log_checksum_alg; + + char *save_buf= NULL; // needed for checksumming the fake Rotate event + char rot_buf[LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN + FN_REFLEN]; + + DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_OFF || + checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF || + checksum_alg == BINLOG_CHECKSUM_ALG_CRC32); + DBUG_ENTER("queue_event"); + /* + FD_queue checksum alg description does not apply in a case of + FD itself. The one carries both parts of the checksum data. + */ + if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) + { + checksum_alg= get_checksum_alg(buf, event_len); + } + else if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3) + { + // checksum behaviour is similar to the pre-checksum FD handling + mi->checksum_alg_before_fd= BINLOG_CHECKSUM_ALG_UNDEF; + mi->rli.relay_log.description_event_for_queue->checksum_alg= + mi->rli.relay_log.relay_log_checksum_alg= checksum_alg= + BINLOG_CHECKSUM_ALG_OFF; + } + + // does not hold always because of old binlog can work with NM + // DBUG_ASSERT(checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF); + + // should hold unless manipulations with RL. Tests that do that + // will have to refine the clause. + DBUG_ASSERT(mi->rli.relay_log.relay_log_checksum_alg != + BINLOG_CHECKSUM_ALG_UNDEF); + + // Emulate the network corruption + DBUG_EXECUTE_IF("corrupt_queue_event", + if (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT) + { + char *debug_event_buf_c = (char*) buf; + int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN); + debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos]; + DBUG_PRINT("info", ("Corrupt the event at queue_event: byte on position %d", debug_cor_pos)); + DBUG_SET("-d,corrupt_queue_event"); + } + ); + + if (event_checksum_test((uchar *) buf, event_len, checksum_alg)) + { + error= ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE; + unlock_data_lock= FALSE; + goto err; + } LINT_INIT(inc_pos); @@ -3644,12 +3857,67 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) goto err; case ROTATE_EVENT: { - Rotate_log_event rev(buf,event_len,mi->rli.relay_log.description_event_for_queue); - if (unlikely(process_io_rotate(mi,&rev))) + Rotate_log_event rev(buf, checksum_alg != BINLOG_CHECKSUM_ALG_OFF ? + event_len - BINLOG_CHECKSUM_LEN : event_len, + mi->rli.relay_log.description_event_for_queue); + + if (unlikely(process_io_rotate(mi, &rev))) { error= 1; goto err; } + /* + Checksum special cases for the fake Rotate (R_f) event caused by the protocol + of events generation and serialization in RL where Rotate of master is + queued right next to FD of slave. + Since it's only FD that carries the alg desc of FD_s has to apply to R_m. + Two special rules apply only to the first R_f which comes in before any FD_m. + The 2nd R_f should be compatible with the FD_s that must have taken over + the last seen FD_m's (A). + + RSC_1: If OM \and fake Rotate \and slave is configured to + to compute checksum for its first FD event for RL + the fake Rotate gets checksummed here. + */ + if (uint4korr(&buf[0]) == 0 && checksum_alg == BINLOG_CHECKSUM_ALG_OFF && + mi->rli.relay_log.relay_log_checksum_alg != BINLOG_CHECKSUM_ALG_OFF) + { + ha_checksum rot_crc= my_checksum(0L, NULL, 0); + event_len += BINLOG_CHECKSUM_LEN; + memcpy(rot_buf, buf, event_len - BINLOG_CHECKSUM_LEN); + int4store(&rot_buf[EVENT_LEN_OFFSET], + uint4korr(&rot_buf[EVENT_LEN_OFFSET]) + BINLOG_CHECKSUM_LEN); + rot_crc= my_checksum(rot_crc, (const uchar *) rot_buf, + event_len - BINLOG_CHECKSUM_LEN); + int4store(&rot_buf[event_len - BINLOG_CHECKSUM_LEN], rot_crc); + DBUG_ASSERT(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET])); + DBUG_ASSERT(mi->rli.relay_log.description_event_for_queue->checksum_alg == + mi->rli.relay_log.relay_log_checksum_alg); + /* the first one */ + DBUG_ASSERT(mi->checksum_alg_before_fd != BINLOG_CHECKSUM_ALG_UNDEF); + save_buf= (char *) buf; + buf= rot_buf; + } + else + /* + RSC_2: If NM \and fake Rotate \and slave does not compute checksum + the fake Rotate's checksum is stripped off before relay-logging. + */ + if (uint4korr(&buf[0]) == 0 && checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + mi->rli.relay_log.relay_log_checksum_alg == BINLOG_CHECKSUM_ALG_OFF) + { + event_len -= BINLOG_CHECKSUM_LEN; + memcpy(rot_buf, buf, event_len); + int4store(&rot_buf[EVENT_LEN_OFFSET], + uint4korr(&rot_buf[EVENT_LEN_OFFSET]) - BINLOG_CHECKSUM_LEN); + DBUG_ASSERT(event_len == uint4korr(&rot_buf[EVENT_LEN_OFFSET])); + DBUG_ASSERT(mi->rli.relay_log.description_event_for_queue->checksum_alg == + mi->rli.relay_log.relay_log_checksum_alg); + /* the first one */ + DBUG_ASSERT(mi->checksum_alg_before_fd != BINLOG_CHECKSUM_ALG_UNDEF); + save_buf= (char *) buf; + buf= rot_buf; + } /* Now the I/O thread has just changed its mi->master_log_name, so incrementing mi->master_log_pos is nonsense. @@ -3670,15 +3938,24 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) */ Format_description_log_event* tmp; const char* errmsg; + // mark it as undefined that is irrelevant anymore + mi->checksum_alg_before_fd= BINLOG_CHECKSUM_ALG_UNDEF; if (!(tmp= (Format_description_log_event*) Log_event::read_log_event(buf, event_len, &errmsg, - mi->rli.relay_log.description_event_for_queue))) + mi->rli.relay_log.description_event_for_queue, + 1))) { error= 2; goto err; } delete mi->rli.relay_log.description_event_for_queue; mi->rli.relay_log.description_event_for_queue= tmp; + if (tmp->checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF) + tmp->checksum_alg= BINLOG_CHECKSUM_ALG_OFF; + + /* installing new value of checksum Alg for relay log */ + mi->rli.relay_log.relay_log_checksum_alg= tmp->checksum_alg; + /* Though this does some conversion to the slave's format, this will preserve the master's binlog format version, and number of event types. @@ -3755,12 +4032,15 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) else error= 3; rli->ign_master_log_name_end[0]= 0; // last event is not ignored + if (save_buf != NULL) + buf= save_buf; } pthread_mutex_unlock(log_lock); err: - pthread_mutex_unlock(&mi->data_lock); + if (unlock_data_lock) + pthread_mutex_unlock(&mi->data_lock); DBUG_PRINT("info", ("error: %d", error)); DBUG_RETURN(error); } @@ -4150,8 +4430,9 @@ static Log_event* next_event(Relay_log_info* rli) But if the relay log is created by new_file(): then the solution is: MYSQL_BIN_LOG::open() will write the buffered description event. */ - if ((ev=Log_event::read_log_event(cur_log,0, - rli->relay_log.description_event_for_exec))) + if ((ev= Log_event::read_log_event(cur_log,0, + rli->relay_log.description_event_for_exec, + opt_slave_sql_verify_checksum))) { DBUG_ASSERT(thd==rli->sql_thd); @@ -4552,9 +4833,9 @@ bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, {37426, { 5, 1, 0 }, { 5, 1, 26 } }, }; const uchar *master_ver= - rli->relay_log.description_event_for_exec->server_version_split; + rli->relay_log.description_event_for_exec->server_version_split.ver; - DBUG_ASSERT(sizeof(rli->relay_log.description_event_for_exec->server_version_split) == 3); + DBUG_ASSERT(sizeof(rli->relay_log.description_event_for_exec->server_version_split.ver) == 3); for (uint i= 0; i < sizeof(versions_for_all_bugs)/sizeof(*versions_for_all_bugs);i++) diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index a59cd631fef..93ade4ffe4e 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -186,7 +186,8 @@ void mysql_client_binlog_statement(THD* thd) } ev= Log_event::read_log_event(bufptr, event_len, &error, - rli->relay_log.description_event_for_exec); + rli->relay_log.description_event_for_exec, + 0); DBUG_PRINT("info",("binlog base64 err=%s", error)); if (!ev) diff --git a/sql/sql_class.h b/sql/sql_class.h index 2b5c3048534..e38784c472a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -118,7 +118,7 @@ typedef struct st_user_var_events #define RP_LOCK_LOG_IS_ALREADY_LOCKED 1 #define RP_FORCE_ROTATE 2 - +#define RP_BINLOG_CHECKSUM_ALG_CHANGE 4 /* The COPY_INFO structure is used by INSERT/REPLACE code. The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 596f0f5c1e6..8b6ba0e44e5 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -28,6 +28,9 @@ my_bool opt_sporadic_binlog_dump_fail = 0; static int binlog_dump_count = 0; #endif +extern TYPELIB binlog_checksum_typelib; + + /* fake_rotate_event() builds a fake (=which does not exist physically in any binlog) Rotate event, which contains the name of the binlog we are going to @@ -47,10 +50,21 @@ static int binlog_dump_count = 0; */ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, - ulonglong position, const char** errmsg) + ulonglong position, const char** errmsg, + uint8 checksum_alg_arg) { DBUG_ENTER("fake_rotate_event"); char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN+100]; + + /* + this Rotate is to be sent with checksum if and only if + slave's get_master_version_and_clock time handshake value + of master's @@global.binlog_checksum was TRUE + */ + + my_bool do_checksum= checksum_alg_arg != BINLOG_CHECKSUM_ALG_OFF && + checksum_alg_arg != BINLOG_CHECKSUM_ALG_UNDEF; + /* 'when' (the timestamp) is set to 0 so that slave could distinguish between real and fake Rotate events (if necessary) @@ -60,7 +74,8 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, char* p = log_file_name+dirname_length(log_file_name); uint ident_len = (uint) strlen(p); - ulong event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN; + ulong event_len = ident_len + LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN + + (do_checksum ? BINLOG_CHECKSUM_LEN : 0); int4store(header + SERVER_ID_OFFSET, server_id); int4store(header + EVENT_LEN_OFFSET, event_len); int2store(header + FLAGS_OFFSET, LOG_EVENT_ARTIFICIAL_F); @@ -71,7 +86,19 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, packet->append(header, sizeof(header)); int8store(buf+R_POS_OFFSET,position); packet->append(buf, ROTATE_HEADER_LEN); - packet->append(p,ident_len); + packet->append(p, ident_len); + + if (do_checksum) + { + char b[BINLOG_CHECKSUM_LEN]; + ha_checksum crc= my_checksum(0L, NULL, 0); + crc= my_checksum(crc, (uchar*)header, sizeof(header)); + crc= my_checksum(crc, (uchar*)buf, ROTATE_HEADER_LEN); + crc= my_checksum(crc, (uchar*)p, ident_len); + int4store(b, crc); + packet->append(b, sizeof(b)); + } + if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) { *errmsg = "failed on my_net_write()"; @@ -153,6 +180,86 @@ static int send_file(THD *thd) } +/** + Internal to mysql_binlog_send() routine that recalculates checksum for + a FD event (asserted) that needs additional arranment prior sending to slave. +*/ +inline void fix_checksum(String *packet, ulong ev_offset) +{ + /* recalculate the crc for this event */ + uint data_len = uint4korr(packet->ptr() + ev_offset + EVENT_LEN_OFFSET); + ha_checksum crc= my_checksum(0L, NULL, 0); + DBUG_ASSERT(data_len == + LOG_EVENT_MINIMAL_HEADER_LEN + FORMAT_DESCRIPTION_HEADER_LEN + + BINLOG_CHECKSUM_ALG_DESC_LEN + BINLOG_CHECKSUM_LEN); + crc= my_checksum(crc, (uchar *)packet->ptr() + ev_offset, data_len - + BINLOG_CHECKSUM_LEN); + int4store(packet->ptr() + ev_offset + data_len - BINLOG_CHECKSUM_LEN, crc); +} + + +static user_var_entry * get_binlog_checksum_uservar(THD * thd) +{ + LEX_STRING name= { C_STRING_WITH_LEN("master_binlog_checksum")}; + user_var_entry *entry= + (user_var_entry*) my_hash_search(&thd->user_vars, (uchar*) name.str, + name.length); + return entry; +} + +/** + Function for calling in mysql_binlog_send + to check if slave initiated checksum-handshake. + + @param[in] thd THD to access a user variable + + @return TRUE if handshake took place, FALSE otherwise +*/ + +static bool is_slave_checksum_aware(THD * thd) +{ + DBUG_ENTER("is_slave_checksum_aware"); + user_var_entry *entry= get_binlog_checksum_uservar(thd); + DBUG_RETURN(entry? true : false); +} + +/** + Function for calling in mysql_binlog_send + to get the value of @@binlog_checksum of the master at + time of checksum-handshake. + + The value tells the master whether to compute or not, and the slave + to verify or not the first artificial Rotate event's checksum. + + @param[in] thd THD to access a user variable + + @return value of @@binlog_checksum alg according to + @c enum enum_binlog_checksum_alg +*/ + +static uint8 get_binlog_checksum_value_at_connect(THD * thd) +{ + uint8 ret; + + DBUG_ENTER("get_binlog_checksum_value_at_connect"); + user_var_entry *entry= get_binlog_checksum_uservar(thd); + if (!entry) + { + ret= BINLOG_CHECKSUM_ALG_UNDEF; + } + else + { + DBUG_ASSERT(entry->type == STRING_RESULT); + String str; + uint dummy_errors; + str.copy(entry->value, entry->length, &my_charset_bin, &my_charset_bin, + &dummy_errors); + ret= (uint8) find_type ((char*) str.ptr(), &binlog_checksum_typelib, 1) - 1; + DBUG_ASSERT(ret <= BINLOG_CHECKSUM_ALG_CRC32); // while it's just on CRC32 alg + } + DBUG_RETURN(ret); +} + /* Adjust the position pointer in the binary log file for all running slaves @@ -327,6 +434,9 @@ Increase max_allowed_packet on master"; case LOG_READ_TRUNC: *errmsg = "binlog truncated in the middle of event"; break; + case LOG_READ_CHECKSUM_FAILURE: + *errmsg = "event read from binlog did not pass crc check"; + break; default: *errmsg = "unknown error reading log event on the master"; break; @@ -353,6 +463,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, NET* net = &thd->net; pthread_mutex_t *log_lock; bool binlog_can_be_corrupted= FALSE; + uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF; + #ifndef DBUG_OFF int left_events = max_binlog_dump_events; #endif @@ -450,7 +562,8 @@ impossible position"; given that we want minimum modification of 4.0, we send the normal and fake Rotates. */ - if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg)) + if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg, + get_binlog_checksum_value_at_connect(current_thd))) { /* This error code is not perfect, as fake_rotate_event() does not @@ -480,8 +593,8 @@ impossible position"; Try to find a Format_description_log_event at the beginning of the binlog */ - if (!(error = Log_event::read_log_event(&log, packet, log_lock))) - { + if (!(error = Log_event::read_log_event(&log, packet, log_lock, 0))) + { /* The packet has offsets equal to the normal offsets in a binlog event +1 (the first character is \0). @@ -491,6 +604,23 @@ impossible position"; (*packet)[EVENT_TYPE_OFFSET+1])); if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT) { + current_checksum_alg= get_checksum_alg(packet->ptr() + 1, + packet->length() - 1); + DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF || + current_checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF || + current_checksum_alg == BINLOG_CHECKSUM_ALG_CRC32); + if (!is_slave_checksum_aware(thd) && + current_checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + current_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; + errmsg= "Slave can not handle replication events with the checksum " + "that master is configured to log"; + sql_print_warning("Master is configured to log replication events " + "with checksum, but will not send such events to " + "slaves that cannot process them"); + goto err; + } binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] & LOG_EVENT_BINLOG_IN_USE_F); (*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F; @@ -506,6 +636,12 @@ impossible position"; */ int4store((char*) packet->ptr()+LOG_EVENT_MINIMAL_HEADER_LEN+ ST_CREATED_OFFSET+1, (ulong) 0); + + /* fix the checksum due to latest changes in header */ + if (current_checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + current_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + fix_checksum(packet, 1); + /* send it */ if (my_net_write(net, (uchar*) packet->ptr(), packet->length())) { @@ -544,7 +680,8 @@ impossible position"; while (!net->error && net->vio != 0 && !thd->killed) { - while (!(error = Log_event::read_log_event(&log, packet, log_lock))) + while (!(error = Log_event::read_log_event(&log, packet, log_lock, + current_checksum_alg))) { #ifndef DBUG_OFF if (max_binlog_dump_events && !left_events--) @@ -558,6 +695,23 @@ impossible position"; if ((uchar)(*packet)[EVENT_TYPE_OFFSET+1] == FORMAT_DESCRIPTION_EVENT) { + current_checksum_alg= get_checksum_alg(packet->ptr() + 1, + packet->length() - 1); + DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF || + current_checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF || + current_checksum_alg == BINLOG_CHECKSUM_ALG_CRC32); + if (!is_slave_checksum_aware(thd) && + current_checksum_alg != BINLOG_CHECKSUM_ALG_OFF && + current_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) + { + my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; + errmsg= "Slave can not handle replication events with the checksum " + "that master is configured to log"; + sql_print_warning("Master is configured to log replication events " + "with checksum, but will not send such events to " + "slaves that cannot process them"); + goto err; + } binlog_can_be_corrupted= test((*packet)[FLAGS_OFFSET+1] & LOG_EVENT_BINLOG_IN_USE_F); (*packet)[FLAGS_OFFSET+1] &= ~LOG_EVENT_BINLOG_IN_USE_F; @@ -594,7 +748,8 @@ impossible position"; here we were reading binlog that was not closed properly (as a result of a crash ?). treat any corruption as EOF */ - if (binlog_can_be_corrupted && error != LOG_READ_MEM) + if (binlog_can_be_corrupted && + (error != LOG_READ_MEM && error != LOG_READ_CHECKSUM_FAILURE)) error=LOG_READ_EOF; /* TODO: now that we are logging the offset, check to make sure @@ -649,7 +804,8 @@ impossible position"; */ pthread_mutex_lock(log_lock); - switch (error= Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0)) { + switch (error= Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0, + current_checksum_alg)) { case 0: /* we read successfully, so we'll need to send it to the slave */ pthread_mutex_unlock(log_lock); @@ -750,7 +906,7 @@ impossible position"; */ if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 || fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE, - &errmsg)) + &errmsg, current_checksum_alg)) { my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; goto err; @@ -1499,7 +1655,8 @@ bool mysql_show_binlog_events(THD* thd) This code will fail on a mixed relay log (one which has Format_desc then Rotate then Format_desc). */ - ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event); + ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event, + opt_master_verify_checksum); if (ev) { if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) @@ -1521,8 +1678,12 @@ bool mysql_show_binlog_events(THD* thd) for (event_count = 0; (ev = Log_event::read_log_event(&log,(pthread_mutex_t*) 0, - description_event)); ) + description_event, + opt_master_verify_checksum)); ) { + if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) + description_event->checksum_alg= ev->checksum_alg; + if (event_count >= limit_start && ev->net_send(protocol, linfo.log_file_name, pos)) { @@ -1815,6 +1976,12 @@ static sys_var_long_ptr sys_slave_trans_retries(&vars, "slave_transaction_retrie &slave_trans_retries); static sys_var_sync_binlog_period sys_sync_binlog_period(&vars, "sync_binlog", &sync_binlog_period); static sys_var_slave_skip_counter sys_slave_skip_counter(&vars, "sql_slave_skip_counter"); +static sys_var_bool_ptr sys_master_verify_checksum(&vars, + "master_verify_checksum", + &opt_master_verify_checksum); +static sys_var_bool_ptr sys_slave_sql_verify_checksum(&vars, + "slave_sql_verify_checksum", + &opt_slave_sql_verify_checksum); bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) |