List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:April 11 2009 6:26pm
Subject:Re: bzr commit into mysql-6.0-rpl branch (luis.soares:2831) Bug#40045
View as plain text  
Hi,

Find a preliminary review.
However, we need to discuss the changes on the sql_upate.cc and
sql_delete.cc.
Let's use skype. I think I did not understand them.

By the way, I did not checked the test cases. I am assuming that you did
exactly what
we discussed on the last time.

See some comments in-line.

Cheers

> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc	2009-03-04 13:33:47 +0000
> +++ b/sql/log_event.cc	2009-04-07 09:55:01 +0000
> @@ -8611,7 +8611,7 @@ void Write_rows_log_event::print(FILE *f
>  
>    Returns TRUE if different.
>  */
> -static bool record_compare(TABLE *table)
>   
I don't remember how ended the discussion about the signature of
the function below. Do we have access to the readset in the object
table, dont we?
> +static bool record_compare(TABLE *table, const MY_BITMAP *cols_in_readset)
>  {
>    /*
>      Need to set the X bit and the filler bits in both records since
> @@ -8643,14 +8643,23 @@ static bool record_compare(TABLE *table)
>      }
>    }
>  
> -  if (table->s->blob_fields + table->s->varchar_fields == 0)
> +  /* 
> +     We can compare the record straight away if:
> +      i) there are no blob and varchar fields
> +     ii) all columns were read or the slave SE provides partial reads
> +  */
> +  if ((table->s->blob_fields + table->s->varchar_fields == 0)
> &&
> +      (bitmap_is_set_all(cols_in_readset) || 
> +      (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)))
>    {
>      result= cmp_record(table,record[1]);
>      goto record_compare_exit;
>    }
>  
> -  /* Compare null bits */
> -  if (memcmp(table->null_flags,
> +  /* Compare null bits only if all fields were read or slave SE has partial reads
> */
> +  if ((bitmap_is_set_all(cols_in_readset) || 
> +       (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ))
> && 
> +      memcmp(table->null_flags,
>  	     table->null_flags+table->s->rec_buff_length,
>  	     table->s->null_bytes))
>    {
> @@ -8661,10 +8670,14 @@ static bool record_compare(TABLE *table)
>    /* Compare updated fields */
>    for (Field **ptr=table->field ; *ptr ; ptr++)
>    {
> -    if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length))
> -    {
> -      result= TRUE;
> -      goto record_compare_exit;
> +    /* compare field if it is set */
> +    if (bitmap_is_set(cols_in_readset, (*ptr)->field_index))
> +    { 
> +      if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length))
> +      {
> +        result= TRUE;
> +        goto record_compare_exit;
> +      }
>      }
>    }
>  
> @@ -8875,7 +8888,7 @@ int Rows_log_event::find_row(const Relay
>       */ 
>      DBUG_PRINT("info",("non-unique index, scanning it to find matching record")); 
>  
> -    while (record_compare(table))
> +    while (record_compare(table, &m_cols))
>      {
>        /*
>          We need to set the null bytes to ensure that the filler bit
> @@ -8956,7 +8969,7 @@ int Rows_log_event::find_row(const Relay
>          goto err;
>        }
>      }
> -    while (restart_count < 2 && record_compare(table));
> +    while (restart_count < 2 && record_compare(table, &m_cols));
>      
>      /* 
>        Note: above record_compare will take into accout all record fields 
>
> === modified file 'sql/log_event_old.cc'
> --- a/sql/log_event_old.cc	2008-12-10 14:30:52 +0000
> +++ b/sql/log_event_old.cc	2009-04-07 09:55:01 +0000
> @@ -313,7 +313,7 @@ last_uniq_key(TABLE *table, uint keyno)
>  
>    Returns TRUE if different.
>  */
> -static bool record_compare(TABLE *table)
> +static bool record_compare(TABLE *table, const MY_BITMAP *cols_in_readset)
>  {
>    /*
>      Need to set the X bit and the filler bits in both records since
> @@ -342,16 +342,25 @@ static bool record_compare(TABLE *table)
>      }
>    }
>  
> -  if (table->s->blob_fields + table->s->varchar_fields == 0)
> +  /*   
> +     We can compare the record straight away if:
> +       i) there are no blob and varchar fields
> +      ii) all columns were read or the slave SE provides partial reads
> +  */
> +  if ((table->s->blob_fields + table->s->varchar_fields == 0)
> &&
> +      (bitmap_is_set_all(cols_in_readset) || 
> +      (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)))
>    {
>      result= cmp_record(table,record[1]);
>      goto record_compare_exit;
>    }
>  
> -  /* Compare null bits */
> -  if (memcmp(table->null_flags,
> -       table->null_flags+table->s->rec_buff_length,
> -       table->s->null_bytes))
> +  /* Compare null bits only if all fields were read or slave SE has partial reads
> */
> +  if ((bitmap_is_set_all(cols_in_readset) || 
> +        (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ))
> && 
> +      memcmp(table->null_flags,
> +             table->null_flags+table->s->rec_buff_length,
> +             table->s->null_bytes))
>    {
>      result= TRUE;       // Diff in NULL value
>      goto record_compare_exit;
> @@ -360,10 +369,14 @@ static bool record_compare(TABLE *table)
>    /* Compare updated fields */
>    for (Field **ptr=table->field ; *ptr ; ptr++)
>    {
> -    if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length))
> -    {
> -      result= TRUE;
> -      goto record_compare_exit;
> +    /* compare field if it is set */
> +    if (bitmap_is_set(cols_in_readset, (*ptr)->field_index))
> +    { 
> +      if ((*ptr)->cmp_binary_offset(table->s->rec_buff_length))
> +      {
> +        result= TRUE;
> +        goto record_compare_exit;
> +      }
>      }
>    }
>  
> @@ -644,6 +657,7 @@ replace_record(THD *thd, TABLE *table,
>  
>    @param table Pointer to table to search
>    @param key   Pointer to key to use for search, if table has key
> +  @param cols  Bitmap denoting the columns read in the BI image.
>  
>    @pre <code>table->record[0]</code> shall contain the row to locate
>    and <code>key</code> shall contain a key to use for searching, if
> @@ -659,7 +673,7 @@ replace_record(THD *thd, TABLE *table,
>    <code>table->record[1]</code>, error code otherwise.
>   */
>  
> -static int find_and_fetch_row(TABLE *table, uchar *key)
> +static int find_and_fetch_row(TABLE *table, uchar *key, MY_BITMAP *cols)
>  {
>    DBUG_ENTER("find_and_fetch_row(TABLE *table, uchar *key, uchar *record)");
>    DBUG_PRINT("enter", ("table: %p, key: %p  record: %p",
> @@ -761,7 +775,7 @@ static int find_and_fetch_row(TABLE *tab
>        DBUG_RETURN(0);
>      }
>  
> -    while (record_compare(table))
> +    while (record_compare(table, cols))
>      {
>        int error;
>  
> @@ -837,7 +851,7 @@ static int find_and_fetch_row(TABLE *tab
>    DBUG_RETURN(error);
>        }
>      }
> -    while (restart_count < 2 && record_compare(table));
> +    while (restart_count < 2 && record_compare(table, cols));
>  
>      /*
>        Have to restart the scan to be able to fetch the next row.
> @@ -1060,7 +1074,7 @@ int Delete_rows_log_event_old::do_exec_r
>    int error;
>    DBUG_ASSERT(table != NULL);
>  
> -  if (!(error= ::find_and_fetch_row(table, m_key)))
> +  if (!(error= ::find_and_fetch_row(table, m_key, &m_cols)))
>    { 
>      /*
>        Now we should have the right row to delete.  We are using
> @@ -1168,7 +1182,7 @@ int Update_rows_log_event_old::do_exec_r
>  {
>    DBUG_ASSERT(table != NULL);
>  
> -  int error= ::find_and_fetch_row(table, m_key);
> +  int error= ::find_and_fetch_row(table, m_key, &m_cols);
>    if (error)
>      return error;
>  
> @@ -2387,7 +2401,7 @@ int Old_rows_log_event::find_row(const R
>       */ 
>      DBUG_PRINT("info",("non-unique index, scanning it to find matching record")); 
>  
> -    while (record_compare(table))
> +    while (record_compare(table, &m_cols))
>      {
>        /*
>          We need to set the null bytes to ensure that the filler bit
> @@ -2463,7 +2477,7 @@ int Old_rows_log_event::find_row(const R
>          DBUG_RETURN(error);
>        }
>      }
> -    while (restart_count < 2 && record_compare(table));
> +    while (restart_count < 2 && record_compare(table, &m_cols));
>      
>      /* 
>        Note: above record_compare will take into accout all record fields 
>
> === modified file 'sql/sql_delete.cc'
> --- a/sql/sql_delete.cc	2009-03-04 13:31:31 +0000
> +++ b/sql/sql_delete.cc	2009-04-07 09:55:01 +0000
> @@ -292,7 +292,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *
>  
>  
>    table->mark_columns_needed_for_delete();
> -
> +  /* conditionally mark columns needed for BI in RBR */
> +  table->mark_columns_needed_for_rbr_bi();
>    while (!(error=info.read_record(&info)) && !thd->killed &&
>  	 ! thd->is_error())
>    {
> @@ -342,6 +343,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *
>      else
>        table->file->unlock_row();  // Row failed selection, release lock on it
>    }
> +  /* conditionally restore read_set bitmap after read */
> +  table->restore_columns_maps_after_rbr_bi();
>    killed_status= thd->killed;
>    if (killed_status != THD::NOT_KILLED || thd->is_error())
>      error= 1;					// Aborted
>
> === modified file 'sql/sql_update.cc'
> --- a/sql/sql_update.cc	2009-02-16 21:18:45 +0000
> +++ b/sql/sql_update.cc	2009-04-07 09:55:01 +0000
> @@ -475,6 +475,8 @@ int mysql_update(THD *thd,
>        thd_proc_info(thd, "Searching rows for update");
>        ha_rows tmp_limit= limit;
>  
> +      /* conditionally mark columns needed for BI in RBR */     
> +      table->mark_columns_needed_for_rbr_bi();
>        while (!(error=info.read_record(&info)) && !thd->killed)
>        {
>  	if (!(select && select->skip_record()))
> @@ -498,6 +500,8 @@ int mysql_update(THD *thd,
>  	else
>  	  table->file->unlock_row();
>        }
> +      /* conditionally restore read_set bitmap after read */
> +      table->restore_columns_maps_after_rbr_bi();
>        if (thd->killed && !error)
>  	error= 1;				// Aborted
>        limit= tmp_limit;
> @@ -572,6 +576,9 @@ int mysql_update(THD *thd,
>    if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)
>      table->prepare_for_position();
>  
> +  /* conditionally mark columns needed for BI in RBR */     
> +  table->mark_columns_needed_for_rbr_bi();
> +
>    /*
>      We can use compare_record() to optimize away updates if
>      the table handler is returning all columns OR if
> @@ -775,6 +782,8 @@ int mysql_update(THD *thd,
>      updated-= dup_key_found;
>    if (will_batch)
>      table->file->end_bulk_update();
> +  /* conditionally restore read_set bitmap after read */
> +  table->restore_columns_maps_after_rbr_bi();
>    table->file->try_semi_consistent_read(0);
>  
>    if (!transactional_table && updated > 0)
>
> === modified file 'sql/table.cc'
> --- a/sql/table.cc	2009-03-04 13:33:47 +0000
> +++ b/sql/table.cc	2009-04-07 09:55:01 +0000
> @@ -4679,6 +4679,72 @@ void TABLE::mark_columns_needed_for_inse
>      mark_auto_increment_column();
>  }
>  
>   
Do you always use the TABLE::mark_columns_needed_for_rbr_bi() and
void TABLE::restore_columns_maps_after_rbr_bi() together? If so, please
move the initialization and destruction of the
structure rbr_bi_tmp_map.bitmap to the TABLE:TABLE and TABLE:~TABLE,
respectively.
> +void TABLE::mark_columns_needed_for_rbr_bi()
> +{
> +  /* sets read set needed for RBR */
> +  if ((!no_replicate && 
> +      in_use->current_stmt_binlog_row_based && 
> +      mysql_bin_log.is_open()))
> +  {
> +
> +    /* save a copy of the old read_set */
> +    if (!rbr_bi_tmp_map.bitmap)
> +      bitmap_init(&rbr_bi_tmp_map, NULL, read_set->n_bits, FALSE);
> +
> +    bitmap_copy(&rbr_bi_tmp_map, read_set);
> +
> +    /* 
> +       use all columns if there is no primary key 
> +       or engine does not provide partial fetch.
> +     */
>   
And about unique indexes?
Why aren't you considering this?
If there is no technical issue write a comment on that before the if
and file a bug report in order that we don't forget it.
You don't need to implement this as part of this bug.

> +    if (s->primary_key == MAX_KEY || 
> +        !(file->ha_table_flags() & HA_PARTIAL_COLUMN_READ))
> +      /*
> +         We could use the s->all_set bitmap here, but since we
> +         need to handle the restore when setting all columns 
> +         for the primary key (the else branch below), we will 
> +         follow the same pattern with the use_all_columns in 
> +         read_set.
> +       */
> +      bitmap_set_all(read_set); 
> +    else
> +    {
> +      /* mark the primary key */
>   
Can you explain why you are preserving the bits in the original readset?
-----------
> +      mark_columns_used_by_index_no_reset(s->primary_key, read_set);
>   
----------
> +      file->column_bitmaps_signal();
> +    }
> +  }
> +}
> +
> +void TABLE::restore_columns_maps_after_rbr_bi()
> +{
> +  if ((!no_replicate && 
> +      in_use->current_stmt_binlog_row_based && 
> +      mysql_bin_log.is_open()))
> +  {
> +    /* 
> +       If the bitmap exists that means that the proper 
> +       mark method was called before this one. Otherwise
> +       just ignore.
> +    */
> +    if (rbr_bi_tmp_map.bitmap != NULL)
> +    {
> +      /* 
> +        Restore old read set by intersecting both: the bitmap set after marking
> +        and the saved bitmap. This handles the following cases:
> +          a) mask out the original readset when marked all columns
> +          b) mask out primary key if it was not set in the first place
> +             Note that partial primary key columns might have been set
> +             even before "mark_columns_needed_for_rbr_bi" and we want
> +             to preserve those as well.
> +      */
>   
Why don't you simply copy the saved readset back?
Is the saved_readset & changed_readet == saved_readset?
Can you explain when this is different?
See comment above.
----------
> +      bitmap_intersect(read_set, &rbr_bi_tmp_map);
>   
----------
> +
> +      /* free memory used by temporary bitmap */
> +      bitmap_free(&rbr_bi_tmp_map);
>   
See comment above.
> +    }
> +  }
> +}
>  
>  /*
>    Cleanup this table for re-execution.
>
> === modified file 'sql/table.h'
> --- a/sql/table.h	2009-03-04 20:29:16 +0000
> +++ b/sql/table.h	2009-04-07 09:55:01 +0000
> @@ -678,7 +678,7 @@ public:
>    const char	*alias;            	  /* alias or table name */
>    uchar		*null_flags;
>    my_bitmap_map	*bitmap_init_value;
> -  MY_BITMAP     def_read_set, def_write_set, tmp_set; /* containers */
> +  MY_BITMAP     def_read_set, def_write_set, tmp_set, rbr_bi_tmp_map; /* containers
> */
>    MY_BITMAP     *read_set, *write_set;          /* Active column sets */
>    /*
>     The ID of the query that opened and is using this table. Has different
> @@ -804,6 +804,8 @@ public:
>    void mark_columns_needed_for_update(void);
>    void mark_columns_needed_for_delete(void);
>    void mark_columns_needed_for_insert(void);
> +  void mark_columns_needed_for_rbr_bi(void);
> +  void restore_columns_maps_after_rbr_bi(void);
>    inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
>                                   MY_BITMAP *write_set_arg)
>    {
>   
> ------------------------------------------------------------------------
>
> This body part will be downloaded on demand.
Cheers.
Thread
bzr commit into mysql-6.0-rpl branch (luis.soares:2831) Bug#40045Luis Soares7 Apr
  • Re: bzr commit into mysql-6.0-rpl branch (luis.soares:2831) Bug#40045Alfranio Correia11 Apr