List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:May 18 2009 11:37am
Subject:bzr commit into mysql-6.1-fk branch (dlenev:2734) WL#148
View as plain text  
#At file:///home/dlenev/src/bzr/mysql-6.1-mil14/ based on revid:kostja@stripped

 2734 Dmitry Lenev	2009-05-18
      WL#148 "Foreign keys".
      
      Milestone 14 "DDL checks and changes: DROP, TRUNCATE, RENAME".
      
      Tentative patch that tries to get rid of per-execution MDL request
      allocation by introducing per-table per-execution context for DROP
      TABLE operation.

    modified:
      sql/ha_ndbcluster.cc
      sql/sql_db.cc
      sql/sql_table.cc
      sql/table.h
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2009-04-22 22:12:25 +0000
+++ b/sql/ha_ndbcluster.cc	2009-05-18 11:37:41 +0000
@@ -7597,9 +7597,12 @@ int ndbcluster_find_files(handlerton *ht
       DBUG_PRINT("info", ("Remove table %s/%s", db, file_name_str));
       // Delete the table and all related files
       TABLE_LIST table_list;
+      MDL_request mdl_request;
       bzero((char*) &table_list,sizeof(table_list));
       table_list.db= (char*) db;
       table_list.alias= table_list.table_name= (char*)file_name_str;
+      mdl_request.init(0, db, file_name_str);
+      table_list.mdl_request= &mdl_request;
       /*
         set TNO_NO_NDB_DROP_TABLE flag to not drop ndb table.
         it should not exist anyways

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2009-05-05 12:58:43 +0000
+++ b/sql/sql_db.cc	2009-05-18 11:37:41 +0000
@@ -1162,6 +1162,9 @@ static long mysql_rm_known_files(THD *th
 
       table_list->alias= table_list->table_name;	// If lower_case_table_names=2
       table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
+      table_list->mdl_request= MDL_request::create(0, table_list->db,
+                                                   table_list->table_name,
+                                                   thd->mem_root);
       /* Link into list */
       (*tot_list_next)= table_list;
       tot_list_next= &table_list->next_local;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2009-05-15 12:46:44 +0000
+++ b/sql/sql_table.cc	2009-05-18 11:37:41 +0000
@@ -1710,6 +1710,25 @@ static bool fk_drop_table_add_parent_tab
 
 
 /**
+  Context carrying information about table being dropped for the whole
+  duration of DROP TABLE/DROP DATABASE operation.
+*/
+
+class Drop_table_rcontext: public Sql_alloc
+{
+public:
+
+  Drop_table_rcontext(TABLE_LIST *table_arg)
+    : table(table_arg), table_type(NULL), is_temporary(FALSE)
+  {}
+
+  TABLE_LIST *table;
+  handlerton *table_type;
+  bool is_temporary;
+};
+
+
+/**
   Runtime context for changes performed by DDL statement on a table
   which participates in foreign key constraints.
 
@@ -1729,7 +1748,7 @@ public:
   {
   }
   bool prepare_drop_table(TABLE_LIST *drop_table,
-                          TABLE_LIST *all_dropped_tables,
+                          List<Drop_table_rcontext> &all_dropped_tables,
                           TABLE_LIST *all_parent_tables);
   bool prepare_create_table(TABLE_LIST *create_table,
                             TABLE_LIST *fkey_tables,
@@ -1827,6 +1846,29 @@ handle_condition(THD *thd, uint sql_errn
 
 
 /**
+  Find context for particular table in a list of Drop_table_rcontext contexts.
+*/
+
+static
+Drop_table_rcontext *find_table_in_list(List<Drop_table_rcontext> &list,
+                                        const char *db_name,
+                                        const char *table_name)
+{
+  List_iterator<Drop_table_rcontext> drop_rctx_it(list);
+  Drop_table_rcontext *drop_rctx;
+
+  while ((drop_rctx= drop_rctx_it++))
+  {
+    if (! drop_rctx->is_temporary &&
+        ! strcmp(drop_rctx->table->db, db_name) &&
+        ! strcmp(drop_rctx->table->table_name, table_name))
+      break;
+  }
+  return drop_rctx;
+}
+
+
+/**
   Prepare context for drop table operation by preparing Parent_info
   objects describing related tables from which foreign keys involving
   table being dropped were removed.
@@ -1840,10 +1882,10 @@ handle_condition(THD *thd, uint sql_errn
   @retval TRUE   Failure (e.g. OOM or absence of one of the parent tables).
 */
 
-bool
-Foreign_key_ddl_rcontext::prepare_drop_table(TABLE_LIST *drop_table,
-                                             TABLE_LIST *all_dropped_tables,
-                                             TABLE_LIST *all_parent_tables)
+bool Foreign_key_ddl_rcontext::
+prepare_drop_table(TABLE_LIST *drop_table,
+                   List<Drop_table_rcontext> &all_dropped_tables,
+                   TABLE_LIST *all_parent_tables)
 {
   TABLE_SHARE *share;
   char key[MAX_DBKEY_LENGTH];
@@ -1852,6 +1894,7 @@ Foreign_key_ddl_rcontext::prepare_drop_t
   int error;
   List_iterator<TABLE_LIST> tab_it(m_related_tables);
   TABLE_LIST *tab;
+  Drop_table_rcontext *drop_rctx;
   Foreign_key_name *name;
 
   DBUG_ASSERT(m_drop);
@@ -1913,7 +1956,7 @@ Foreign_key_ddl_rcontext::prepare_drop_t
 
       if (! tab)
       {
-        tab= find_table_in_local_list(all_dropped_tables,
+        drop_rctx= find_table_in_list(all_dropped_tables,
                                       fk_s->parent_table_db.str,
                                       fk_s->parent_table_name.str);
 
@@ -1922,7 +1965,9 @@ Foreign_key_ddl_rcontext::prepare_drop_t
           is a temporary table which shadows it and gets dropped instead of it)
           it must present among additionally locked tables.
         */
-        if (! tab || ! tab->mdl_request)
+        if (drop_rctx)
+          tab= drop_rctx->table;
+        else
           tab= find_table_in_local_list(all_parent_tables,
                                         fk_s->parent_table_db.str,
                                         fk_s->parent_table_name.str);
@@ -1977,11 +2022,13 @@ Foreign_key_ddl_rcontext::prepare_drop_t
           break;
       if (! tab)
       {
-        tab= find_table_in_local_list(all_dropped_tables,
+        drop_rctx= find_table_in_list(all_dropped_tables,
                                       fk_s_p->child_table_db.str,
                                       fk_s_p->child_table_name.str);
 
-        if (! tab || ! tab->mdl_request)
+        if (drop_rctx)
+          tab= drop_rctx->table;
+        else
           tab= find_table_in_local_list(all_parent_tables,
                                         fk_s_p->child_table_db.str,
                                         fk_s_p->child_table_name.str);
@@ -2119,34 +2166,23 @@ Foreign_key_ddl_rcontext::prepare_drop_t
 
 static bool
 lock_dropped_and_parent_tables(THD *thd,
-                               TABLE_LIST *tables, TABLE_LIST *parents,
+                               List<Drop_table_rcontext> &tables,
+                               TABLE_LIST *parents,
                                List<Foreign_key_name> &fk_names)
 {
   TABLE_LIST *table;
   MDL_request *mdl_request;
+  List_iterator<Drop_table_rcontext> drop_rctx_it(tables);
+  Drop_table_rcontext *drop_rctx;
   List_iterator<Foreign_key_name> fk_names_it(fk_names);
   Foreign_key_name *fk_name;
 
-  for (table= tables; table; table= table->next_local)
+  while ((drop_rctx= drop_rctx_it++))
   {
-    if (! table->table)
+    if (! drop_rctx->is_temporary)
     {
-      /*
-        QQ: Ideally we should get rid of allocation here. But this can be
-            problematic due to fact that we set TABLE_LIST::mdl_lock_data
-            to 0 for temporary tables and rely on that (think of
-            re-execution). Any other ideas?
-      */
-      if (! (mdl_request= MDL_request::create(0, table->db,
-                                              table->table_name,
-                                              thd->mem_root)))
-      {
-        thd->mdl_context.remove_all_requests();
-        return TRUE;
-      }
-      mdl_request->set_type(MDL_EXCLUSIVE);
-      thd->mdl_context.add_request(mdl_request);
-      table->mdl_request= mdl_request;
+      drop_rctx->table->mdl_request->set_type(MDL_EXCLUSIVE);
+      thd->mdl_context.add_request(drop_rctx->table->mdl_request);
     }
   }
 
@@ -2188,20 +2224,23 @@ lock_dropped_and_parent_tables(THD *thd,
 
 static bool
 upgrade_mdl_for_dropped_and_parent_tables(THD *thd,
-                                          TABLE_LIST *tables,
+                                          List<Drop_table_rcontext> &tables,
                                           TABLE_LIST *parents,
                                           List<Foreign_key_name> &fk_names)
 {
+  List_iterator<Drop_table_rcontext> drop_rctx_it(tables);
+  Drop_table_rcontext *drop_rctx;
   List_iterator<Foreign_key_name> fk_name_it(fk_names);
   Foreign_key_name *fk_name;
   TABLE_LIST *table;
 
   /* Upgrade meta-data locks for all tables to be dropped. */
-  for (table= tables; table; table= table->next_local)
+  while ((drop_rctx= drop_rctx_it++))
   {
-    if (table->table->s->tmp_table == NO_TMP_TABLE)
+    if (! drop_rctx->is_temporary)
     {
-      if (wait_while_table_is_used(thd, table->table, HA_EXTRA_FORCE_REOPEN))
+      if (wait_while_table_is_used(thd, drop_rctx->table->table,
+                                   HA_EXTRA_FORCE_REOPEN))
       {
         /*
           QQ: Isn't it better to to downgrade locks before returning an error ?
@@ -2216,7 +2255,7 @@ upgrade_mdl_for_dropped_and_parent_table
         get crashes due to query cache and foreign key handling code
         accessing memory occupied by invalidated TABLE instances.
       */
-      table->table= 0;
+      drop_rctx->table->table= 0;
     }
   }
 
@@ -2271,27 +2310,29 @@ upgrade_mdl_for_dropped_and_parent_table
 */
 
 static bool
-fk_check_tables_before_drop(THD *thd, TABLE_LIST *tables,
+fk_check_tables_before_drop(THD *thd,
+                            List<Drop_table_rcontext> tables,
                             TABLE_LIST **parents_to_lock,
                             List<Foreign_key_name> *fk_names_to_lock,
                             bool *has_not_locked_parent_or_fk_name)
 {
-  TABLE_LIST *table;
   TABLE_SHARE *share;
   char key[MAX_DBKEY_LENGTH];
   uint key_length;
   Silence_non_fatal_non_transient_error non_fatal_error_silencer;
   int error;
+  List_iterator<Drop_table_rcontext> drop_rctx_it(tables);
+  Drop_table_rcontext *drop_rctx;
   Foreign_key_name *fk_name;
 
   *parents_to_lock= NULL;
   fk_names_to_lock->empty();
   *has_not_locked_parent_or_fk_name= FALSE;
 
-  for (table= tables; table; table= table->next_local)
+  while ((drop_rctx= drop_rctx_it++))
   {
     /* Skip this table if it is a temporary table. */
-    if (table->table)
+    if (drop_rctx->is_temporary)
       continue;
 
     /*
@@ -2308,10 +2349,10 @@ fk_check_tables_before_drop(THD *thd, TA
       away long ago b) even if they exist they should be dropped when
       normal table with which they are associated is dropped.
     */
-    if (table->internal_tmp_table)
+    if (drop_rctx->table->internal_tmp_table)
       continue;
 
-    key_length= create_table_def_key(thd, key, table, 0);
+    key_length= create_table_def_key(thd, key, drop_rctx->table, 0);
 
     /*
       We ignore ER_NO_SUCH_TABLE error in order to avoid failing with this
@@ -2325,8 +2366,8 @@ fk_check_tables_before_drop(THD *thd, TA
     */
     thd->push_internal_handler(&non_fatal_error_silencer);
     pthread_mutex_lock(&LOCK_open);
-    share= get_table_share_with_create(thd, table, key, key_length, OPEN_VIEW,
-                                       &error);
+    share= get_table_share_with_create(thd, drop_rctx->table, key,
+                                       key_length, OPEN_VIEW, &error);
     pthread_mutex_unlock(&LOCK_open);
     thd->pop_internal_handler();
 
@@ -2345,13 +2386,13 @@ fk_check_tables_before_drop(THD *thd, TA
       */
       while ((fk_p_s= fkeys_p_it++))
       {
-        if (! find_table_in_local_list(tables, fk_p_s->child_table_db.str,
-                                       fk_p_s->child_table_name.str))
+        if (! find_table_in_list(tables, fk_p_s->child_table_db.str,
+                                 fk_p_s->child_table_name.str))
         {
           my_error(ER_FK_CHILD_TABLE_EXISTS, MYF(0), fk_p_s->name.str,
                    thd->lex->sql_command == SQLCOM_DROP_DB ? "DROP DATABASE" :
                                                              "DROP TABLE",
-                   table->table_name);
+                   drop_rctx->table->table_name);
           pthread_mutex_lock(&LOCK_open);
           release_table_share(share);
           pthread_mutex_unlock(&LOCK_open);
@@ -2404,7 +2445,7 @@ fk_check_tables_before_drop(THD *thd, TA
                                   fk_c_s->parent_table_db.str,
                                   fk_c_s->parent_table_name.str) ||
              ! thd->mdl_context.is_exclusive_lock_owner(TYPE_ENUM_FOREIGN_KEY,
-                                  table->db, fk_c_s->name.str)))
+                                  drop_rctx->table->db, fk_c_s->name.str)))
           *has_not_locked_parent_or_fk_name= TRUE;
 
         if (fk_drop_table_add_parent_table(thd, parents_to_lock,
@@ -2417,15 +2458,15 @@ fk_check_tables_before_drop(THD *thd, TA
           return TRUE;
         }
 
-        LEX_STRING child_table_db= { table->db, table->db_length };
+        LEX_STRING child_table_db= { drop_rctx->table->db,
+                                     drop_rctx->table->db_length };
 
-        if (! fk_find_name_in_list(*fk_names_to_lock, table->db,
+        if (! fk_find_name_in_list(*fk_names_to_lock, drop_rctx->table->db,
                                    fk_c_s->name.str) &&
             (! (fk_name= Foreign_key_name::create(thd->mem_root,
                                                   child_table_db,
                                                   fk_c_s->name)) ||
              fk_names_to_lock->push_back(fk_name, thd->mem_root)))
-
         {
           pthread_mutex_lock(&LOCK_open);
           release_table_share(share);
@@ -2465,20 +2506,22 @@ fk_check_tables_before_drop(THD *thd, TA
 
 static bool
 fk_check_tables_before_drop(THD *thd,
-                            TABLE_LIST *tables, TABLE_LIST **parents_locked,
+                            List<Drop_table_rcontext> &tables,
+                            TABLE_LIST **parents_locked,
                             List<Foreign_key_name> *fk_names_locked)
 {
-  TABLE_LIST *table;
+  List_iterator<Drop_table_rcontext> drop_rctx_it(tables);
+  Drop_table_rcontext *drop_rctx;
   TABLE_SHARE *share;
   Foreign_key_name *fk_name;
 
-  for (table= tables; table; table= table->next_local)
+  while ((drop_rctx= drop_rctx_it++))
   {
     /* Skip this table if it is a temporary table. */
-    if (table->table->s->tmp_table != NO_TMP_TABLE)
+    if (drop_rctx->is_temporary)
       continue;
 
-    share= table->table->s;
+    share= drop_rctx->table->table->s;
 
     List_iterator<Foreign_key_parent_share> fkeys_p_it(share->
                                                        fkeys.fkeys_parent);
@@ -2486,13 +2529,13 @@ fk_check_tables_before_drop(THD *thd,
 
     while ((fk_p_s= fkeys_p_it++))
     {
-      if (! find_table_in_local_list(tables, fk_p_s->child_table_db.str,
-                                     fk_p_s->child_table_name.str))
+      if (! find_table_in_list(tables, fk_p_s->child_table_db.str,
+                               fk_p_s->child_table_name.str))
       {
         my_error(ER_FK_CHILD_TABLE_EXISTS, MYF(0), fk_p_s->name.str,
                  thd->lex->sql_command == SQLCOM_DROP_DB ? "DROP DATABASE" :
                                                            "DROP TABLE",
-                 table->table_name);
+                 drop_rctx->table->table_name);
         return TRUE;
       }
     }
@@ -2502,9 +2545,8 @@ fk_check_tables_before_drop(THD *thd,
 
     while ((fk_c_s= fkeys_c_it++))
     {
-      if (! find_table_in_local_list(tables,
-                                     fk_c_s->parent_table_db.str,
-                                     fk_c_s->parent_table_name.str) &&
+      if (! find_table_in_list(tables, fk_c_s->parent_table_db.str,
+                               fk_c_s->parent_table_name.str) &&
           ! find_table_in_local_list(*parents_locked,
                                      fk_c_s->parent_table_db.str,
                                      fk_c_s->parent_table_name.str))
@@ -2531,7 +2573,8 @@ fk_check_tables_before_drop(THD *thd,
 
         @sa fk_take_mdl_on_fk_names().
       */
-      fk_name= thd->locked_tables_list.find_fk_name(table->db, fk_c_s->name.str);
+      fk_name= thd->locked_tables_list.find_fk_name(drop_rctx->table->db,
+                                                    fk_c_s->name.str);
       DBUG_ASSERT(fk_name);
 
       if (fk_names_locked->push_back(fk_name, thd->mem_root))
@@ -2589,6 +2632,9 @@ int mysql_rm_table_part2(THD *thd, TABLE
   List<Foreign_key_name> fk_names_to_lock, fk_names_locked;
   List_iterator<Foreign_key_name> fk_names_it(fk_names_locked);
   Foreign_key_name *fk_name;
+  List<Drop_table_rcontext> dropped_tables;
+  List_iterator<Drop_table_rcontext> drop_rctx_it(dropped_tables);
+  Drop_table_rcontext *drop_rctx;
   DBUG_ENTER("mysql_rm_table_part2");
 
   LINT_INIT(alias);
@@ -2613,18 +2659,28 @@ int mysql_rm_table_part2(THD *thd, TABLE
   if (!drop_temporary)
     global_schema_lock_guard.lock();
 
+  /* Create per-table runtime contexts for the operation. */
+  for (table= tables; table; table= table->next_local)
+  {
+    if (! (drop_rctx= new(thd->mem_root) Drop_table_rcontext(table)) ||
+        dropped_tables.push_back(drop_rctx, thd->mem_root))
+      DBUG_RETURN(1);
+  }
+
   /*
     If we have the table in the definition cache, we don't have to check the
     .frm file to find if the table is a normal table (not view) and what
     engine to use.
   */
   pthread_mutex_lock(&LOCK_open);
-  for (table= tables; table; table= table->next_local)
+  while ((drop_rctx= drop_rctx_it++))
   {
     TABLE_SHARE *share;
-    table->db_type= NULL;
+
+    table= drop_rctx->table;
+
     if ((share= get_cached_table_share(table->db, table->table_name)))
-      table->db_type= share->db_type();
+      drop_rctx->table_type= share->db_type();
 
     /* Disable drop of enabled log tables */
     if (share && (share->table_category == TABLE_CATEGORY_PERFORMANCE) &&
@@ -2646,23 +2702,18 @@ int mysql_rm_table_part2(THD *thd, TABLE
       some expensive steps (like foreign key handling). Also our foreign
       key code relies on this.
     */
-    for (table= tables; table; table= table->next_local)
+    drop_rctx_it.rewind();
+    while ((drop_rctx= drop_rctx_it++))
     {
-      if ((table->table= find_temporary_table(thd, table->db,
-                                              table->table_name)))
-      {
-        /*
-          Since we don't acquire metadata lock if we have found temporary
-          table, we should do something to avoid releasing it at the end.
-        */
-        table->mdl_request= 0;
-      }
+      if (find_temporary_table(thd, drop_rctx->table->db,
+                               drop_rctx->table->table_name))
+        drop_rctx->is_temporary= TRUE;
     }
 
     if (!thd->locked_tables_mode)
     {
 retry_lock:
-      if (lock_dropped_and_parent_tables(thd, tables,
+      if (lock_dropped_and_parent_tables(thd, dropped_tables,
                                          parents_to_lock, fk_names_to_lock))
         DBUG_RETURN(1);
       parents_locked= parents_to_lock;
@@ -2670,7 +2721,7 @@ retry_lock:
 
       if (opt_fk_all_engines)
       {
-        if (fk_check_tables_before_drop(thd, tables,
+        if (fk_check_tables_before_drop(thd, dropped_tables,
                                         &parents_to_lock, &fk_names_to_lock,
                                         &has_not_locked_parent_or_fk_name))
           DBUG_RETURN(1);
@@ -2685,20 +2736,24 @@ retry_lock:
     }
     else
     {
-      for (table= tables; table; table= table->next_local)
-        if (! table->table)
+      drop_rctx_it.rewind();
+      while ((drop_rctx= drop_rctx_it++))
+      {
+        if (! drop_rctx->is_temporary)
         {
           /*
             Check that each non-temporary table to be dropped is locked
             for write and cache pointer to its TABLE object for lock
             upgrade.
           */
+          table= drop_rctx->table;
           table->table= find_write_locked_table(thd->open_tables, table->db,
                                                 table->table_name);
           if (!table->table)
             DBUG_RETURN(1);
           table->mdl_request->ticket= table->table->mdl_ticket;
         }
+      }
 
       /*
         Check that we are not dropping parent tables withour dropping child
@@ -2708,7 +2763,7 @@ retry_lock:
         not among tables to be dropped to use for this upgrade.
       */
       if (opt_fk_all_engines &&
-          fk_check_tables_before_drop(thd, tables, &parents_locked,
+          fk_check_tables_before_drop(thd, dropped_tables, &parents_locked,
                                       &fk_names_locked))
         DBUG_RETURN(1);
 
@@ -2719,7 +2774,7 @@ retry_lock:
         Also upgrade meta-data locks on foreign key names so we can safely
         mark them as unused when dropping their child tables.
       */
-      if (upgrade_mdl_for_dropped_and_parent_tables(thd, tables,
+      if (upgrade_mdl_for_dropped_and_parent_tables(thd, dropped_tables,
                                                     parents_locked,
                                                     fk_names_locked))
       {
@@ -2729,13 +2784,16 @@ retry_lock:
     }
   }
 
-  for (table= tables; table; table= table->next_local)
+  drop_rctx_it.rewind();
+  while ((drop_rctx= drop_rctx_it++))
   {
-    char *db=table->db;
+    char *db= drop_rctx->table->db;
     handlerton *table_type;
     enum legacy_db_type frm_db_type;
     Foreign_key_ddl_rcontext fk_ctx(thd, TRUE);
 
+    table= drop_rctx->table;
+
     DBUG_PRINT("table", ("table_l: '%s'.'%s'  table: %p  s: %p",
                          table->db, table->table_name, table->table,
                          table->table ? table->table->s : (TABLE_SHARE *)-1));
@@ -2745,8 +2803,8 @@ retry_lock:
     switch (error) {
     case  0:
       // removed temporary table
+      DBUG_ASSERT(drop_temporary || drop_rctx->is_temporary);
       tmp_table_deleted= 1;
-      table->table= 0;
       continue;
     case -1:
       DBUG_ASSERT(thd->in_sub_stmt);
@@ -2754,6 +2812,7 @@ retry_lock:
       goto err;
     default:
       // temporary table not found
+      DBUG_ASSERT(! drop_rctx->is_temporary);
       error= 0;
     }
 
@@ -2783,11 +2842,11 @@ retry_lock:
       built_query.append("`,");
     }
 
-    table_type= table->db_type;
+    table_type= drop_rctx->table_type;
     if (!drop_temporary)
     {
       if (opt_fk_all_engines &&
-          fk_ctx.prepare_drop_table(table, tables, parents_locked))
+          fk_ctx.prepare_drop_table(table, dropped_tables, parents_locked))
       {
         error= 1;
         goto err_table;
@@ -3038,16 +3097,18 @@ err:
       thd->locked_tables_list.unlock_locked_tables(thd);
       goto end;
     }
-    for (table= tables; table; table= table->next_local)
+    drop_rctx_it.rewind();
+    while ((drop_rctx= drop_rctx_it++))
     {
-      if (table->mdl_request)
+      if (! drop_rctx->is_temporary)
       {
         /*
           Under LOCK TABLES we may have several instances of table open
           and locked and therefore have to remove several metadata lock
           requests associated with them.
         */
-        thd->mdl_context.release_all_locks_for_name(table->mdl_request->ticket);
+        thd->mdl_context.release_all_locks_for_name(drop_rctx->table->
+                                                    mdl_request->ticket);
       }
     }
     while ((fk_name= fk_names_it++))

=== modified file 'sql/table.h'
--- a/sql/table.h	2009-05-14 14:18:43 +0000
+++ b/sql/table.h	2009-05-18 11:37:41 +0000
@@ -1424,7 +1424,6 @@ struct TABLE_LIST
   bool          check_option_processed;
   /* FRMTYPE_ERROR if any type is acceptable */
   enum frm_type_enum required_type;
-  handlerton	*db_type;		/* table_type for handler */
   char		timestamp_buffer[20];	/* buffer for timestamp (19+1) */
   /*
     This TABLE_LIST object is just placeholder for prelocking, it will be


Attachment: [text/bzr-bundle] bzr/dlenev@mysql.com-20090518113741-fpfjdjx1p01pvccf.bundle
Thread
bzr commit into mysql-6.1-fk branch (dlenev:2734) WL#148Dmitry Lenev18 May