diff options
author | Konstantin Osipov <kostja@sun.com> | 2009-12-01 00:44:05 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2009-12-01 00:44:05 +0300 |
commit | b58e79566c5c5899c4d54a4b36ed4e876fa197ca (patch) | |
tree | 1ddec29ac5054654a2ac19a56830d104f8cb37d8 /sql/sql_base.cc | |
parent | cd055f0efe330ace1d4d83536f1cbbeb1c8e0ab9 (diff) | |
download | mariadb-git-b58e79566c5c5899c4d54a4b36ed4e876fa197ca.tar.gz |
Backport of:
------------------------------------------------------------
revno: 2630.4.13
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Wed 2008-05-28 12:07:30 +0400
message:
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()).
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.
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 182 |
1 files changed, 3 insertions, 179 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1356a2cd16f..40377a99d21 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1482,7 +1482,7 @@ void close_thread_tables(THD *thd, /* 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. */ @@ -2228,7 +2228,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) /* 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. */ @@ -8444,154 +8444,6 @@ void flush_tables() } -/* - 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*) my_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) - my_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. @@ -8895,34 +8747,6 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) /* - 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. @@ -9165,7 +8989,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup) /* 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. */ |