# # BUG#42749: infinite loop writing to row based binlog - processlist shows # "freeing items" # # # WHY # === # # This bug would make table map event to report data_written one # byte less than what would actually be written in its body. This # would cause one byte shorter event end_log_pos. The ultimate # impact was that it would make fixing the position in # MYSQL_BIN_LOG::write_cache bogus or end up in an infinite loop. # # HOW # === # # Checking that the patch fixes the problem is done as follows: # # i) one table with m_field_metadata sized at 290 # ii) an insert is performed; # iii) the logs are flushed; # iv) mysqlbinlog is used to check if it succeeds. # # In step iv), before the bug was fixed, the test case would fail # with mysqlbinlog reporting that it was unable to succeed in # reading the event. -- source include/master-slave.inc -- source include/have_innodb.inc -- source include/have_binlog_format_row.inc -- disable_warnings DROP TABLE IF EXISTS `t1`; -- enable_warnings -- echo ### TABLE with field_metadata_size == 290 CREATE TABLE `t1` ( `c1` int(11) NOT NULL AUTO_INCREMENT, `c2` varchar(30) NOT NULL, `c3` varchar(30) DEFAULT NULL, `c4` varchar(30) DEFAULT NULL, `c5` varchar(30) DEFAULT NULL, `c6` varchar(30) DEFAULT NULL, `c7` varchar(30) DEFAULT NULL, `c8` varchar(30) DEFAULT NULL, `c9` varchar(30) DEFAULT NULL, `c10` varchar(30) DEFAULT NULL, `c11` varchar(30) DEFAULT NULL, `c12` varchar(30) DEFAULT NULL, `c13` varchar(30) DEFAULT NULL, `c14` varchar(30) DEFAULT NULL, `c15` varchar(30) DEFAULT NULL, `c16` varchar(30) DEFAULT NULL, `c17` varchar(30) DEFAULT NULL, `c18` varchar(30) DEFAULT NULL, `c19` varchar(30) DEFAULT NULL, `c20` varchar(30) DEFAULT NULL, `c21` varchar(30) DEFAULT NULL, `c22` varchar(30) DEFAULT NULL, `c23` varchar(30) DEFAULT NULL, `c24` varchar(30) DEFAULT NULL, `c25` varchar(30) DEFAULT NULL, `c26` varchar(30) DEFAULT NULL, `c27` varchar(30) DEFAULT NULL, `c28` varchar(30) DEFAULT NULL, `c29` varchar(30) DEFAULT NULL, `c30` varchar(30) DEFAULT NULL, `c31` varchar(30) DEFAULT NULL, `c32` varchar(30) DEFAULT NULL, `c33` varchar(30) DEFAULT NULL, `c34` varchar(30) DEFAULT NULL, `c35` varchar(30) DEFAULT NULL, `c36` varchar(30) DEFAULT NULL, `c37` varchar(30) DEFAULT NULL, `c38` varchar(30) DEFAULT NULL, `c39` varchar(30) DEFAULT NULL, `c40` varchar(30) DEFAULT NULL, `c41` varchar(30) DEFAULT NULL, `c42` varchar(30) DEFAULT NULL, `c43` varchar(30) DEFAULT NULL, `c44` varchar(30) DEFAULT NULL, `c45` varchar(30) DEFAULT NULL, `c46` varchar(30) DEFAULT NULL, `c47` varchar(30) DEFAULT NULL, `c48` varchar(30) DEFAULT NULL, `c49` varchar(30) DEFAULT NULL, `c50` varchar(30) DEFAULT NULL, `c51` varchar(30) DEFAULT NULL, `c52` varchar(30) DEFAULT NULL, `c53` varchar(30) DEFAULT NULL, `c54` varchar(30) DEFAULT NULL, `c55` varchar(30) DEFAULT NULL, `c56` varchar(30) DEFAULT NULL, `c57` varchar(30) DEFAULT NULL, `c58` varchar(30) DEFAULT NULL, `c59` varchar(30) DEFAULT NULL, `c60` varchar(30) DEFAULT NULL, `c61` varchar(30) DEFAULT NULL, `c62` varchar(30) DEFAULT NULL, `c63` varchar(30) DEFAULT NULL, `c64` varchar(30) DEFAULT NULL, `c65` varchar(30) DEFAULT NULL, `c66` varchar(30) DEFAULT NULL, `c67` varchar(30) DEFAULT NULL, `c68` varchar(30) DEFAULT NULL, `c69` varchar(30) DEFAULT NULL, `c70` varchar(30) DEFAULT NULL, `c71` varchar(30) DEFAULT NULL, `c72` varchar(30) DEFAULT NULL, `c73` varchar(30) DEFAULT NULL, `c74` varchar(30) DEFAULT NULL, `c75` varchar(30) DEFAULT NULL, `c76` varchar(30) DEFAULT NULL, `c77` varchar(30) DEFAULT NULL, `c78` varchar(30) DEFAULT NULL, `c79` varchar(30) DEFAULT NULL, `c80` varchar(30) DEFAULT NULL, `c81` varchar(30) DEFAULT NULL, `c82` varchar(30) DEFAULT NULL, `c83` varchar(30) DEFAULT NULL, `c84` varchar(30) DEFAULT NULL, `c85` varchar(30) DEFAULT NULL, `c86` varchar(30) DEFAULT NULL, `c87` varchar(30) DEFAULT NULL, `c88` varchar(30) DEFAULT NULL, `c89` varchar(30) DEFAULT NULL, `c90` varchar(30) DEFAULT NULL, `c91` varchar(30) DEFAULT NULL, `c92` varchar(30) DEFAULT NULL, `c93` varchar(30) DEFAULT NULL, `c94` varchar(30) DEFAULT NULL, `c95` varchar(30) DEFAULT NULL, `c96` varchar(30) DEFAULT NULL, `c97` varchar(30) DEFAULT NULL, `c98` varchar(30) DEFAULT NULL, `c99` varchar(30) DEFAULT NULL, `c100` varchar(30) DEFAULT NULL, `c101` varchar(30) DEFAULT NULL, `c102` varchar(30) DEFAULT NULL, `c103` varchar(30) DEFAULT NULL, `c104` varchar(30) DEFAULT NULL, `c105` varchar(30) DEFAULT NULL, `c106` varchar(30) DEFAULT NULL, `c107` varchar(30) DEFAULT NULL, `c108` varchar(30) DEFAULT NULL, `c109` varchar(30) DEFAULT NULL, `c110` varchar(30) DEFAULT NULL, `c111` varchar(30) DEFAULT NULL, `c112` varchar(30) DEFAULT NULL, `c113` varchar(30) DEFAULT NULL, `c114` varchar(30) DEFAULT NULL, `c115` varchar(30) DEFAULT NULL, `c116` varchar(30) DEFAULT NULL, `c117` varchar(30) DEFAULT NULL, `c118` varchar(30) DEFAULT NULL, `c119` varchar(30) DEFAULT NULL, `c120` varchar(30) DEFAULT NULL, `c121` varchar(30) DEFAULT NULL, `c122` varchar(30) DEFAULT NULL, `c123` varchar(30) DEFAULT NULL, `c124` varchar(30) DEFAULT NULL, `c125` varchar(30) DEFAULT NULL, `c126` varchar(30) DEFAULT NULL, `c127` varchar(30) DEFAULT NULL, `c128` varchar(30) DEFAULT NULL, `c129` varchar(30) DEFAULT NULL, `c130` varchar(30) DEFAULT NULL, `c131` varchar(30) DEFAULT NULL, `c132` varchar(30) DEFAULT NULL, `c133` varchar(30) DEFAULT NULL, `c134` varchar(30) DEFAULT NULL, `c135` varchar(30) DEFAULT NULL, `c136` varchar(30) DEFAULT NULL, `c137` varchar(30) DEFAULT NULL, `c138` varchar(30) DEFAULT NULL, `c139` varchar(30) DEFAULT NULL, `c140` varchar(30) DEFAULT NULL, `c141` varchar(30) DEFAULT NULL, `c142` varchar(30) DEFAULT NULL, `c143` varchar(30) DEFAULT NULL, `c144` varchar(30) DEFAULT NULL, `c145` varchar(30) DEFAULT NULL, `c146` varchar(30) DEFAULT NULL, PRIMARY KEY (`c1`) ) ENGINE=InnoDB; LOCK TABLES `t1` WRITE; INSERT INTO `t1`(c2) VALUES ('1'); FLUSH LOGS; -- sync_slave_with_master -- connection master -- echo ### assertion: the slave replicated event successfully and tables match -- let $diff_tables= master:t1, slave:t1 -- source include/diff_tables.inc DROP TABLE `t1`; -- connection master -- sync_slave_with_master -- connection master -- echo === Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a corrupted event, thence would fail. -- let $MYSQLD_DATADIR= `SELECT @@datadir` -- exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog -- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug42749.binlog ############################################################# # BUG#50018: binlog corruption when table has many columns # # Same test from BUG#42749, but now we generate some SQL which # creates and inserts into tables with metadata size from 249 # to 258. # # The test works as follows: # 1. SQL for several CREATE TABLE and INSERTS are generated # into a file. # 2. This file is then "sourced" # 3. The slave is synchronized with the master # 4. FLUSH LOGS on master # 5. Compare tables on master and slave. # 6. run mysqlbinlog on master's binary log # # Steps #5 and #6 assert that binary log is not corrupted # in both cases: when slave is replaying events and when # mysqlbinlog is used to read the binary log --source include/rpl_reset.inc -- connection master # Create several tables with field_metadata_size ranging # from 249 to 258 (so that we cover 251 and 255 range). # This should exercise the switch between using 1 or 3 # bytes to pack m_field_metadata_size. # # Each varchar field takes up to 2 metadata bytes, see: # # Field_varstring::do_save_field_metadata (field.cc) # # The float field takes 1 byte, see: # # Field_float::do_save_field_metadata (field.cc) # -- let $generated_sql= $MYSQLTEST_VARDIR/tmp/b50018.sql -- let B50018_FILE= $generated_sql -- echo ### action: generating several tables with different metadata -- echo ### sizes (resorting to perl) -- perl my $file= $ENV{'B50018_FILE'}; open(FILE, ">", "$file") or die "Unable to open bug 50018 generated SQL file: $!" ; my $tables= ""; my $ntables= 10; my $base_ncols= 124; for my $i (1..$ntables) { my $ncols= $base_ncols + $i; my $metadata_size= $ncols_variable * 2 + 1; print FILE "-- echo ### testing table with " . ($base_ncols*2 + $i) . " field metadata size.\n"; print FILE "CREATE TABLE t$i (\n"; for my $n (1..$base_ncols) { print FILE "c$n VARCHAR(30) NOT NULL DEFAULT 'BUG#50018',\n"; } for my $n (1..$i) { print FILE "c" . ($base_ncols+$n) . " FLOAT NOT NULL DEFAULT 0"; if ($n < $i) { print FILE ",\n"; } } print FILE ") Engine=InnoDB;\n"; $tables.= " t$i WRITE"; if ($i < $ntables) { $tables .=","; } print FILE "LOCK TABLES t$i WRITE;\n"; print FILE "INSERT INTO t$i(c". ($base_ncols+1) . ") VALUES (50018);\n"; print FILE "UNLOCK TABLES;"; } close(FILE); EOF ## we don't need this in the result file ## however, for debugging purposes you ## may want to reactivate query logging -- disable_query_log -- source $generated_sql -- enable_query_log -- sync_slave_with_master -- connection master FLUSH LOGS; -- let $ntables=10 while($ntables) { -- echo ### assertion: the slave replicated event successfully and tables match for t$ntables -- let $diff_tables= master:t$ntables, slave:t$ntables -- source include/diff_tables.inc -- connection master -- disable_query_log -- eval DROP TABLE t$ntables -- enable_query_log -- sync_slave_with_master -- connection master -- dec $ntables } -- echo ### assertion: check that binlog is not corrupt. Using mysqlbinlog to -- echo ### detect failure. Before the patch mysqlbinlog would find -- echo ### a corrupted event, thence would fail. -- let $MYSQLD_DATADIR= `SELECT @@datadir` -- exec $MYSQL_BINLOG -v --hex $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog ## clean up ## For debugging purposes you might want not to remove these -- remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug50018.binlog -- remove_file $generated_sql --source include/rpl_end.inc