List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:May 28 2008 5:13am
Subject:commit into mysql-6.0 branch (dlenev:2651) WL#3726
View as plain text  
#At file:///home/dlenev/src/bzr/mysql-6.0-3726-w/

 2651 Dmitry Lenev	2008-05-28
      WL#3726 "DDL locking for all metadata objects".
      
      After review fixes in progress.
      
      Get rid of remove_table_from_cache() function since it was
      doing two things at once -- waiting while no one uses particular
      table (now job of metadata locking) and removing TABLE/TABLE_SHARE
      instances from table definition cache (now job of
      expel_table_from_cache()).
      
      Question for reviewer is marked by QQ.
modified:
  sql/mysql_priv.h
  sql/sql_base.cc
  sql/sql_table.cc

per-file comments:
  sql/mysql_priv.h
    Got rid of remove_table_from_cache() function. Now one
    should use exclusive metadata lock for waiting until all
    other connections will stop using particular table and
    use expel_table_from_cache() for removing table instances
    and table share from table definition cache.
    Removed unused mysql_wait_completed_table() function.
  sql/sql_base.cc
    Got rid of remove_table_from_cache() function. Now one
    should use exclusive metadata lock for waiting until all
    other connections will stop using particular table and
    use expel_table_from_cache() for removing table instances
    and table share from table definition cache.
    Removed unused mysql_wait_completed_table() function.
  sql/sql_table.cc
    Get rid of two last places where we use remove_table_from_cache()
    by using wait_while_table_is_used() (which uses metadata locks)
    and close_cached_tables() instead.

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-05-27 17:50:29 +0000
+++ b/sql/mysql_priv.h	2008-05-28 05:13:24 +0000
@@ -1653,13 +1653,6 @@
                            uint *fast_alter_partition);
 #endif
 
-/* bits for last argument to remove_table_from_cache() */
-#define RTFC_NO_FLAG                0x0000
-#define RTFC_OWNED_BY_THD_FLAG      0x0001
-#define RTFC_WAIT_OTHER_THREAD_FLAG 0x0002
-#define RTFC_CHECK_KILLED_FLAG      0x0004
-bool remove_table_from_cache(THD *thd, const char *db, const char *table,
-                             uint flags);
 bool notify_thread_having_shared_lock(THD *thd, THD *in_use);
 void expel_table_from_cache(THD *leave_thd, const char *db,
                             const char *table_name);
@@ -1781,7 +1774,6 @@
 bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
 int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt);
 void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt);
-void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table);
 
 /* Functions to work with system tables. */
 bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2008-05-27 17:50:29 +0000
+++ b/sql/sql_base.cc	2008-05-28 05:13:24 +0000
@@ -1435,7 +1435,7 @@
   /*
     Note that we need to hold LOCK_open while changing the
     open_tables list. Another thread may work on it.
-    (See: remove_table_from_cache(), mysql_wait_completed_table())
+    (See: notify_thread_having_shared_lock())
     Closing a MERGE child before the parent would be fatal if the
     other thread tries to abort the MERGE lock in between.
   */
@@ -2169,7 +2169,7 @@
   /*
     Note that we need to hold LOCK_open while changing the
     open_tables list. Another thread may work on it.
-    (See: remove_table_from_cache(), mysql_wait_completed_table())
+    (See: notify_thread_having_shared_lock())
     Closing a MERGE child before the parent would be fatal if the
     other thread tries to abort the MERGE lock in between.
   */
@@ -8227,154 +8227,6 @@
 }
 
 
-/*
-  Mark all entries with the table as deleted to force an reopen of the table
-
-  The table will be closed (not stored in cache) by the current thread when
-  close_thread_tables() is called.
-
-  PREREQUISITES
-    Lock on LOCK_open()
-
-  RETURN
-    0  This thread now have exclusive access to this table and no other thread
-       can access the table until close_thread_tables() is called.
-    1  Table is in use by another thread
-*/
-
-bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
-                             uint flags)
-{
-  char key[MAX_DBKEY_LENGTH];
-  uint key_length;
-  TABLE *table;
-  TABLE_SHARE *share;
-  bool result= 0, signalled= 0;
-  DBUG_ENTER("remove_table_from_cache");
-  DBUG_PRINT("enter", ("table: '%s'.'%s'  flags: %u", db, table_name, flags));
-
-  key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
-  for (;;)
-  {
-    result= signalled= 0;
-
-    if ((share= (TABLE_SHARE*)hash_search(&table_def_cache, (uchar*) key,
-                                          key_length)))
-    {
-      I_P_List_iterator<TABLE, TABLE_share> it(share->free_tables);
-      share->version= 0;
-      while ((table= it++))
-        relink_unused(table);
-
-      it.init(share->used_tables);
-      while ((table= it++))
-      {
-        THD *in_use= table->in_use;
-        DBUG_ASSERT(in_use);
-        if (in_use != thd)
-        {
-          DBUG_PRINT("info", ("Table was in use by other thread"));
-          /*
-            Mark that table is going to be deleted from cache. This will
-            force threads that are in mysql_lock_tables() (but not yet
-            in thr_multi_lock()) to abort it's locks, close all tables and retry
-          */
-          in_use->some_tables_deleted= 1;
-
-          if (table->is_name_opened())
-          {
-            DBUG_PRINT("info", ("Found another active instance of the table"));
-            result=1;
-          }
-          /* Kill delayed insert threads */
-          if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
-              ! in_use->killed)
-          {
-            in_use->killed= THD::KILL_CONNECTION;
-            pthread_mutex_lock(&in_use->mysys_var->mutex);
-            if (in_use->mysys_var->current_cond)
-            {
-              pthread_mutex_lock(in_use->mysys_var->current_mutex);
-              signalled= 1;
-              pthread_cond_broadcast(in_use->mysys_var->current_cond);
-              pthread_mutex_unlock(in_use->mysys_var->current_mutex);
-            }
-            pthread_mutex_unlock(&in_use->mysys_var->mutex);
-          }
-          /*
-            Now we must abort all tables locks used by this thread
-            as the thread may be waiting to get a lock for another table.
-            Note that we need to hold LOCK_open while going through the
-            list. So that the other thread cannot change it. The other
-            thread must also hold LOCK_open whenever changing the
-            open_tables list. Aborting the MERGE lock after a child was
-            closed and before the parent is closed would be fatal.
-          */
-          for (TABLE *thd_table= in_use->open_tables;
-               thd_table ;
-               thd_table= thd_table->next)
-          {
-            /* Do not handle locks of MERGE children. */
-            if (thd_table->db_stat && !thd_table->parent)	// If table is
open
-              signalled|= mysql_lock_abort_for_thread(thd, thd_table);
-          }
-        }
-        else
-        {
-          DBUG_PRINT("info", ("Table was in use by current thread. db_stat: %u",
-                     table->db_stat));
-          result= result || (flags & RTFC_OWNED_BY_THD_FLAG);
-        }
-      }
-
-      while (unused_tables && !unused_tables->s->version)
-        free_cache_entry(unused_tables);
-
-      DBUG_PRINT("info", ("share version: %lu  ref_count: %u",
-                          share->version, share->ref_count));
-      if (share->ref_count == 0)
-        hash_delete(&table_def_cache, (uchar*) share);
-    }
-
-    if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
-    {
-      /*
-        Signal any thread waiting for tables to be freed to
-        reopen their tables
-      */
-      broadcast_refresh();
-      DBUG_PRINT("info", ("Waiting for refresh signal"));
-      if (!(flags & RTFC_CHECK_KILLED_FLAG) || !thd->killed)
-      {
-        dropping_tables++;
-        if (likely(signalled))
-          (void) pthread_cond_wait(&COND_refresh, &LOCK_open);
-        else
-        {
-          struct timespec abstime;
-          /*
-            It can happen that another thread has opened the
-            table but has not yet locked any table at all. Since
-            it can be locked waiting for a table that our thread
-            has done LOCK TABLE x WRITE on previously, we need to
-            ensure that the thread actually hears our signal
-            before we go to sleep. Thus we wait for a short time
-            and then we retry another loop in the
-            remove_table_from_cache routine.
-          */
-          set_timespec(abstime, 10);
-          pthread_cond_timedwait(&COND_refresh, &LOCK_open, &abstime);
-        }
-        dropping_tables--;
-        continue;
-      }
-    }
-    break;
-  }
-  DBUG_RETURN(result);
-}
-
-
 /**
    A callback to the server internals that is used to address
    special cases of the locking protocol.
@@ -8678,34 +8530,6 @@
 
 
 /*
-  SYNOPSIS
-    close_open_tables_and_downgrade()
-  RESULT VALUES
-    NONE
-  DESCRIPTION
-    We need to ensure that any thread that has managed to open the table
-    but not yet encountered our lock on the table is also thrown out to
-    ensure that no threads see our frm changes premature to the final
-    version. The intermediate versions are only meant for use after a
-    crash and later REPAIR TABLE.
-    We also downgrade locks after the upgrade to WRITE_ONLY
-*/
-
-/* purecov: begin deadcode */
-void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt)
-{
-  pthread_mutex_lock(&LOCK_open);
-  remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name,
-                          RTFC_WAIT_OTHER_THREAD_FLAG);
-  pthread_mutex_unlock(&LOCK_open);
-  /* If MERGE child, forward lock handling to parent. */
-  mysql_lock_downgrade_write(lpt->thd, lpt->table->parent ?
lpt->table->parent :
-                             lpt->table, lpt->old_lock_type);
-}
-/* purecov: end */
-
-
-/*
   Tells if two (or more) tables have auto_increment columns and we want to
   lock those tables with a write lock.
 
@@ -8964,7 +8788,7 @@
   /*
     Note that we need to hold LOCK_open while changing the
     open_tables list. Another thread may work on it.
-    (See: remove_table_from_cache(), mysql_wait_completed_table())
+    (See: notify_thread_having_shared_lock())
     Closing a MERGE child before the parent would be fatal if the
     other thread tries to abort the MERGE lock in between.
   */

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2008-05-27 09:45:34 +0000
+++ b/sql/sql_table.cc	2008-05-28 05:13:24 +0000
@@ -4284,19 +4284,13 @@
     /* Close all instances of the table to allow repair to rename files */
     if (lock_type == TL_WRITE && table->table->s->version)
     {
-      DBUG_PRINT("admin", ("removing table from cache"));
-      pthread_mutex_lock(&LOCK_open);
-      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
-					      "Waiting to get writelock");
-      mysql_lock_abort(thd,table->table, TRUE);
-      remove_table_from_cache(thd, table->table->s->db.str,
-                              table->table->s->table_name.str,
-                              RTFC_WAIT_OTHER_THREAD_FLAG |
-                              RTFC_CHECK_KILLED_FLAG);
-      thd->exit_cond(old_message);
-      DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
-      if (thd->killed)
-	goto err;
+      if (wait_while_table_is_used(thd, table->table,
+                                   HA_EXTRA_PREPARE_FOR_RENAME))
+        goto err;
+      DBUG_EXECUTE_IF("wait_in_mysql_admin_table",
+                      wait_for_kill_signal(thd);
+                      if (thd->killed)
+                        goto err;);
       /* Flush entries in the query cache involving this table. */
       query_cache_invalidate3(thd, table->table, 0);
       open_for_modify= 0;
@@ -4534,10 +4528,16 @@
           table->table->file->info(HA_STATUS_CONST);
         else
         {
-          pthread_mutex_lock(&LOCK_open);
-          remove_table_from_cache(thd, table->table->s->db.str,
-                                  table->table->s->table_name.str,
RTFC_NO_FLAG);
-          pthread_mutex_unlock(&LOCK_open);
+          TABLE_LIST *save_next_global= table->next_global;
+          table->next_global= 0;
+          /*
+            QQ: It is a tad inefficient to use this function here...
+                May be we should simply introduce TDC API function
+                which will destroy all unused TABLE instances for
+                particular share ?
+          */
+          close_cached_tables(thd, table, FALSE, FALSE);
+          table->next_global= save_next_global;
         }
         /* May be something modified consequently we have to invalidate cache */
         query_cache_invalidate3(thd, table->table, 0);
@@ -4580,6 +4580,7 @@
 bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
 {
   DBUG_ENTER("mysql_optimize_table");
+  set_all_mdl_upgradable(tables);
   DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
 				"optimize", TL_WRITE, 1,0,0,0,
 				&handler::ha_optimize, 0));

Thread
commit into mysql-6.0 branch (dlenev:2651) WL#3726Dmitry Lenev28 May
  • Re: commit into mysql-6.0 branch (dlenev:2651) WL#3726Konstantin Osipov28 May