Hi Luis,
Great work and findings! patch approved!
Luis Soares wrote:
> #At file:///home/lsoares/Workspace/mysql-server/bugfix/b42749/5.1-bt/ based on
> revid:anurag.shekhar@stripped
>
> 2887 Luis Soares 2009-05-12
> BUG#42749: infinite loop writing to row based binlog - processlist shows
> "freeing items"
>
> The calculation of the table map log event in the event constructor
> was one byte shorter than what would be actually written. This would
> lead to a mismatch between the number of bytes written and the event
> end_log_pos, causing bad event alignment in the binlog (corrupted
> binlog) or in the transaction cache while fixing positions
> (MYSQL_BIN_LOG::write_cache). This could lead to impossible to read
> binlog or even infinite loops in MYSQL_BIN_LOG::write_cache.
>
> This patch addresses this issue by correcting the expected event
> length in the Table_map_log_event constructor, when the field metadata
> size exceeds 255.
> @ sql/log_event.cc
> Added the extra byte as net_store_length imposes.
>
> added:
> mysql-test/suite/binlog/r/binlog_tbl_metadata.result
> mysql-test/suite/binlog/t/binlog_tbl_metadata.test
> modified:
> sql/log_event.cc
> === added file 'mysql-test/suite/binlog/r/binlog_tbl_metadata.result'
> --- a/mysql-test/suite/binlog/r/binlog_tbl_metadata.result 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/r/binlog_tbl_metadata.result 2009-05-12 11:53:46 +0000
> @@ -0,0 +1,156 @@
> +RESET MASTER;
> +DROP TABLE IF EXISTS `t1`;
> +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` VALUES
> ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1');
> +DROP TABLE `t1`;
> +FLUSH LOGS;
> +=== Using mysqlbinlog to detect failure. Before the patch mysqlbinlog would find a
> corrupted event, thence would fail.
>
> === added file 'mysql-test/suite/binlog/t/binlog_tbl_metadata.test'
> --- a/mysql-test/suite/binlog/t/binlog_tbl_metadata.test 1970-01-01 00:00:00 +0000
> +++ b/mysql-test/suite/binlog/t/binlog_tbl_metadata.test 2009-05-12 11:53:46 +0000
> @@ -0,0 +1,199 @@
> +#
> +# 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) a table with several fields is created;
> +# 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/have_log_bin.inc
> +-- source include/have_innodb.inc
> +-- source include/have_binlog_format_row.inc
> +-- connection default
> +
> +RESET MASTER;
> +
> +-- disable_warnings
> +DROP TABLE IF EXISTS `t1`;
> +-- enable_warnings
> +
> +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` VALUES
> ('1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1');
> +
> +DROP TABLE `t1`;
> +
> +FLUSH LOGS;
> +
> +-- 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
>
> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc 2009-04-21 14:31:21 +0000
> +++ b/sql/log_event.cc 2009-05-12 11:53:46 +0000
> @@ -7861,10 +7861,11 @@ Table_map_log_event::Table_map_log_event
>
> /*
> Now set the size of the data to the size of the field metadata array
> - plus one or two bytes for number of elements in the field metadata array.
> + plus one or three bytes (see pack.c:net_store_length) for number of
> + elements in the field metadata array.
> */
> if (m_field_metadata_size > 255)
> - m_data_size+= m_field_metadata_size + 2;
> + m_data_size+= m_field_metadata_size + 3;
> else
> m_data_size+= m_field_metadata_size + 1;
>
>