List:Commits« Previous MessageNext Message »
From:He Zhenxing Date:March 11 2009 9:59am
Subject:Re: bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719
View as plain text  
Hi Leonard,

Leonard Zhou wrote:
> #At file:///home/zhl/mysql/rep/5.0/bug41719/
> 
>  2767 Leonard Zhou	2009-03-05
>       BUG#41719 delayed INSERT into timestamp col needs set time_zone for concurrent
> binlogging
>       
>       When do 'insert delayed' operation, the time_zone info doesn't follow with the
> row info.

doesn't follow with => is not saved in

>       So when we do insert sometime later, time_zone didn't write into binlog.
>       This will cause wrong result for timestamp column in slave.
>       
>       Our solution is that adding time_zone info with the delayed-row and
>       restoring time_zone from row-info when execute that row in the furture by
> another thread.
>       So we can write correct time_zone info into binlog and got correct result in
> slave.

Very good.

> modified:
>   mysql-test/r/rpl_timezone.result
>   mysql-test/t/rpl_timezone.test
>   sql/sql_insert.cc
> 
> per-file messages:
>   mysql-test/r/rpl_timezone.result
>     Test result
>   mysql-test/t/rpl_timezone.test
>     Add test for bug#41719
>   sql/sql_insert.cc
>     Add time_zone info in the delayed-row and restore time_zone when execute the row
> in the furture by another thread.
> === modified file 'mysql-test/r/rpl_timezone.result'
> --- a/mysql-test/r/rpl_timezone.result	2007-12-15 11:50:23 +0000
> +++ b/mysql-test/r/rpl_timezone.result	2009-03-04 18:56:35 +0000
> @@ -153,4 +153,22 @@ a	b
>  SET @@session.time_zone = default;
>  DROP TABLE t1;
>  SET @@session.time_zone = default;
> +CREATE TABLE t1 (date timestamp NOT NULL default CURRENT_TIMESTAMP on update
> CURRENT_TIMESTAMP, a int(11) default NULL);
> +SET @@session.time_zone='+01:00';
> +insert into t1 values('2008-12-23 19:39:39',1);
> +SET @@session.time_zone='+02:00';
> +insert delayed into t1 values ('2002-12-23 19:39:39',2);
> +flush logs;
> +select * from t1;
> +date	a
> +2008-12-23 20:39:39	1
> +2002-12-23 19:39:39	2
> +delete from t1;
> +DROP TABLE t1;
> +select * from t1;
> +date	a
> +2008-12-23 20:39:39	1
> +2002-12-23 19:39:39	2
> +DROP TABLE t1;
> +SET @@session.time_zone = default;
>  End of 5.0 tests
> 
> === modified file 'mysql-test/t/rpl_timezone.test'
> --- a/mysql-test/t/rpl_timezone.test	2007-08-06 11:57:28 +0000
> +++ b/mysql-test/t/rpl_timezone.test	2009-03-04 18:56:35 +0000
> @@ -154,5 +154,28 @@ connection master;
>  DROP TABLE t1;
>  SET @@session.time_zone = default;
>  
> +# Bug#41719 delayed INSERT into timestamp col needs set time_zone for concurrent
> binlogging
> +# To test that time_zone is correctly binloging for 'insert delayed' statement
> +# Insert 2 values into timestamp col with different time_zone. Check result.
> +
> +--connection master
> +CREATE TABLE t1 (date timestamp NOT NULL default CURRENT_TIMESTAMP on update
> CURRENT_TIMESTAMP, a int(11) default NULL);
> +
> +SET @@session.time_zone='+01:00';
> +insert into t1 values('2008-12-23 19:39:39',1);
> +
> +--connection master1
> +SET @@session.time_zone='+02:00';
> +insert delayed into t1 values ('2002-12-23 19:39:39',2);

use 'FLUSH TABLES t1' to wait for the delay insert finish.

> +flush logs;
> +select * from t1;
> +delete from t1;

the delete can be removed

> +DROP TABLE t1;
> +
> +--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 | $MYSQL
> +--connection master1
> +select * from t1;
> +DROP TABLE t1;
> +SET @@session.time_zone = default;
>  
>  --echo End of 5.0 tests
> 
> === modified file 'sql/sql_insert.cc'
> --- a/sql/sql_insert.cc	2008-10-15 13:55:52 +0000
> +++ b/sql/sql_insert.cc	2009-03-04 18:56:35 +0000
> @@ -1605,6 +1605,8 @@ public:
>    ulong auto_increment_increment;
>    ulong auto_increment_offset;
>    timestamp_auto_set_type timestamp_field_type;
> +  char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
> +  uint time_zone_len;

Use 

Time_zone *time_zone;

to replace above two members, so that you do can avoid searching for the
timezone object later.

Please also change the constructor to initialize this member to 0;

>    uint query_length;
>  
>    delayed_row(enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg)
> @@ -2062,6 +2064,19 @@ int write_delayed(THD *thd,TABLE *table,
>    row->last_insert_id=		thd->last_insert_id;
>    row->timestamp_field_type=    table->timestamp_field_type;
>  
> +  // add session variable timezone

Please use /* */ for comments, this is required by the code guidelines
for server.

> +  if (thd->time_zone_used)
> +  {
> +    row->time_zone_len= thd->variables.time_zone->get_name()->length();
> +    memcpy(row->time_zone_str,
> +	   thd->variables.time_zone->get_name()->ptr(),
> +           row->time_zone_len);
> +    row->time_zone_str[row->time_zone_len+1] = '\0';

If you use Time_zone *time_zone, these lines can be:
  row->time_zone= thd->variables.time_zone

> +  }
> +  else
> +  {
> +     row->time_zone_len = 0;
> +  }

and this will be: 
  row->time_zone= 0;

>    /* The session variable settings can always be copied. */
>    row->auto_increment_increment= thd->variables.auto_increment_increment;
>    row->auto_increment_offset=    thd->variables.auto_increment_offset;
> @@ -2515,6 +2530,22 @@ bool Delayed_insert::handle_inserts(void
>      }
>      if (row->query && row->log_query && using_bin_log)
>      {
> +      if (row->time_zone_len)
> +      {
> +        thd.time_zone_used = true;
> +        String tmp(row->time_zone_str, row->time_zone_len,
> &my_charset_bin);
> +        if (!(thd.variables.time_zone=my_tz_find(&tmp,
> thd.lex->time_zone_tables_used)))
> +        {
> +          thd.variables.time_zone= global_system_variables.time_zone;
> +          sql_print_error("%s",thd.net.last_error);
> +          DBUG_PRINT("error", ("Unknow time zone"));
> +          goto err;
> +        }

And you can avoid searching for the time zone object by name here.

> +      }
> +      else
> +      {
> +        thd.variables.time_zone= global_system_variables.time_zone;

Could you explain why you need this? I think this is not necessary.

> +      }
>        Query_log_event qinfo(&thd, row->query, row->query_length, 0,
> FALSE);
>        mysql_bin_log.write(&qinfo);
>      }
> 
> 

Thread
bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719Leonard Zhou7 Mar
  • Re: bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719Andrei Elkin9 Mar
  • Re: bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719He Zhenxing11 Mar
    • Re: bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719Leonard zhou12 Mar
      • Re: bzr commit into mysql-5.0-bugteam branch (leonard:2767) Bug#41719He Zhenxing12 Mar