mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into bodhi.(none):/opt/local/work/mysql-5.1-runtime client/mysqldump.c: Auto merged mysql-test/r/mysqldump.result: Auto merged mysql-test/t/disabled.def: Auto merged mysql-test/t/mysqldump.test: Auto merged sql/handler.cc: Auto merged sql/lock.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged mysql-test/include/mix1.inc: Manual merge. mysql-test/r/innodb_mysql.result: Manual merge.
This commit is contained in:
177
sql/sql_base.cc
177
sql/sql_base.cc
@@ -902,8 +902,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
bool found=0;
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
||||
{
|
||||
if ((!table->table || !table->table->s->log_table) &&
|
||||
remove_table_from_cache(thd, table->db, table->table_name,
|
||||
if (remove_table_from_cache(thd, table->db, table->table_name,
|
||||
RTFC_OWNED_BY_THD_FLAG))
|
||||
found=1;
|
||||
}
|
||||
@@ -951,8 +950,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
are employed by CREATE TABLE as in this case table simply does not
|
||||
exist yet.
|
||||
*/
|
||||
if (!table->s->log_table &&
|
||||
(table->needs_reopen_or_name_lock() && table->db_stat))
|
||||
if (table->needs_reopen_or_name_lock() && table->db_stat)
|
||||
{
|
||||
found=1;
|
||||
DBUG_PRINT("signal", ("Waiting for COND_refresh"));
|
||||
@@ -1679,8 +1677,28 @@ TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Close temporary table and unlink from thd->temporary tables
|
||||
/**
|
||||
Drop a temporary table.
|
||||
|
||||
Try to locate the table in the list of thd->temporary_tables.
|
||||
If the table is found:
|
||||
- if the table is in thd->locked_tables, unlock it and
|
||||
remove it from the list of locked tables. Currently only transactional
|
||||
temporary tables are present in the locked_tables list.
|
||||
- Close the temporary table, remove its .FRM
|
||||
- remove the table from the list of temporary tables
|
||||
|
||||
This function is used to drop user temporary tables, as well as
|
||||
internal tables created in CREATE TEMPORARY TABLE ... SELECT
|
||||
or ALTER TABLE. Even though part of the work done by this function
|
||||
is redundant when the table is internal, as long as we
|
||||
link both internal and user temporary tables into the same
|
||||
thd->temporary_tables list, it's impossible to tell here whether
|
||||
we're dealing with an internal or a user temporary table.
|
||||
|
||||
@retval TRUE the table was not found in the list of temporary tables
|
||||
of this thread
|
||||
@retval FALSE the table was found and dropped successfully.
|
||||
*/
|
||||
|
||||
bool close_temporary_table(THD *thd, TABLE_LIST *table_list)
|
||||
@@ -1689,6 +1707,11 @@ bool close_temporary_table(THD *thd, TABLE_LIST *table_list)
|
||||
|
||||
if (!(table= find_temporary_table(thd, table_list)))
|
||||
return 1;
|
||||
/*
|
||||
If LOCK TABLES list is not empty and contains this table,
|
||||
unlock the table and remove the table from this list.
|
||||
*/
|
||||
mysql_lock_remove(thd, thd->locked_tables, table, FALSE);
|
||||
close_temporary_table(thd, table, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -1835,7 +1858,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock)
|
||||
!memcmp(list->s->table_cache_key.str, key, key_length))
|
||||
{
|
||||
if (unlock && thd->locked_tables)
|
||||
mysql_lock_remove(thd, thd->locked_tables,list);
|
||||
mysql_lock_remove(thd, thd->locked_tables, list, TRUE);
|
||||
VOID(hash_delete(&open_cache,(uchar*) list)); // Close table
|
||||
}
|
||||
else
|
||||
@@ -1861,8 +1884,13 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock)
|
||||
|
||||
@note This routine assumes that table to be closed is open only
|
||||
by calling thread so we needn't wait until other threads
|
||||
will close the table. It also assumes that table to be
|
||||
dropped is already unlocked.
|
||||
will close the table. Also unless called under implicit or
|
||||
explicit LOCK TABLES mode it assumes that table to be
|
||||
dropped is already unlocked. In the former case it will
|
||||
also remove lock on the table. But one should not rely on
|
||||
this behaviour as it may change in future.
|
||||
Currently, however, this function is never called for a
|
||||
table that was locked with LOCK TABLES.
|
||||
*/
|
||||
|
||||
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||
@@ -2468,8 +2496,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
&state))
|
||||
{
|
||||
/*
|
||||
Here we flush tables marked for flush. However we never flush log
|
||||
tables here. They are flushed only on FLUSH LOGS.
|
||||
Here we flush tables marked for flush.
|
||||
Normally, table->s->version contains the value of
|
||||
refresh_version from the moment when this table was
|
||||
(re-)opened and added to the cache.
|
||||
@@ -2486,7 +2513,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
c1: name lock t2; -- blocks
|
||||
c2: open t1; -- blocks
|
||||
*/
|
||||
if (table->needs_reopen_or_name_lock() && !table->s->log_table)
|
||||
if (table->needs_reopen_or_name_lock())
|
||||
{
|
||||
DBUG_PRINT("note",
|
||||
("Found table '%s.%s' with different refresh version",
|
||||
@@ -2840,7 +2867,7 @@ void close_data_files_and_morph_locks(THD *thd, const char *db,
|
||||
!strcmp(table->s->db.str, db))
|
||||
{
|
||||
if (thd->locked_tables)
|
||||
mysql_lock_remove(thd, thd->locked_tables, table);
|
||||
mysql_lock_remove(thd, thd->locked_tables, table, TRUE);
|
||||
table->open_placeholder= 1;
|
||||
close_handle_and_leave_table_as_lock(table);
|
||||
}
|
||||
@@ -2962,10 +2989,9 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
|
||||
for (; table ; table=table->next)
|
||||
{
|
||||
/*
|
||||
Reopen marked for flush. But close log tables. They are flushed only
|
||||
explicitly on FLUSH LOGS
|
||||
Reopen marked for flush.
|
||||
*/
|
||||
if (table->needs_reopen_or_name_lock() && !table->s->log_table)
|
||||
if (table->needs_reopen_or_name_lock())
|
||||
{
|
||||
found=1;
|
||||
if (table->db_stat)
|
||||
@@ -2979,7 +3005,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
|
||||
instances of this table.
|
||||
*/
|
||||
mysql_lock_abort(thd, table, TRUE);
|
||||
mysql_lock_remove(thd, thd->locked_tables, table);
|
||||
mysql_lock_remove(thd, thd->locked_tables, table, TRUE);
|
||||
/*
|
||||
We want to protect the table from concurrent DDL operations
|
||||
(like RENAME TABLE) until we will re-open and re-lock it.
|
||||
@@ -3012,10 +3038,6 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
|
||||
Wait until all threads has closed the tables in the list
|
||||
We have also to wait if there is thread that has a lock on this table even
|
||||
if the table is closed
|
||||
NOTE: log tables are handled differently by the logging routines.
|
||||
E.g. general_log is always opened and locked by the logger
|
||||
and the table handler used by the logger, will be skipped by
|
||||
this check.
|
||||
*/
|
||||
|
||||
bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||
@@ -3034,10 +3056,10 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||
search= (TABLE*) hash_next(&open_cache, (uchar*) key,
|
||||
key_length, &state))
|
||||
{
|
||||
DBUG_PRINT("info", ("share: 0x%lx locked_by_logger: %d "
|
||||
DBUG_PRINT("info", ("share: 0x%lx "
|
||||
"open_placeholder: %d locked_by_name: %d "
|
||||
"db_stat: %u version: %lu",
|
||||
(ulong) search->s, search->locked_by_logger,
|
||||
(ulong) search->s,
|
||||
search->open_placeholder, search->locked_by_name,
|
||||
search->db_stat,
|
||||
search->s->version));
|
||||
@@ -3049,12 +3071,9 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||
- If we are in flush table and we didn't execute the flush
|
||||
- If the table engine is open and it's an old version
|
||||
(We must wait until all engines are shut down to use the table)
|
||||
However we fo not wait if we encountered a table, locked by the logger.
|
||||
Log tables are managed separately by logging routines.
|
||||
*/
|
||||
if (!search->locked_by_logger &&
|
||||
(search->locked_by_name && wait_for_name_lock ||
|
||||
(search->is_name_opened() && search->needs_reopen_or_name_lock())))
|
||||
if ( (search->locked_by_name && wait_for_name_lock) ||
|
||||
(search->is_name_opened() && search->needs_reopen_or_name_lock()))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
} while ((table=table->next));
|
||||
@@ -3131,7 +3150,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name)
|
||||
if (!strcmp(table->s->table_name.str, table_name) &&
|
||||
!strcmp(table->s->db.str, db))
|
||||
{
|
||||
mysql_lock_remove(thd, thd->locked_tables,table);
|
||||
mysql_lock_remove(thd, thd->locked_tables, table, TRUE);
|
||||
if (!found)
|
||||
{
|
||||
found= table;
|
||||
@@ -3766,6 +3785,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
|
||||
thd Thread handler
|
||||
table_list Table to open is first table in this list
|
||||
lock_type Lock to use for open
|
||||
lock_flags Flags passed to mysql_lock_table
|
||||
|
||||
NOTE
|
||||
This function don't do anything like SP/SF/views/triggers analysis done
|
||||
@@ -3781,7 +3801,8 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
|
||||
table_list->table table
|
||||
*/
|
||||
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
|
||||
uint lock_flags)
|
||||
{
|
||||
TABLE *table;
|
||||
bool refresh;
|
||||
@@ -3809,8 +3830,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
{
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
|
||||
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, 0,
|
||||
&refresh)))
|
||||
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1,
|
||||
lock_flags, &refresh)))
|
||||
table= 0;
|
||||
}
|
||||
}
|
||||
@@ -4149,11 +4170,6 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
TABLE **start,**ptr;
|
||||
uint lock_flag= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN;
|
||||
|
||||
/* Ignore GLOBAL READ LOCK and GLOBAL READ_ONLY if called from a logger */
|
||||
if (logger.is_privileged_thread(thd))
|
||||
lock_flag|= (MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
|
||||
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY);
|
||||
|
||||
if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count)))
|
||||
DBUG_RETURN(-1);
|
||||
@@ -7182,7 +7198,6 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
|
||||
else if (in_use != thd)
|
||||
{
|
||||
DBUG_PRINT("info", ("Table was in use by other thread"));
|
||||
in_use->some_tables_deleted=1;
|
||||
if (table->is_name_opened())
|
||||
{
|
||||
DBUG_PRINT("info", ("Found another active instance of the table"));
|
||||
@@ -7618,7 +7633,7 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
||||
if (!table)
|
||||
goto error;
|
||||
|
||||
DBUG_ASSERT(table->s->system_table);
|
||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
||||
|
||||
table->use_all_columns();
|
||||
table->reginfo.lock_type= tables->lock_type;
|
||||
@@ -7685,12 +7700,92 @@ open_system_table_for_update(THD *thd, TABLE_LIST *one_table)
|
||||
{
|
||||
DBUG_ENTER("open_system_table_for_update");
|
||||
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type);
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, 0);
|
||||
if (table)
|
||||
{
|
||||
DBUG_ASSERT(table->s->system_table);
|
||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
|
||||
table->use_all_columns();
|
||||
}
|
||||
|
||||
DBUG_RETURN(table);
|
||||
}
|
||||
|
||||
/**
|
||||
Open a performance schema table.
|
||||
Opening such tables is performed internally in the server
|
||||
implementation, and is a 'nested' open, since some tables
|
||||
might be already opened by the current thread.
|
||||
The thread context before this call is saved, and is restored
|
||||
when calling close_performance_schema_table().
|
||||
@param thd The current thread
|
||||
@param one_table Performance schema table to open
|
||||
@param backup [out] Temporary storage used to save the thread context
|
||||
*/
|
||||
TABLE *
|
||||
open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
|
||||
Open_tables_state *backup)
|
||||
{
|
||||
uint flags= ( MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK
|
||||
| MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY
|
||||
| MYSQL_LOCK_PERF_SCHEMA );
|
||||
|
||||
DBUG_ENTER("open_performance_schema_table");
|
||||
|
||||
thd->reset_n_backup_open_tables_state(backup);
|
||||
|
||||
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, flags);
|
||||
if (table)
|
||||
{
|
||||
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_PERFORMANCE);
|
||||
/* Make sure all columns get assigned to a default value */
|
||||
table->use_all_columns();
|
||||
table->no_replicate= 1;
|
||||
}
|
||||
|
||||
DBUG_RETURN(table);
|
||||
}
|
||||
|
||||
/**
|
||||
Close a performance schema table.
|
||||
The last table opened by open_performance_schema_table()
|
||||
is closed, then the thread context is restored.
|
||||
@param thd The current thread
|
||||
@param backup [in] the context to restore.
|
||||
*/
|
||||
void close_performance_schema_table(THD *thd, Open_tables_state *backup)
|
||||
{
|
||||
bool found_old_table;
|
||||
|
||||
if (thd->lock)
|
||||
{
|
||||
/*
|
||||
Note:
|
||||
We do not create explicitly a separate transaction for the
|
||||
performance table I/O, but borrow the current transaction.
|
||||
lock + unlock will autocommit the change done in the
|
||||
performance schema table: this is the expected result.
|
||||
The current transaction should not be affected by this code.
|
||||
TODO: Note that if a transactional engine is used for log tables,
|
||||
this code will need to be revised, as a separate transaction
|
||||
might be needed.
|
||||
*/
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock= 0;
|
||||
}
|
||||
|
||||
safe_mutex_assert_not_owner(&LOCK_open);
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
|
||||
found_old_table= false;
|
||||
while (thd->open_tables)
|
||||
found_old_table|= close_thread_table(thd, &thd->open_tables);
|
||||
|
||||
if (found_old_table)
|
||||
broadcast_refresh();
|
||||
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
thd->restore_backup_open_tables_state(backup);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user