List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:October 27 2010 12:55pm
Subject:Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)
Bug#53386
View as plain text  
On 10/20/2010 04:45 PM, Luis Soares wrote:
> #At file:///home/lsoares/Workspace/bzr/work/bugfixing/53386/mysql-trunk-bugfixing/
> based on revid:alfranio.correia@stripped
>
>  3288 Luis Soares	2010-10-20
>       BUG#53386: HA_ERR_CORRUPT_EVENT or debug assertion with different
>       table on slave
>       
>       When the number of raw bytes used for a CHAR field exceeds 255
>       two bytes are actually used while packing the length of the
>       field. CHAR fields can exceed the raw 255 byte length, for
>       instance, if using multi-byte character sets.
>       
>       The problem is that when calculating the raw length of the field,
>       at unpacking time, only one byte was assumed to be used
>       always. Therefore, the number of bytes used would not add up,
>       triggering the assertion.
>       
>       We fix this, by making the member function that calculates the
>       raw byte length for a given field to take into account the actual
>       number of bytes used while packing the field length.
>      @ mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test
>         Extended the test case with one based on the bug report entry.
>
>     modified:
>       mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test
>       mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result
>       mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result
>       sql/rpl_utility.cc
> === modified file 'mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test'
> --- a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test	2010-06-22 09:34:59 +0000
> +++ b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test	2010-10-20 14:45:31 +0000
> @@ -1029,4 +1029,34 @@ sync_slave_with_master;
>  
>  # END of 5.1 tests case
>  
> +#
> +# BUG#53386: HA_ERR_CORRUPT_EVENT or debug assertion with different table on slave
> +#
> +
> +-- connection master
> +-- source include/master-slave-reset.inc
> +-- connection master
> +
> +# CREATE Different tables on master and slave
> +SET SQL_LOG_BIN=0;
> +-- eval CREATE TABLE t1 (c1 INT NOT NULL, c2 CHAR(255) CHARACTER SET UTF8 NOT NULL)
> ENGINE=$engine_type
> +SET SQL_LOG_BIN=1;
> +-- connection slave
> +-- eval CREATE TABLE t1 (c1 INT) ENGINE=$engine_type
> +
> +# insert empty row (c2 gets an empty string)
> +-- connection master
> +
> +-- disable_warnings
> +INSERT INTO t1 VALUES (); 
> +-- enable_warnings
> +
> +SELECT * FROM t1; 
> +-- sync_slave_with_master
> +SELECT * FROM t1; 
> +
> +# clean up
> +-- connection master
> +DROP TABLE t1; 
> +-- sync_slave_with_master
>  
>
> === modified file 'mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result'
> --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result	2010-06-22 09:34:59
> +0000
> +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result	2010-10-20 14:45:31
> +0000
> @@ -876,3 +876,21 @@ c1	hex(c4)	c5
>  3	6231623162316231	QA
>  DROP TABLE t5;
>  
> +stop slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +reset master;
> +reset slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +start slave;
> +SET SQL_LOG_BIN=0;
> +CREATE TABLE t1 (c1 INT NOT NULL, c2 CHAR(255) CHARACTER SET UTF8 NOT NULL)
> ENGINE='InnoDB';
> +SET SQL_LOG_BIN=1;
> +CREATE TABLE t1 (c1 INT) ENGINE='InnoDB';
> +INSERT INTO t1 VALUES ();
> +SELECT * FROM t1;
> +c1	c2
> +0	
> +SELECT * FROM t1;
> +c1
> +0
> +DROP TABLE t1;
>
> === modified file 'mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result'
> --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result	2010-06-22 09:34:59
> +0000
> +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result	2010-10-20 14:45:31
> +0000
> @@ -876,3 +876,21 @@ c1	hex(c4)	c5
>  3	6231623162316231	QA
>  DROP TABLE t5;
>  
> +stop slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +reset master;
> +reset slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +start slave;
> +SET SQL_LOG_BIN=0;
> +CREATE TABLE t1 (c1 INT NOT NULL, c2 CHAR(255) CHARACTER SET UTF8 NOT NULL)
> ENGINE='MyISAM';
> +SET SQL_LOG_BIN=1;
> +CREATE TABLE t1 (c1 INT) ENGINE='MyISAM';
> +INSERT INTO t1 VALUES ();
> +SELECT * FROM t1;
> +c1	c2
> +0	
> +SELECT * FROM t1;
> +c1
> +0
> +DROP TABLE t1;
>
> === modified file 'sql/rpl_utility.cc'
> --- a/sql/rpl_utility.cc	2010-07-16 21:00:50 +0000
> +++ b/sql/rpl_utility.cc	2010-10-20 14:45:31 +0000
> @@ -225,9 +225,10 @@ uint32 table_def::calc_field_size(uint c
>        /*
>          We are reading the actual size from the master_data record
>          because this field has the actual lengh stored in the first
> -        byte.
> +        one or two bytes.
>        */
> -      length= (uint) *master_data + 1;
> +      uint32 max_length= max_display_length_for_field(MYSQL_TYPE_STRING,
> m_field_metadata[col]);
> +      length= (uint) (max_length > 255 ? 2 : 1) + *master_data;
>   

If two bytes are used to represent the length, I think you need to read
two bytes from the master data to compute the length... but you're just
reading one.

Shouldn't it be:

    if (max_length > 255)
        length= *master_data + *(master_data + 1) << 8 + 2;
    else
        length = *master_data + 1;

or

    length = *master_data + (max_length > 255 ? 2 + *(master_data + 1)
    << 8 : 1)

whichever you prefer.

Just my few cents,
Mats Kindahl


>        DBUG_ASSERT(length != 0);
>      }
>      break;
>
>   
>
>
>
>   

Thread
bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288) Bug#53386Luis Soares20 Oct
  • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386He Zhenxing27 Oct
  • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386Mats Kindahl27 Oct
    • Re: bzr commit into mysql-trunk-bugfixing branch (luis.soares:3288)Bug#53386Luís Soares29 Oct