#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#27863 | Alexander Nozdrin | 28 Apr |