MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:dlenev Date:April 12 2006 10:53am
Subject:bk commit into 5.0 tree (dlenev:1.2139) BUG#17260
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2139 06/04/12 14:53:03 dlenev@stripped +1 -0
  Draft fix for bug #17260 "Multiple invocations of triggers or stored functions
  hog memory".
  
  During each invocation of stored function or trigger some objects which
  lifetime is one function call (e.g. sp_rcontext) were allocated on
  arena/memroot of calling statement. This led to consumption of fixed amount
  of memory for each function/trigger invocation and so statements which
  involve lot of them were hogging memory. This in its return led to OOM
  crashes or freezes.
  
  This fix introduces new memroot and arena for objects which lifetime is
  whole duration of function call. So all memory consumed by such objects
  is freed at the end of function call.

  sql/sp_head.cc
    1.206 06/04/12 14:52:59 dlenev@stripped +49 -10
    sp_head::execute_function():
      Introduced new memroot and arena for objects which lifetime is whole
      duration of function call (e.g. sp_rcontext, param_values array). We can't
      use caller's arena/memroot for those objects because in this case 
      some fixed amount of memory will be consumed for each function/trigger
      invocation and so statements which involve lot of them will hog memory.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	dlenev
# Host:	jabberwock.site
# Root:	/home/dlenev/mysql-5.0-bg17260

--- 1.205/sql/sp_head.cc	2006-03-21 16:35:45 +03:00
+++ 1.206/sql/sp_head.cc	2006-04-12 14:52:59 +04:00
@@ -1210,10 +1210,24 @@
   sp_rcontext *octx = thd->spcont;
   sp_rcontext *nctx = NULL;
   bool err_status= FALSE;
+  MEM_ROOT call_mem_root;
+  Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP),
+              backup_arena;
 
   DBUG_ENTER("sp_head::execute_function");
   DBUG_PRINT("info", ("function %s", m_name.str));
 
+  /*
+    Prepare arena and memroot for objects which lifetime is whole
+    duration of function call (e.g. sp_rcontext, param_values array).
+    We can't use caller's arena/memroot for those objects because
+    in this case some fixed amount of memory will be consumed for
+    each function/trigger invocation and so statements which involve
+    lot of them will hog memory.
+  */
+  init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+  thd->set_n_backup_active_arena(&call_arena, &backup_arena);
+
   params = m_pcont->context_pvars();
 
   /*
@@ -1231,21 +1245,25 @@
     */
     my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0),
              "FUNCTION", m_qname.str, params, argcount);
-    DBUG_RETURN(TRUE);
+    err_status= TRUE;
+    goto err_with_cleanup;
   }
 
   /* Allocate param_values to be used for dumping the call into binlog. */
 
   if (!(param_values= (Item_cache**)thd->alloc(sizeof(Item_cache*)*argcount)))
-    DBUG_RETURN(TRUE);
+  {
+    err_status= TRUE;
+    goto err_with_cleanup;
+  }
 
   // QQ Should have some error checking here? (types, etc...)
 
   if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
       nctx->init(thd))
   {
-    delete nctx; /* Delete nctx if it was init() that failed. */
-    DBUG_RETURN(TRUE);
+    err_status= TRUE;
+    goto err_with_cleanup;
   }
 
 #ifndef DBUG_OFF
@@ -1256,7 +1274,16 @@
 
   {
     uint i;
-    
+    Item_result item_cache_type;
+
+    /*
+      We have to switch temporarily back to callers arena/memroot.
+      Function arguments belong to the caller and so the may reference
+      memory which they will allocate during calculation long after
+      this function call will be finished (e.g. in Item::cleanup()).
+    */
+    thd->restore_active_arena(&call_arena, &backup_arena);
+
     for (i= 0 ; i < argcount ; i++)
     {
       if (!argp[i]->fixed && argp[i]->fix_fields(thd, &argp[i]))
@@ -1265,7 +1292,16 @@
         break;
       }
 
-      param_values[i]= Item_cache::get_cache(argp[i]->result_type());
+      item_cache_type= argp[i]->result_type();
+      /*
+        But lifetime of Item_cache_* objects is function call
+        therefor they have to be allocated on call arena otherwise
+        we will get memory hogging again.
+      */
+      thd->set_n_backup_active_arena(&call_arena, &backup_arena);
+      param_values[i]= Item_cache::get_cache(item_cache_type);
+      thd->restore_active_arena(&call_arena, &backup_arena);
+
       param_values[i]->store(argp[i]);
 
       if (nctx->set_variable(thd, i, param_values[i]))
@@ -1274,13 +1310,11 @@
         break;
       }
     }
+    thd->set_n_backup_active_arena(&call_arena, &backup_arena);
   }
 
   if (err_status)
-  {
-    delete nctx;
-    DBUG_RETURN(TRUE);
-  }
+    goto err_with_cleanup;
 
   thd->spcont= nctx;
 
@@ -1348,8 +1382,13 @@
   }
 
   nctx->pop_all_cursors();	// To avoid memory leaks after an error
+
+err_with_cleanup:
   delete nctx;
   thd->spcont= octx;
+  thd->free_items();
+  thd->restore_active_arena(&call_arena, &backup_arena);
+  free_root(&call_mem_root, MYF(0));
 
   DBUG_RETURN(err_status);
 }
Thread
bk commit into 5.0 tree (dlenev:1.2139) BUG#17260dlenev12 Apr