List:Commits« Previous MessageNext Message »
From:Øystein Grøvlen Date:November 18 2008 2:46pm
Subject:Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)
Bug#40262
View as plain text  
STATUS
======

Approved when a long line has been fixed.

REQUESTS
========

1. Long line: [3]

SUGGESTIONS
===========

1. Please, consider whether sleep is necessary [1]

2. Use a single query to check all vp info [2]


Rafal Somla wrote:
> #At file:///ext/mysql/bzr/backup/bug40262/
> 
>  2734 Rafal Somla	2008-11-17
>       Bug #40262  - Binary log information incorrect in backup of no data with binlog
> 
>                     turned on
>       
>       This is the second and last patch which fixes the main problem of reporting VP
> 
>       info also in the case there are no tables to be backed-up. 
>       
>       It also fixes an issue with incorrect parsing of backup image upon restore, if
> 
>       there are no table data stored in it.
> modified:
>   mysql-test/suite/backup/r/backup.result
>   mysql-test/suite/backup/t/backup.test
>   sql/backup/data_backup.cc
>   sql/backup/image_info.cc
>   sql/backup/image_info.h
>   sql/share/errmsg.txt
> 
> per-file messages:
>   mysql-test/suite/backup/t/backup.test
>     Added a test case checking that VP info was correctly read from the image if 
>     there are no tables stored in it.
>   sql/backup/data_backup.cc
>     - Save and report VP info also if there are no tables to backup.
>     - Move the code fro storing and reporting VP info into helper functions 
>       save/report_vp_info()
>     - Fix error in restore_table_data(): if there are no tables to restore, we 
>       still need to read the 0x00 marker signaling end of table data chunks.
>   sql/backup/image_info.cc
>     Add member and method for storing master's binlog position at VP time.
>   sql/backup/image_info.h
>     Add member and method for storing master's binlog position at VP time.
> === modified file 'mysql-test/suite/backup/r/backup.result'
> --- a/mysql-test/suite/backup/r/backup.result	2008-10-07 17:15:44 +0000
> +++ b/mysql-test/suite/backup/r/backup.result	2008-11-17 14:43:10 +0000
> @@ -148,6 +148,35 @@ DROP DATABASE db1;
>  DROP DATABASE db2;
>  DROP DATABASE db3;
>  SET DEBUG_SYNC= 'RESET';
> +CREATE DATABASE db1;
> +BACKUP DATABASE db1 TO 'db1.bkp';
> +backup_id
> +#
> +SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;
> +SELECT validity_point_time FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_time;
> +SELECT binlog_file FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_file;
> +SELECT binlog_pos FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_pos;
> +DROP DATABASE db1;
> +RESTORE FROM 'db1.bkp';
> +backup_id
> +#
> +SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;
> +SELECT validity_point_time = @vp_time FROM mysql.backup_history
> +WHERE backup_id = @bid;
> +validity_point_time = @vp_time
> +1
> +SELECT binlog_file = @vp_file FROM mysql.backup_history
> +WHERE backup_id = @bid;
> +binlog_file = @vp_file
> +1
> +SELECT binlog_pos = @vp_pos FROM mysql.backup_history
> +WHERE backup_id = @bid;
> +binlog_pos = @vp_pos
> +1
> +DROP DATABASE db1;
>  DROP DATABASE IF EXISTS bup_default;
>  CREATE DATABASE bup_default;
>  CREATE TABLE bup_default.wide (
> 
> === modified file 'mysql-test/suite/backup/t/backup.test'
> --- a/mysql-test/suite/backup/t/backup.test	2008-10-07 17:15:44 +0000
> +++ b/mysql-test/suite/backup/t/backup.test	2008-11-17 14:43:10 +0000
> @@ -193,6 +193,52 @@ DROP DATABASE db3;
>  SET DEBUG_SYNC= 'RESET';
>  
>  #
> +# Check that PTR data (such as VP time and binlog positon) is correctly stored and
> read
> +# when there are no tables to backup (BUG#40262). 
> +#
> +
> +--error 0,1
> +--remove_file $MYSQLTEST_VARDIR/master-data/db1.bkp
> +CREATE DATABASE db1;
> +
> +--replace_column 1 #
> +BACKUP DATABASE db1 TO 'db1.bkp';
> +# get backup_id of the BACKUP operation. 
> +SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;
> +
> +# store VP time and binlog position
> +
> +SELECT validity_point_time FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_time;
> +SELECT binlog_file FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_file;
> +SELECT binlog_pos FROM mysql.backup_history
> +WHERE backup_id = @bid INTO @vp_pos;
> +
> +DROP DATABASE db1;
> +
> +# wait few seconds so that restore time != backup time
> +--sleep 2

[1]  I do not understand the purpose of sleep here.  Why does restore 
time have to be different from backup time.

> +
> +--replace_column 1 #
> +RESTORE FROM 'db1.bkp';
> +# determine id of RESTORE operation
> +SELECT MAX(backup_id) FROM mysql.backup_history INTO @bid;
> +
> +# check that VP info was correctly read and reported
> +
> +SELECT validity_point_time = @vp_time FROM mysql.backup_history
> +WHERE backup_id = @bid; 
> +SELECT binlog_file = @vp_file FROM mysql.backup_history
> +WHERE backup_id = @bid; 
> +SELECT binlog_pos = @vp_pos FROM mysql.backup_history
> +WHERE backup_id = @bid; 

[2] All three criteria could be checked with a single select statement.

> +
> +DROP DATABASE db1;
> +--remove_file $MYSQLTEST_VARDIR/master-data/db1.bkp
> +
> +
> +#
>  # This test is for the default and snapshot online backup drivers
>  #
>  
> 
> === modified file 'sql/backup/data_backup.cc'
> --- a/sql/backup/data_backup.cc	2008-10-30 20:02:15 +0000
> +++ b/sql/backup/data_backup.cc	2008-11-17 14:43:10 +0000
> @@ -412,6 +412,68 @@ int unblock_commits(THD *thd)
>  }
>  
>  /**
> +  Store information about validity point in @c Backup_info structure.
> +  
> +  @note This function is called in a time critical synchronization phase
> +  of the backup process. Therefore it should not perform any time consuming
> +  or potentially waiting operations such as I/O.
> +
> +  @returns 0 on success.
> +*/
> +static
> +int save_vp_info(Backup_info &info)
> +{
> +  LOG_INFO binlog_pos;
> +  int ret=0;
> +
> +  /*
> +    Save VP creation time.
> +  */
> +  info.save_vp_time(my_time(0));
> +
> +  /*
> +    Save current binlog position if it is enabled.
> +  */
> +  if (mysql_bin_log.is_open())
> +    if (mysql_bin_log.get_current_log(&binlog_pos))
> +    {
> +      info.m_ctx.report_error(ER_BACKUP_BINLOG);
> +      ret= TRUE;
> +    }
> +    else
> +      info.save_binlog_pos(binlog_pos);
> +
> +  /*
> +    Save master's binlog information if we are a connected slave.
> +  */
> +  if (obs::is_slave() && active_mi)
> +    info.save_master_pos(*active_mi);
> +
> +  return ret;
> +}
> +
> +/**
> +  Log validity point information.
> +
> +  Information such as validity point time is logged using backup logger which,
> +  in particular, writes it to backup history and progress logs.
> +  
> +  @note Logging the information may involve time consuming I/O. Therefore this
> +  function should not be called in the time critical synchronization phase, but
> +  after the synchronisation has been done.
> +*/ 
> +static
> +void report_vp_info(Backup_info &info)
> +{
> +  info.m_ctx.report_vp_time(info.get_vp_time(), TRUE); // TRUE = also write to
> progress log

[3] Line is too long.

> +  if (info.flags & BSTREAM_FLAG_BINLOG)
> +    info.m_ctx.report_binlog_pos(info.binlog_pos);
> +  if (info.master_pos.pos)
> +    info.m_ctx.report_master_binlog_pos(info.master_pos);
> +}
> +
> +
> +/**
>    Save data from tables being backed up.
>  
>    Function initializes and controls backup drivers which create the image
> @@ -424,8 +486,21 @@ int write_table_data(THD* thd, Backup_in
>  {
>    DBUG_ENTER("backup::write_table_data");
>  
> +  /*
> +    If there no tables to backup, there is nothing to do in this function
> +    except for storing and reporting the validity point info.
> +    
> +    Note that since backup image contains no table data, any time is a good
> +    validity time -- there is no issue of synchronizing the data stored in 
> +    the image with the data in the rest of the server.
> +  */ 
>    if (info.snap_count() == 0 || info.table_count() == 0) // nothing to backup
> -    DBUG_RETURN(0);
> +  {
> +    int res= save_vp_info(info);    // logs errors
> +    if (!res)
> +      report_vp_info(info);
> +    DBUG_RETURN(res);
> +  }
>  
>    Scheduler   sch(s, &info.m_ctx);          // scheduler instance
>    List<Scheduler::Pump>  inactive;  // list of images not yet being created
> @@ -433,8 +508,6 @@ int write_table_data(THD* thd, Backup_in
>    // keeps maximal init size for images in inactive list
>    size_t      max_init_size=0;
>  
> -  time_t      vp_time;              // to store validity point time
> -
>    DBUG_PRINT("backup_data",("initializing scheduler"));
>  
>    // add unknown "at end" drivers to scheduler, rest to inactive list
> @@ -582,8 +655,6 @@ int write_table_data(THD* thd, Backup_in
>      
>      DBUG_PRINT("backup_data",("-- SYNC PHASE --"));
>  
> -    LOG_INFO binlog_pos;
> -    
>      info.m_ctx.report_state(BUP_VALIDITY_POINT);
>      /*
>        This breakpoint is used to assist in testing state changes for
> @@ -600,33 +671,7 @@ int write_table_data(THD* thd, Backup_in
>      if (sch.lock())
>        goto error;
>  
> -    /*
> -      Save binlog information for point in time recovery on restore.
> -    */
> -    if (mysql_bin_log.is_open())
> -      if (mysql_bin_log.get_current_log(&binlog_pos))
> -      {
> -        info.m_ctx.fatal_error(ER_BACKUP_BINLOG);
> -        goto error;
> -      }
> -
> -    /*
> -      If we are a connected slave, write master's binlog information to
> -      the progress log for later use.
> -    */
> -    st_bstream_binlog_pos master_pos;
> -    master_pos.pos= 0;
> -    master_pos.file= 0;
> -    if (obs::is_slave() && active_mi)
> -    {
> -      master_pos.pos= (ulong)active_mi->master_log_pos;
> -      master_pos.file= active_mi->master_log_name;
> -    }
> -
> -    /*
> -      Save VP creation time.
> -    */
> -    vp_time= my_time(0);
> +    save_vp_info(info);
>  
>      DEBUG_SYNC(thd, "before_backup_data_unlock");
>      if (sch.unlock())
> @@ -640,23 +685,7 @@ int write_table_data(THD* thd, Backup_in
>      if (error)
>        goto error;
>  
> -    // Report and save information about VP
> -
> -    info.save_vp_time(vp_time);
> -    info.m_ctx.report_vp_time(vp_time, TRUE); // TRUE = also write to progress log
> -
> -    if (mysql_bin_log.is_open())
> -    {
> -      info.save_binlog_pos(binlog_pos);
> -      info.m_ctx.report_binlog_pos(info.binlog_pos);
> -    }
> -
> -    /*
> -      If we are a slave and the master's binlog position has been recorded
> -      write it to the log.
> -    */
> -    if (obs::is_slave() && master_pos.pos)
> -      info.m_ctx.report_master_binlog_pos(master_pos);
> +    report_vp_info(info);
>  
>      info.m_ctx.report_state(BUP_RUNNING);
>      DEBUG_SYNC(thd, "after_backup_binlog");
> @@ -1364,12 +1393,29 @@ namespace backup {
>   */
>  int restore_table_data(THD *thd, Restore_info &info, Input_stream &s)
>  {
> +  st_bstream_data_chunk chunk_info; // For reading chunks from the stream.
> +
>    DBUG_ENTER("restore::restore_table_data");
>  
>    enum { READING, SENDING, DONE, ERROR } state= READING;
>  
> +  /*
> +    If there are no tables stored in the image, there is nothing to do in this
> +    function. However, we must call bstream_rd_data_chunk() which will absorb
> +    the 0x00 byte signalling end of (the empty) table data chunk sequence.
> +  */ 
>    if (info.snap_count() == 0 || info.table_count() == 0) // nothing to restore
> +  {
> +    int res= bstream_rd_data_chunk(&s, &chunk_info);
> +    if (res != BSTREAM_EOC)
> +    {
> +       info.m_ctx.report_error(res == BSTREAM_ERROR ?
> +                                ER_BACKUP_READ_DATA :
> +                                ER_BACKUP_UNEXPECTED_DATA);
> +       DBUG_RETURN(ERROR);
> +    }
>      DBUG_RETURN(0);
> +  }
>  
>    Restore_driver* drv[256];
>  
> @@ -1426,8 +1472,6 @@ int restore_table_data(THD *thd, Restore
>  
>      // main data reading loop
>  
> -    st_bstream_data_chunk chunk_info;
> -
>      while ( state != DONE && state != ERROR )
>      {
>        switch (state) {
> 
> === modified file 'sql/backup/image_info.cc'
> --- a/sql/backup/image_info.cc	2008-11-05 09:41:15 +0000
> +++ b/sql/backup/image_info.cc	2008-11-17 14:43:10 +0000
> @@ -1,4 +1,5 @@
>  #include "../mysql_priv.h"
> +#include "../rpl_mi.h"
>  
>  #include "image_info.h"
>  #include "be_native.h"
> @@ -50,6 +51,7 @@ Image_info::Image_info()
>  #endif
>  
>    bzero(m_snap, sizeof(m_snap));
> +  bzero(&master_pos, sizeof(master_pos));
>  }
>  
>  Image_info::~Image_info()
> @@ -384,6 +386,14 @@ Image_info::Obj *find_obj(const Image_in
>    }
>  }
>  
> +void Image_info::save_master_pos(const ::Master_info &mi)
> +{
> +  // store binlog coordinates
> +  master_pos.pos=  static_cast<unsigned long int>(mi.master_log_pos);
> +  master_pos.file= const_cast<char*>(mi.master_log_name);
> +}
> +
> +
>  } // backup namespace
>  
>  template class Map<uint, backup::Image_info::Db>;
> 
> === modified file 'sql/backup/image_info.h'
> --- a/sql/backup/image_info.h	2008-11-05 09:41:15 +0000
> +++ b/sql/backup/image_info.h	2008-11-17 14:43:10 +0000
> @@ -75,6 +75,7 @@ public: // public interface
>     // info about image (most of it is in the st_bstream_image_header base
>  
>     size_t     data_size;      ///< How much of table data is saved in the image.
> +   st_bstream_binlog_pos  master_pos; ///< To store master position info.
>  
>     ulong      table_count() const;
>     uint       db_count() const;
> @@ -115,6 +116,7 @@ public: // public interface
>     void save_vp_time(const time_t time);   
>  
>     void save_binlog_pos(const ::LOG_INFO&);
> +   void save_master_pos(const ::Master_info&);
>  
>     time_t get_vp_time() const;
>  
> 
> === modified file 'sql/share/errmsg.txt'
> --- a/sql/share/errmsg.txt	2008-11-05 15:07:40 +0000
> +++ b/sql/share/errmsg.txt	2008-11-17 14:43:10 +0000
> @@ -6414,3 +6414,5 @@ ER_RESTORE_ON_SLAVE
>    eng "A restore operation was attempted on a slave during replication. You must
> stop the slave prior to running a restore."
>  ER_NONUNIQ_DB 42000 S1009
>          eng "Not unique database: '%-.192s'"
> +ER_BACKUP_UNEXPECTED_DATA
> +  eng "Backup image contains no tables, but table data was found in it"
> 
> 
Thread
bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734) Bug#40262Rafal Somla17 Nov
  • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Øystein Grøvlen18 Nov
    • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Rafal Somla18 Nov
      • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Øystein Grøvlen19 Nov
  • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Chuck Bell19 Nov
  • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Chuck Bell19 Nov
    • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Rafal Somla20 Nov
      • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Øystein Grøvlen20 Nov
        • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Rafal Somla20 Nov
          • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Rafal Somla20 Nov
            • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Øystein Grøvlen20 Nov
      • RE: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Chuck Bell24 Nov
        • Re: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Rafal Somla25 Nov
          • RE: bzr commit into mysql-6.0-backup branch (Rafal.Somla:2734)Bug#40262Chuck Bell25 Nov