List:Commits« Previous MessageNext Message »
From:Jon Stephens Date:November 25 2009 9:10am
Subject:Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)
Bug#42851
View as plain text  
Daogang Qu wrote:
> Hi Jon,
> Thanks for your good comments. You missed the two questions.
> Please check them below. Thanks!
> 
> Best Regards,
> 
> Daogang
> 
> 
> Andrei Elkin wrote:
>> Dao-Gang, hello.
>>
>> Although the patch looks really good - I only have some cosmetics-wise 
>> comments - I have one question for the whole idea.
>>
>> The patch introduces the global limit whereas a limit per session 
>> might be a better
>> solution.
>> The global limitting has a drawback that if for instance two 
>> connectons try logging
>> the limit value can be hit by the first-and-only error message of the 
>> 2nd session.
>> Therefore the error-log observer would miss that 2nd session error 
>> message.
>>
>> Was that really disscussed before?
>>
>> Please find my comments inlined.
>>
>> cheers,
>>
>> Andrei
>>
>>
>>  
>>> #At file:///home/daogangqu/mysql/bzrwork/bug42851/mysql-5.1-bugteam/ 
>>> based on revid:davi.arnaut@stripped
>>>
>>>  3192 Dao-Gang.Qu@stripped    2009-11-11
>>>       Bug #42851      Spurious "Statement is not safe to log in 
>>> statement format." warnings
>>>             Warnings in error log make error log grow too large.
>>>             The problem can be resolved by limiting the rate of 
>>> messages that are       written to the log. A volume of messages that 
>>> is less than or equal to       the specified rate is written to the 
>>> log, whereas the volume of messages       that exceeds the rate is 
>>> discarded.
>>>             For example,
>>>             log-warnings-ratelimit-interval = 10
>>>       log-warnings-ratelimit-burst = 5
>>>             This allows 5 log messages per 10 seconds. The sixth (and 
>>> posterior)
>>>       attempts to write a log message within a 10 seconds interval are
>>>       discarded.
>>>     
>>
>> good.
>>
>>  
>>>      @ mysql-test/suite/rpl/r/rpl_ratelimit_warnings.result
>>>         Test Result for BUG#42851.
>>>      @ mysql-test/suite/rpl/t/rpl_ratelimit_warnings.test
>>>         Added the test file to verify if the rate limit works fine.
>>>      @ sql/log.cc
>>>         Added the implementation of the 'Rate_limit' class.
>>>      @ sql/log.h
>>>         Added the definition of the 'Rate_limit' class.
>>>      @ sql/mysqld.cc
>>>         Added OPT_LOG_WARNINGS_RATELIMIT_INTERVAL and 
>>> OPT_LOG_WARNINGS_RATELIMIT_BURST         options for rate limit.
>>>
>>>     added:
>>>       mysql-test/suite/rpl/r/rpl_ratelimit_warnings.result
>>>       mysql-test/suite/rpl/t/rpl_ratelimit_warnings-master.opt
>>>       mysql-test/suite/rpl/t/rpl_ratelimit_warnings-slave.opt
>>>       mysql-test/suite/rpl/t/rpl_ratelimit_warnings.test
>>>     modified:
>>>       sql/log.cc
>>>       sql/log.h
>>>       sql/mysqld.cc
>>> === added file 'mysql-test/suite/rpl/r/rpl_ratelimit_warnings.result'
>>> --- a/mysql-test/suite/rpl/r/rpl_ratelimit_warnings.result    
>>> 1970-01-01 00:00:00 +0000
>>> +++ b/mysql-test/suite/rpl/r/rpl_ratelimit_warnings.result    
>>> 2009-11-11 06:45:07 +0000
>>> @@ -0,0 +1,26 @@
>>> +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;
>>> +call mtr.add_suppression("Burst exceeded, rate limiting.");
>>> +call mtr.add_suppression("Rate limit lifted, .* warning messages 
>>> were suppressed.");
>>> +CREATE TABLE `t1` (
>>> +`recNo` int(10) unsigned NOT NULL AUTO_INCREMENT,
>>> +`string` varchar(64) NOT NULL,
>>> +`inUseBy` varchar(38) NOT NULL DEFAULT '',
>>> +`tsLastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
>>> +CURRENT_TIMESTAMP,
>>> +PRIMARY KEY (`recNo`),
>>> +KEY `tsLastUpdated` (`tsLastUpdated`),
>>> +KEY `inUseBy` (`inUseBy`)
>>> +);
>>> +INSERT INTO t1 SET string='one';
>>> +INSERT INTO t1 SET string='two';
>>> +INSERT INTO t1 SET string='three';
>>> +# above query will produce a warning
>>> +SHOW WARNINGS;
>>> +Level    Code    Message
>>> +Note    1592    Statement may not be safe to log in statement format.
>>> +drop table t1;
>>>
>>> === added file 
>>> 'mysql-test/suite/rpl/t/rpl_ratelimit_warnings-master.opt'
>>> --- a/mysql-test/suite/rpl/t/rpl_ratelimit_warnings-master.opt    
>>> 1970-01-01 00:00:00 +0000
>>> +++ b/mysql-test/suite/rpl/t/rpl_ratelimit_warnings-master.opt    
>>> 2009-11-11 06:45:07 +0000
>>> @@ -0,0 +1 @@
>>> +--log-warnings-ratelimit-interval=10 --log-warnings-ratelimit-burst=5
>>>
>>> === added file 'mysql-test/suite/rpl/t/rpl_ratelimit_warnings-slave.opt'
>>> --- a/mysql-test/suite/rpl/t/rpl_ratelimit_warnings-slave.opt    
>>> 1970-01-01 00:00:00 +0000
>>> +++ b/mysql-test/suite/rpl/t/rpl_ratelimit_warnings-slave.opt    
>>> 2009-11-11 06:45:07 +0000
>>> @@ -0,0 +1 @@
>>> +--log-warnings-ratelimit-interval=10 --log-warnings-ratelimit-burst=5
>>>
>>> === added file 'mysql-test/suite/rpl/t/rpl_ratelimit_warnings.test'
>>> --- a/mysql-test/suite/rpl/t/rpl_ratelimit_warnings.test    
>>> 1970-01-01 00:00:00 +0000
>>> +++ b/mysql-test/suite/rpl/t/rpl_ratelimit_warnings.test    
>>> 2009-11-11 06:45:07 +0000
>>> @@ -0,0 +1,44 @@
>>> +#
>>> +# BUG#42851
>>> +# This test verifies if rate limit allows at most 5 log messages +# 
>>> per 10 seconds. The sixth (and posterior) attempts to write a +# log 
>>> message within a 10 seconds interval are discarded.
>>> +#
>>> +
>>> +source include/master-slave.inc;
>>> +source include/have_binlog_format_statement.inc;
>>> +
>>> +call mtr.add_suppression("Burst exceeded, rate limiting.");
>>> +call mtr.add_suppression("Rate limit lifted, .* warning messages 
>>> were suppressed.");
>>> +# create table
>>> +CREATE TABLE `t1` (
>>> +  `recNo` int(10) unsigned NOT NULL AUTO_INCREMENT,
>>> +  `string` varchar(64) NOT NULL,
>>> +  `inUseBy` varchar(38) NOT NULL DEFAULT '',
>>> +  `tsLastUpdated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON 
>>> UPDATE
>>> +CURRENT_TIMESTAMP,
>>> +  PRIMARY KEY (`recNo`),
>>> +  KEY `tsLastUpdated` (`tsLastUpdated`),
>>> +  KEY `inUseBy` (`inUseBy`)
>>> +);
>>> +# insert test data
>>> +INSERT INTO t1 SET string='one';
>>> +INSERT INTO t1 SET string='two';
>>> +INSERT INTO t1 SET string='three';
>>> +# grab one record
>>> +let $count=5000;
>>> +--disable_warnings
>>> +--disable_query_log
>>> +while ($count)
>>> +{
>>> +  UPDATE t1 SET inUseBy='me' WHERE inUseBy='' limit 1;
>>> +  dec $count;
>>> +}
>>> +--enable_query_log
>>> +--enable_warnings
>>> +--echo # above query will produce a warning
>>> +SHOW WARNINGS;
>>> +
>>> +drop table t1;
>>> +sync_slave_with_master;
>>> +
>>>
>>> === modified file 'sql/log.cc'
>>> --- a/sql/log.cc    2009-10-23 00:03:41 +0000
>>> +++ b/sql/log.cc    2009-11-11 06:45:07 +0000
>>> @@ -51,6 +51,8 @@ LOGGER logger;
>>>  
>>>  MYSQL_BIN_LOG mysql_bin_log;
>>>  ulong sync_binlog_counter= 0;
>>> +ulong log_warnings_ratelimit_interval;
>>> +ulong log_warnings_ratelimit_burst;
>>>  
>>>  static bool test_if_number(const char *str,
>>>                 long *res, bool allow_wildcards);
>>> @@ -737,11 +739,80 @@ bool Log_to_csv_event_handler::
>>>    return FALSE;
>>>  }
>>>  
>>> +
>>> +Rate_limit::Rate_limit()
>>> +  : m_count(0), m_suppressed(0), m_begin(0), +    interval(0), burst(0)
>>> +{}
>>> +
>>> +Rate_limit::~Rate_limit()
>>> +{}
>>> +
>>> +void Rate_limit::rate_limit_exceeded()
>>> +{}
>>> +
>>> +void Rate_limit::rate_limit_reset(unsigned int suppressed)
>>> +{}
>>> +
>>> +bool Rate_limit::rate_limit_impl()
>>> +{
>>> +  unsigned int suppressed= 0;
>>> +  bool exceeds, notify_exceeded= false;
>>> +
>>> +  if (!m_begin)
>>> +    m_begin= my_time(0);
>>> +
>>> +  if ((m_begin + interval) < my_time(0))
>>> +  {
>>> +    /* Interval has elapsed, reset counters. */
>>> +    suppressed= m_suppressed;
>>> +    m_begin= 0;
>>> +    m_count= m_suppressed= 0;
>>> +  }
>>> +
>>> +  /* Whether burst limit has been surpassed. */
>>> +  exceeds= (burst && burst <= m_count);
>>> +
>>> +  /*
>>> +    Issue a notification callback only if the the
>>> +    limit has been surpassed for the first time.
>>> +  */
>>> +  if (exceeds)
>>> +    notify_exceeded= !(m_suppressed++);
>>> +  else
>>> +    m_count++;
>>> +
>>> +  if (suppressed)
>>> +    rate_limit_reset(suppressed);
>>> +
>>> +  if (notify_exceeded)
>>> +    rate_limit_exceeded();
>>> +
>>> +  return !exceeds;
>>> +}
>>> +
>>> +
>>>  bool Log_to_file_event_handler::
>>>    log_error(enum loglevel level, const char *format,
>>>              va_list args)
>>>  {
>>> -  return vprint_msg_to_log(level, format, args);
>>> +  bool rv= false;
>>> +
>>> +  if ((level != WARNING_LEVEL) || rate_limit())
>>> +    rv= vprint_msg_to_log(level, format, args);
>>> +
>>> +  return rv;
>>> +}
>>> +
>>> +void Log_to_file_event_handler::rate_limit_exceeded()
>>> +{
>>>     
>>
>>  
>>> +  sql_print_error("Burst exceeded, rate limiting.");
>>>     
>>
>> I suggest slightly extend the text to make is certainly readable by
>> a human being not just a programmer.
>>
>> " log-warnings-ratelimit-burst parameter's value (N) exceeded; discarding
>>   the rest of error messages "
>>
>> where N stands for the actual value of the parameter.
>>
>>
>>  
>>> +}
>>> +
>>> +void Log_to_file_event_handler::rate_limit_reset(unsigned int 
>>> suppressed)
>>> +{
>>> +  sql_print_error("Rate limit lifted, %u warning messages were 
>>> suppressed.",
>>> +                  suppressed);
>>>  }
>>>  
>>>  void Log_to_file_event_handler::init_pthread_objects()
>>>
>>> === modified file 'sql/log.h'
>>> --- a/sql/log.h    2009-06-18 13:52:46 +0000
>>> +++ b/sql/log.h    2009-11-11 06:45:07 +0000
>>> @@ -16,6 +16,9 @@
>>>  #ifndef LOG_H
>>>  #define LOG_H
>>>  
>>> +extern ulong log_warnings_ratelimit_interval;
>>> +extern ulong log_warnings_ratelimit_burst;
>>> +
>>>  class Relay_log_info;
>>>  
>>>  class Format_description_log_event;
>>> @@ -459,15 +462,87 @@ public:
>>>  };
>>>  
>>>  
>>> +/**
>>> +  Rate limiter.
>>> +*/
>>> +
>>> +class Rate_limit
>>> +{
>>> +  public:
>>> +    Rate_limit();
>>> +    virtual ~Rate_limit();
>>> +
>>> +  private:
>>> +    unsigned int interval;
>>> +    unsigned int burst;
>>> +    unsigned int m_count;
>>> +    unsigned int m_suppressed;
>>> +    time_t m_begin;
>>> +
>>> +  private:
>>> +    bool rate_limit_impl();
>>> +
>>> +  protected:
>>> +    /** Rate limit exceeded notification. */
>>> +    virtual void rate_limit_exceeded();
>>> +
>>> +    /**
>>> +      Rate limit lifted notification.
>>> +
>>> +      @param suppressed Number of suppressed attempts.
>>> +    */
>>> +    virtual void rate_limit_reset(unsigned int suppressed);
>>> +
>>> +  public:
>>> +    /**
>>> +      Enforce a rate limit based on the number of successive
>>> +      calls per time interval, e.g. Rate_limit::burst calls
>>> +      per Rate_limit::interval.
>>> +
>>> +      @remark Designed to mitigate DoS attacks.
>>> +
>>> +      @return         Whether a attempt falls within the limit.
>>> +      @retval true    Within rate limit.
>>> +      @retval false   Rate limit exceeded.
>>> +    */
>>> +    bool rate_limit()
>>> +    {
>>> +      return interval ? rate_limit_impl() : true;
>>> +    }
>>> +
>>> +    /**
>>> +      Set interval of rate limit.
>>> +      @param The interval of rate limit.
>>> +    */
>>> +    void set_interval(unsigned int ratelimit_interval)
>>> +    {
>>> +      interval= ratelimit_interval;
>>> +    }
>>> +
>>> +    /**
>>> +      Set burst of rate limit.
>>> +      @param The burst of rate limit.
>>> +    */
>>> +    void set_burst(unsigned int ratelimit_burst)
>>> +    {
>>> +      burst= ratelimit_burst;
>>> +    }
>>> +};
>>> +
>>> +
>>>  /* type of the log table */
>>>  #define QUERY_LOG_SLOW 1
>>>  #define QUERY_LOG_GENERAL 2
>>>  
>>> -class Log_to_file_event_handler: public Log_event_handler
>>> +class Log_to_file_event_handler: public Log_event_handler,
>>> +                                 public Rate_limit
>>>  {
>>>    MYSQL_QUERY_LOG mysql_log;
>>>    MYSQL_QUERY_LOG mysql_slow_log;
>>>    bool is_initialized;
>>> +protected:
>>> +  void rate_limit_exceeded();
>>> +  void rate_limit_reset(unsigned int suppressed);
>>>  public:
>>>    Log_to_file_event_handler(): is_initialized(FALSE)
>>>    {}
>>> @@ -565,6 +640,10 @@ public:
>>>        return file_log_handler->get_mysql_log();
>>>      return NULL;
>>>    }
>>> +  Log_to_file_event_handler *get_log_file_event_handler()
>>> +  {
>>> +    return file_log_handler;
>>> +  }
>>>  };
>>>  
>>>  enum enum_binlog_format {
>>>
>>> === modified file 'sql/mysqld.cc'
>>> --- a/sql/mysqld.cc    2009-11-03 00:52:57 +0000
>>> +++ b/sql/mysqld.cc    2009-11-11 06:45:07 +0000
>>> @@ -5700,7 +5700,9 @@ enum options_mysqld
>>>    OPT_SLAVE_EXEC_MODE,
>>>    OPT_GENERAL_LOG_FILE,
>>>    OPT_SLOW_QUERY_LOG_FILE,
>>> -  OPT_IGNORE_BUILTIN_INNODB
>>> +  OPT_IGNORE_BUILTIN_INNODB,
>>> +  OPT_LOG_WARNINGS_RATELIMIT_INTERVAL,
>>> +  OPT_LOG_WARNINGS_RATELIMIT_BURST
>>>  };
>>>  
>>>  
>>> @@ -6046,6 +6048,18 @@ log and this option justs turns on --log
>>>     (uchar**) &global_system_variables.log_warnings,
>>>     (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, 
>>> OPT_ARG, 1, 0, 0,
>>>     0, 0, 0},
>>>     
>>
>> Explanations of parameters for mysqld --help I would suggest to 
>> discuss with docs
>> people. Jon would be great to master short english text here.
>> I dare to suggest my personal version for the 2 params.
>>
>>  
>>> +  {"log-warnings-ratelimit-interval", 
>>> OPT_LOG_WARNINGS_RATELIMIT_INTERVAL,
>>> +   "Minimum length of time between which successive warning messages 
>>> are "
>>> +   "written to the log file.",
>>>     
>>
>> "Time interval within which error messages logging is limitted 
>> according to
>> --log-warnings-ratelimit-burst value"
>>   
> Hi Jon,
> What's you idea about the description?

"The interval to which the number of warnings specified by 
--log-warnings-volume applies"

> 
> Best Regards,
> 
> Daogang
>>  
>>> +   (uchar**) &log_warnings_ratelimit_interval,
>>> +   (uchar**) &log_warnings_ratelimit_interval,
>>> +   0, GET_ULONG, REQUIRED_ARG, 5, 0, 0, 0, 0, 0},
>>>     
>>
>>  
>>> +  {"log-warnings-ratelimit-burst", OPT_LOG_WARNINGS_RATELIMIT_BURST,
>>> +   "Number of warning messages within a interval that shall trigger "
>>> +   "rate limiting.",
>>>     
>>
>> "The limit for the number of warnings that can be error-logged within
>> --log-warnings-ratelimit-interval value; exceeding messages are not 
>> logged"
>>
>>   
> Hi Jon,
> What's you idea about the description?

"The maximum number of warnings logged within the period specified by 
--log-warnings-interval"

> 
> Best Regards,
> 
> Daogang


-- 


Jon Stephens - jon.stephens@stripped
Technical Writer
MySQL Documentation Team
Sun Microsystems AB
MySQL and Software Infrastructure Group
Liljeholmen (Stockholm), Sweden
Summer: UTC +02.00 / Winter: UTC +01.00
Mobile: +46 (0) 736 773 993
Skype: plastic-fish
MySQL: www.mysql.com
Sun: www.sun.com

Thread
bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192) Bug#42851Dao-Gang.Qu23 Nov
  • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut23 Nov
    • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Daogang Qu24 Nov
    • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Daogang Qu24 Nov
      • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Jon Stephens24 Nov
        • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Daogang Qu24 Nov
        • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut24 Nov
          • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Jon Stephens25 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Daogang Qu24 Nov
  • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Jon Stephens25 Nov
    • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Daogang Qu25 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut24 Nov
  • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut24 Nov
    • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851He Zhenxing26 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut24 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851He Zhenxing26 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut26 Nov
  • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851He Zhenxing27 Nov
    • Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut27 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut26 Nov
Re: bzr commit into mysql-5.1-bugteam branch (Dao-Gang.Qu:3192)Bug#42851Davi Arnaut26 Nov