diff options
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4471c336188..02a874ce62f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -22,17 +22,17 @@ #include "sql_rename.h" // do_rename #include "sql_parse.h" // test_if_data_home_dir #include "sql_cache.h" // query_cache_* -#include "sql_base.h" // open_temporary_table -#include "lock.h" // wait_if_global_read_lock, lock_table_names, +#include "sql_base.h" // open_temporary_table, lock_table_names +#include "lock.h" // wait_if_global_read_lock // start_waiting_global_read_lock, - // unlock_table_names, mysql_unlock_tables + // mysql_unlock_tables #include "strfunc.h" // find_type2, find_set #include "sql_view.h" // view_checksum #include "sql_truncate.h" // regenerate_locked_table #include "sql_partition.h" // mem_alloc_error, // generate_partition_syntax, // partition_info -#include "sql_db.h" // load_db_opt_by_name, lock_db_cache, creating_database +#include "sql_db.h" // load_db_opt_by_name #include "sql_time.h" // make_truncated_value_warning #include "records.h" // init_read_record, end_read_record #include "filesort.h" // filesort_free_buffers @@ -58,8 +58,6 @@ #include <io.h> #endif -int creating_table= 0; // How many mysql_create_table are running - const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); @@ -1954,7 +1952,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { if (!thd->locked_tables_mode) { - if (lock_table_names(thd, tables)) + if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, + MYSQL_OPEN_SKIP_TEMPORARY)) DBUG_RETURN(1); mysql_mutex_lock(&LOCK_open); for (table= tables; table; table= table->next_local) @@ -1964,7 +1963,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, else { for (table= tables; table; table= table->next_local) - if (find_temporary_table(thd, table->db, table->table_name)) + if (table->open_type != OT_BASE_ONLY && + find_temporary_table(thd, table->db, table->table_name)) { /* A temporary table. @@ -2009,8 +2009,11 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->db, table->table_name, (long) table->table, table->table ? (long) table->table->s : (long) -1)); - error= drop_temporary_table(thd, table); - + if (table->open_type == OT_BASE_ONLY) + error= 1; + else + error= drop_temporary_table(thd, table); + switch (error) { case 0: // removed temporary table @@ -2282,18 +2285,13 @@ err: { /* Under LOCK TABLES we should release meta-data locks on the tables - which were dropped. Otherwise we can rely on close_thread_tables() - doing this. Unfortunately in this case we are likely to get more - false positives in try_acquire_lock() function. So - it makes sense to remove exclusive meta-data locks in all cases. + which were dropped. Leave LOCK TABLES mode if we managed to drop all tables which were locked. Additional check for 'non_temp_tables_count' is to avoid leaving LOCK TABLES mode if we have dropped only temporary tables. */ - if (! thd->locked_tables_mode) - unlock_table_names(thd); - else + if (thd->locked_tables_mode) { if (thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0) { @@ -2302,7 +2300,8 @@ err: } for (table= tables; table; table= table->next_local) { - if (table->mdl_request.ticket) + /* Drop locks for all successfully dropped tables. */ + if (table->table == NULL && table->mdl_request.ticket) { /* Under LOCK TABLES we may have several instances of table open @@ -2313,6 +2312,10 @@ err: } } } + /* + Rely on the caller to implicitly commit the transaction + and release metadata locks. + */ } end: @@ -4211,8 +4214,14 @@ warn: } -/* - Database and name-locking aware wrapper for mysql_create_table_no_lock(), +/** + Implementation of SQLCOM_CREATE_TABLE. + + Take the metadata locks (including a shared lock on the affected + schema) and create the table. Is written to be called from + mysql_execute_command(), to which it delegates the common parts + with other commands (i.e. implicit commit before and after, + close of thread tables. */ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, @@ -4222,31 +4231,13 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, bool result; DBUG_ENTER("mysql_create_table"); - /* Wait for any database locks */ - mysql_mutex_lock(&LOCK_lock_db); - while (!thd->killed && - my_hash_search(&lock_db_cache, (uchar*)create_table->db, - create_table->db_length)) - { - wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - mysql_mutex_lock(&LOCK_lock_db); - } - - if (thd->killed) - { - mysql_mutex_unlock(&LOCK_lock_db); - DBUG_RETURN(TRUE); - } - creating_table++; - mysql_mutex_unlock(&LOCK_lock_db); - /* Open or obtain an exclusive metadata lock on table being created. */ if (open_and_lock_tables(thd, thd->lex->query_tables, FALSE, 0)) { result= TRUE; - goto unlock; + goto end; } /* Got lock. */ @@ -4268,20 +4259,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table, !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) - { - /* - close_thread_tables() takes care about both closing open tables (which - might be still around in case of error) and releasing metadata locks. - */ - close_thread_tables(thd); - } - -unlock: - mysql_mutex_lock(&LOCK_lock_db); - if (!--creating_table && creating_database) - mysql_cond_signal(&COND_refresh); - mysql_mutex_unlock(&LOCK_lock_db); +end: DBUG_RETURN(result); } @@ -4454,8 +4432,6 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, { char key[MAX_DBKEY_LENGTH]; uint key_length; - MDL_request mdl_global_request; - MDL_request_list mdl_requests; /* If the table didn't exist, we have a shared metadata lock on it that is left from mysql_admin_table()'s attempt to @@ -4475,12 +4451,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, table_list->db, table_list->table_name, MDL_EXCLUSIVE); - mdl_global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE); - mdl_requests.push_front(&table_list->mdl_request); - mdl_requests.push_front(&mdl_global_request); - - if (thd->mdl_context.acquire_locks(&mdl_requests, - thd->variables.lock_wait_timeout)) + if (lock_table_names(thd, table_list, table_list->next_global, + thd->variables.lock_wait_timeout, + MYSQL_OPEN_SKIP_TEMPORARY)) DBUG_RETURN(0); has_mdl_lock= TRUE; @@ -4776,6 +4749,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, trans_rollback_stmt(thd); trans_rollback(thd); close_thread_tables(thd); + thd->mdl_context.release_transactional_locks(); DBUG_PRINT("admin", ("simple error, admin next table")); continue; case -1: // error, message could be written to net @@ -5062,11 +5036,11 @@ send_result_message: trans_commit_stmt(thd); trans_commit(thd); close_thread_tables(thd); - table->table= NULL; thd->mdl_context.release_transactional_locks(); + table->table= NULL; if (!result_code) // recreation went ok { - /* Clear the ticket released in close_thread_tables(). */ + /* Clear the ticket released above. */ table->mdl_request.ticket= NULL; DEBUG_SYNC(thd, "ha_admin_open_ltable"); table->mdl_request.set_type(MDL_SHARED_WRITE); @@ -5170,7 +5144,8 @@ send_result_message: May be something modified. Consequently, we have to invalidate the query cache. */ - query_cache_invalidate3(thd, table->table, 0); + table->table= 0; // For query cache + query_cache_invalidate3(thd, table, 0); } } /* Error path, a admin command failed. */ @@ -5178,7 +5153,6 @@ send_result_message: trans_commit_implicit(thd); close_thread_tables(thd); thd->mdl_context.release_transactional_locks(); - table->table=0; // For query cache /* If it is CHECK TABLE v1, v2, v3, and v1, v2, v3 are views, we will run @@ -6575,6 +6549,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info); + DEBUG_SYNC(thd, "alter_table_before_open_tables"); error= open_and_lock_tables(thd, table_list, FALSE, 0, &alter_prelocking_strategy); @@ -6751,13 +6726,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000);); error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) goto err; error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); - /* COND_refresh will be signaled in close_thread_tables() */ break; default: DBUG_ASSERT(FALSE); @@ -6843,8 +6816,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { /* Under LOCK TABLES we should adjust meta-data locks before finishing - statement. Otherwise we can rely on close_thread_tables() releasing - them. + statement. Otherwise we can rely on them being released + along with the implicit commit. */ if (new_name != table_name || new_db != db) { @@ -7391,8 +7364,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, 5) Write statement to the binary log. 6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we remove placeholders and release metadata locks. - 7) If we are not not under LOCK TABLES we rely on close_thread_tables() - call to remove placeholders and releasing metadata locks. + 7) If we are not not under LOCK TABLES we rely on the caller + (mysql_execute_command()) to release metadata locks. */ thd_proc_info(thd, "rename result table"); @@ -8021,7 +7994,13 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, } } thd->clear_error(); + if (! thd->in_sub_stmt) + trans_rollback_stmt(thd); close_thread_tables(thd); + /* + Don't release metadata locks, this will be done at + statement end. + */ table->table=0; // For query cache } if (protocol->write()) @@ -8031,10 +8010,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, my_eof(thd); DBUG_RETURN(FALSE); - err: - close_thread_tables(thd); // Shouldn't be needed - if (table) - table->table=0; +err: DBUG_RETURN(TRUE); } |