List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:April 28 2010 4:47pm
Subject:bzr commit into mysql-next-mr-bugfixing branch (alik:3144) Bug#27863
View as plain text  
#At file:///mnt/raid/alik/MySQL/bzr/00/bug27863/mysql-next-mr-bf-bug27863.2/ based on revid:alik@stripped

 3144 Alexander Nozdrin	2010-04-28
      A patch for Bug#27863 (excessive memory usage for many small queries
      in a multiquery packet).
      
      This patch fixes issue #1 described in the bug report:
      1) Lex_input_stream allocates more memory on its construction than it is
         ever going to need
      
      The fix is to allocate a buffer (cpp_buffer) once for a multiquery packet.

    modified:
      sql/event_data_objects.cc
      sql/ha_ndbcluster_binlog.cc
      sql/log_event.cc
      sql/mysql_priv.h
      sql/sp.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_partition.cc
      sql/sql_prepare.cc
      sql/sql_trigger.cc
      sql/sql_view.cc
=== modified file 'sql/event_data_objects.cc'
--- a/sql/event_data_objects.cc	2010-01-30 19:37:52 +0000
+++ b/sql/event_data_objects.cc	2010-04-28 16:47:28 +0000
@@ -1435,7 +1435,13 @@ Event_job_data::execute(THD *thd, bool d
   thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
 
   {
-    Parser_state parser_state(thd, thd->query(), thd->query_length());
+    char *cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+    if (!cpp_buffer)
+      goto end;
+
+    Parser_state parser_state(thd, thd->query(), thd->query_length(),
+                              cpp_buffer);
     lex_start(thd);
 
     if (parse_sql(thd, & parser_state, creation_ctx))

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2010-03-13 10:58:27 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2010-04-28 16:47:28 +0000
@@ -255,6 +255,7 @@ static void run_query(THD *thd, char *bu
   DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->variables.option_bits));
   NET save_thd_net= thd->net;
   const char* found_semicolon= NULL;
+  char *cpp_buffer;
 
   bzero((char*) &thd->net, sizeof(NET));
   thd->set_query(buf, (uint) (end - buf));
@@ -268,7 +269,13 @@ static void run_query(THD *thd, char *bu
   DBUG_ASSERT(!thd->in_sub_stmt);
   DBUG_ASSERT(!thd->locked_tables_mode);
 
-  mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon);
+  cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+  if (!cpp_buffer)
+    return;
+
+  mysql_parse(thd, thd->query(), thd->query_length(), cpp_buffer,
+              &found_semicolon);
 
   if (no_print_error && thd->is_slave_error)
   {

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2010-03-20 09:35:40 +0000
+++ b/sql/log_event.cc	2010-04-28 16:47:28 +0000
@@ -3274,7 +3274,13 @@ int Query_log_event::do_apply_event(Rela
       
       /* Execute the query (note that we bypass dispatch_command()) */
       const char* found_semicolon= NULL;
-      mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon);
+      char *cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+      if (!cpp_buffer)
+        goto end;
+
+      mysql_parse(thd, thd->query(), thd->query_length(), cpp_buffer,
+                  &found_semicolon);
       log_slow_statement(thd);
 
       /*

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2010-03-22 10:36:23 +0000
+++ b/sql/mysql_priv.h	2010-04-28 16:47:28 +0000
@@ -1088,9 +1088,10 @@ bool mysql_opt_change_db(THD *thd,
                          bool *cur_db_changed);
 
 void mysql_parse(THD *thd, const char *inBuf, uint length,
+                 char *cpp_buffer,
                  const char ** semicolon);
 
-bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
+bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length);
 bool is_update_query(enum enum_sql_command command);
 bool is_log_table_write_query(enum enum_sql_command command);
 bool alloc_query(THD *thd, const char *packet, uint packet_length);

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	2010-03-20 09:35:40 +0000
+++ b/sql/sp.cc	2010-04-28 16:47:28 +0000
@@ -713,7 +713,12 @@ static sp_head *sp_compile(THD *thd, Str
   thd->variables.sql_mode= sql_mode;
   thd->variables.select_limit= HA_POS_ERROR;
 
-  Parser_state parser_state(thd, defstr->c_ptr(), defstr->length());
+  char *cpp_buffer= (char *) thd->alloc(defstr->length() + 1);
+
+  if (!cpp_buffer)
+    return NULL;
+
+  Parser_state parser_state(thd, defstr->c_ptr(), defstr->length(), cpp_buffer);
   lex_start(thd);
   thd->push_internal_handler(&warning_handler);
   thd->spcont= 0;

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-03-22 10:36:23 +0000
+++ b/sql/sql_lex.cc	2010-04-28 16:47:28 +0000
@@ -138,7 +138,8 @@ st_parsing_options::reset()
 
 Lex_input_stream::Lex_input_stream(THD *thd,
                                    const char* buffer,
-                                   unsigned int length)
+                                   unsigned int length,
+                                   char *cpp_buffer)
 : m_thd(thd),
   yylineno(1),
   yytoklen(0),
@@ -153,6 +154,8 @@ Lex_input_stream::Lex_input_stream(THD *
   m_buf(buffer),
   m_buf_length(length),
   m_echo(TRUE),
+  m_cpp_buf(cpp_buffer),
+  m_cpp_ptr(m_cpp_buf),
   m_cpp_tok_start(NULL),
   m_cpp_tok_start_prev(NULL),
   m_cpp_tok_end(NULL),
@@ -166,8 +169,7 @@ Lex_input_stream::Lex_input_stream(THD *
   in_comment(NO_COMMENT),
   m_underscore_cs(NULL)
 {
-  m_cpp_buf= (char*) thd->alloc(length + 1);
-  m_cpp_ptr= m_cpp_buf;
+  DBUG_ASSERT(m_cpp_buf);
 }
 
 Lex_input_stream::~Lex_input_stream()

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-03-22 10:36:23 +0000
+++ b/sql/sql_lex.h	2010-04-28 16:47:28 +0000
@@ -1345,7 +1345,8 @@ enum enum_comment_state
 class Lex_input_stream
 {
 public:
-  Lex_input_stream(THD *thd, const char* buff, unsigned int length);
+  Lex_input_stream(THD *thd, const char* buff, unsigned int length,
+                   char *cpp_buffer);
   ~Lex_input_stream();
 
   /**
@@ -2245,8 +2246,9 @@ public:
 class Parser_state
 {
 public:
-  Parser_state(THD *thd, const char* buff, unsigned int length)
-    : m_lip(thd, buff, length), m_yacc()
+  Parser_state(THD *thd, const char* buff, unsigned int length,
+               char *cpp_buffer)
+    : m_lip(thd, buff, length, cpp_buffer), m_yacc()
   {}
 
   ~Parser_state()

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-03-20 09:35:40 +0000
+++ b/sql/sql_parse.cc	2010-04-28 16:47:28 +0000
@@ -423,6 +423,8 @@ static void handle_bootstrap_impl(THD *t
   while (mysql_file_fgets(buff, thd->net.max_packet, file))
   {
     char *query;
+    char *cpp_buffer;
+
     /* strlen() can't be deleted because mysql_file_fgets() doesn't return length */
     ulong length= (ulong) strlen(buff);
     while (buff[length-1] != '\n' && !mysql_file_feof(file))
@@ -470,7 +472,12 @@ static void handle_bootstrap_impl(THD *t
       mode we have only one thread.
     */
     thd->set_time();
-    mysql_parse(thd, thd->query(), length, & found_semicolon);
+    cpp_buffer= (char *) thd->alloc(length + 1);
+
+    if (!cpp_buffer)
+      break;
+
+    mysql_parse(thd, thd->query(), length, cpp_buffer, &found_semicolon);
     close_thread_tables(thd);			// Free tables
 
     bootstrap_error= thd->is_error();
@@ -1021,7 +1028,12 @@ bool dispatch_command(enum enum_server_c
     thd->profiling.set_query_source(thd->query(), thd->query_length());
 #endif
 
-    mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt);
+    char *cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+    if (!cpp_buffer)
+      break;
+
+    mysql_parse(thd, thd->query(), thd->query_length(), cpp_buffer, &end_of_stmt);
 
     while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error())
     {
@@ -1067,7 +1079,7 @@ bool dispatch_command(enum enum_server_c
       statistic_increment(thd->status_var.questions, &LOCK_status);
       thd->set_time(); /* Reset the query start time. */
       /* TODO: set thd->lex->sql_command to SQLCOM_END here */
-      mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
+      mysql_parse(thd, beginning_of_next_stmt, length, cpp_buffer, &end_of_stmt);
     }
 
     DBUG_PRINT("info",("query ready"));
@@ -5656,6 +5668,7 @@ void mysql_init_multi_delete(LEX *lex)
 */
 
 void mysql_parse(THD *thd, const char *inBuf, uint length,
+                 char *cpp_buffer,
                  const char ** found_semicolon)
 {
   int error;
@@ -5686,7 +5699,7 @@ void mysql_parse(THD *thd, const char *i
   {
     LEX *lex= thd->lex;
 
-    Parser_state parser_state(thd, inBuf, length);
+    Parser_state parser_state(thd, inBuf, length, cpp_buffer);
 
     bool err= parse_sql(thd, & parser_state, NULL);
     *found_semicolon= parser_state.m_lip.found_semicolon;
@@ -5781,9 +5794,13 @@ bool mysql_test_parse_for_slave(THD *thd
 {
   LEX *lex= thd->lex;
   bool error= 0;
+  char *cpp_buffer= (char *) thd->alloc(length + 1);
   DBUG_ENTER("mysql_test_parse_for_slave");
 
-  Parser_state parser_state(thd, inBuf, length);
+  if (!cpp_buffer)
+    DBUG_RETURN(TRUE);
+
+  Parser_state parser_state(thd, inBuf, length, cpp_buffer);
   lex_start(thd);
   mysql_reset_thd_for_next_command(thd);
 

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2010-03-22 10:36:23 +0000
+++ b/sql/sql_partition.cc	2010-04-28 16:47:28 +0000
@@ -4175,11 +4175,15 @@ bool mysql_unpack_partition(THD *thd,
   CHARSET_INFO *old_character_set_client= thd->variables.character_set_client;
   LEX *old_lex= thd->lex;
   LEX lex;
+  char *cpp_buffer= (char *) thd->alloc(part_info_len + 1);
   DBUG_ENTER("mysql_unpack_partition");
 
+  if (!cpp_buffer)
+    DBUG_RETURN(TRUE);
+
   thd->variables.character_set_client= system_charset_info;
 
-  Parser_state parser_state(thd, part_buf, part_info_len);
+  Parser_state parser_state(thd, part_buf, part_info_len, cpp_buffer);
 
   if (init_lex_with_single_table(thd, table, &lex))
     goto end;

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2010-03-11 13:47:34 +0000
+++ b/sql/sql_prepare.cc	2010-04-28 16:47:28 +0000
@@ -2926,11 +2926,17 @@ bool
 Execute_sql_statement::execute_server_code(THD *thd)
 {
   bool error;
+  char *cpp_buffer;
 
   if (alloc_query(thd, m_sql_text.str, m_sql_text.length))
     return TRUE;
 
-  Parser_state parser_state(thd, thd->query(), thd->query_length());
+  cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+  if (!cpp_buffer)
+    return TRUE;
+
+  Parser_state parser_state(thd, thd->query(), thd->query_length(), cpp_buffer);
 
   parser_state.m_lip.multi_statements= FALSE;
   lex_start(thd);
@@ -3139,6 +3145,7 @@ bool Prepared_statement::prepare(const c
   Statement stmt_backup;
   Query_arena *old_stmt_arena;
   MDL_ticket *mdl_savepoint= NULL;
+  char *cpp_buffer;
   DBUG_ENTER("Prepared_statement::prepare");
   /*
     If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
@@ -3167,10 +3174,19 @@ bool Prepared_statement::prepare(const c
     DBUG_RETURN(TRUE);
   }
 
+  cpp_buffer= (char *) thd->alloc(thd->query_length() + 1);
+
+  if (!cpp_buffer)
+  {
+    thd->restore_backup_statement(this, &stmt_backup);
+    thd->restore_active_arena(this, &stmt_backup);
+    DBUG_RETURN(TRUE);
+  }
+
   old_stmt_arena= thd->stmt_arena;
   thd->stmt_arena= this;
 
-  Parser_state parser_state(thd, thd->query(), thd->query_length());
+  Parser_state parser_state(thd, thd->query(), thd->query_length(), cpp_buffer);
   parser_state.m_lip.stmt_prepare_mode= TRUE;
   parser_state.m_lip.multi_statements= FALSE;
   lex_start(thd);

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2010-02-24 13:52:27 +0000
+++ b/sql/sql_trigger.cc	2010-04-28 16:47:28 +0000
@@ -1113,6 +1113,8 @@ bool Table_triggers_list::check_n_load(T
       Table_triggers_list *triggers=
         new (&table->mem_root) Table_triggers_list(table);
       Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str);
+      char *cpp_buffer= NULL;
+      int cpp_buffer_length= 0;
 
       if (!triggers)
         DBUG_RETURN(1);
@@ -1306,11 +1308,21 @@ bool Table_triggers_list::check_n_load(T
         trg_sql_mode= itm++;
         LEX_STRING *trg_definer= it_definer++;
 
+        if (cpp_buffer_length < trg_create_str->length + 1)
+        {
+          cpp_buffer_length= trg_create_str->length + 1;
+          cpp_buffer= (char *) thd->alloc(cpp_buffer_length);
+        }
+
+        if (!cpp_buffer)
+          goto err_without_lex_cleanup;
+
         thd->variables.sql_mode= (ulong)*trg_sql_mode;
 
         Parser_state parser_state(thd,
                                   trg_create_str->str,
-                                  trg_create_str->length);
+                                  trg_create_str->length,
+                                  cpp_buffer);
 
         Trigger_creation_ctx *creation_ctx=
           Trigger_creation_ctx::create(thd,
@@ -1456,6 +1468,8 @@ bool Table_triggers_list::check_n_load(T
 err_with_lex_cleanup:
       // QQ: anything else ?
       lex_end(&lex);
+
+err_without_lex_cleanup:
       thd->lex= old_lex;
       thd->spcont= save_spcont;
       thd->variables.sql_mode= save_sql_mode;

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2010-03-20 09:35:40 +0000
+++ b/sql/sql_view.cc	2010-04-28 16:47:28 +0000
@@ -1173,9 +1173,18 @@ bool mysql_make_view(THD *thd, File_pars
     char old_db_buf[NAME_LEN+1];
     LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
     bool dbchanged;
+    char *cpp_buffer= (char *) thd->alloc(table->select_stmt.length + 1);
+
+    if (!cpp_buffer)
+    {
+      result= TRUE;
+      goto end;
+    }
+
     Parser_state parser_state(thd,
                               table->select_stmt.str,
-                              table->select_stmt.length);
+                              table->select_stmt.length,
+                              cpp_buffer);
 
     /* 
       Use view db name as thread default database, in order to ensure


Attachment: [text/bzr-bundle] bzr/alik@sun.com-20100428164728-e819245bpsr2qgcl.bundle
Thread
bzr commit into mysql-next-mr-bugfixing branch (alik:3144) Bug#27863Alexander Nozdrin28 Apr