diff --git a/sql/slave.cc b/sql/slave.cc
index d2a7d397fa7..8af38624df6 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3111,6 +3111,7 @@ slave_begin:
     sql_print_error("Failed during slave thread initialization");
     goto err;
   }
+  thd->init_for_queries();
   rli->sql_thd= thd;
   thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
   pthread_mutex_lock(&LOCK_thread_count);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 606ecdbecbb..12f0cc4ca72 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -144,9 +144,6 @@ THD::THD():user_time(0), is_fatal_error(0),
   *scramble= '\0';
 
   init();
-  init_sql_alloc(&mem_root,                    // must be after init()
-                 variables.query_alloc_block_size,
-                 variables.query_prealloc_size);
   /* Initialize sub structures */
   bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
   bzero((char*) &warn_root,sizeof(warn_root));
@@ -182,9 +179,6 @@ THD::THD():user_time(0), is_fatal_error(0),
     transaction.trans_log.end_of_file= max_binlog_cache_size;
   }
 #endif
-  init_sql_alloc(&transaction.mem_root,         
-		 variables.trans_alloc_block_size, 
-		 variables.trans_prealloc_size);
   /*
     We need good random number initialization for new thread
     Just coping global one will not work
@@ -227,6 +221,23 @@ void THD::init(void)
 }
 
 
+/*
+  Init THD for query processing.
+  This has to be called once before we call mysql_parse.
+  See also comments in sql_class.h.
+*/
+
+void THD::init_for_queries()
+{
+  init_sql_alloc(&mem_root,
+                 variables.query_alloc_block_size,
+                 variables.query_prealloc_size);
+  init_sql_alloc(&transaction.mem_root,         
+		 variables.trans_alloc_block_size, 
+		 variables.trans_prealloc_size);
+}
+
+
 /*
   Do what's needed when one invokes change user
 
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 546a90d2be3..c1cd65edf76 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -405,7 +405,6 @@ struct system_variables
 
 void free_tmp_table(THD *thd, TABLE *entry);
 
-class Prepared_statement;
 
 /*
   State of a single command executed against this connection.
@@ -760,6 +759,16 @@ public:
   ~THD();
 
   void init(void);
+  /*
+    Initialize memory roots necessary for query processing and (!)
+    pre-allocate memory for it. We can't do that in THD constructor because
+    there are use cases (acl_init, delayed inserts, watcher threads,
+    killing mysqld) where it's vital to not allocate excessive and not used
+    memory. Note, that we still don't return error from init_for_queries():
+    if preallocation fails, we should notice that at the first call to
+    alloc_root. 
+  */
+  void init_for_queries();
   void change_user(void);
   void cleanup(void);
   bool store_globals();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6d975de421f..678d0890136 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -974,6 +974,7 @@ pthread_handler_decl(handle_one_connection,arg)
 
     thd->proc_info=0;
     thd->set_time();
+    thd->init_for_queries();
     while (!net->error && net->vio != 0 && !thd->killed)
     {
       if (do_command(thd))
@@ -1054,6 +1055,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
   thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME));
 
   buff= (char*) thd->net.buff;
+  thd->init_for_queries();
   while (fgets(buff, thd->net.max_packet, file))
   {
     uint length=(uint) strlen(buff);