diff options
-rw-r--r-- | mysql-test/suite/maria/lock.result | 19 | ||||
-rw-r--r-- | mysql-test/suite/maria/lock.test | 23 | ||||
-rw-r--r-- | sql/sql_admin.cc | 38 | ||||
-rw-r--r-- | sql/sql_base.cc | 32 | ||||
-rw-r--r-- | sql/sql_partition.cc | 10 | ||||
-rw-r--r-- | sql/sql_reload.cc | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 2 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 4 |
9 files changed, 98 insertions, 38 deletions
diff --git a/mysql-test/suite/maria/lock.result b/mysql-test/suite/maria/lock.result index 606cb5fed4d..101347c7d4c 100644 --- a/mysql-test/suite/maria/lock.result +++ b/mysql-test/suite/maria/lock.result @@ -8,3 +8,22 @@ LOCK TABLE t1 WRITE, t2 WRITE; DROP TABLE t1; UNLOCK TABLES; DROP TABLE t2; +CREATE TABLE t1 (i INT) ENGINE=Aria; +CREATE TABLE t2 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE, t2 WRITE; +FLUSH TABLE t1; +select * from t1; +i +unlock tables; +drop table t1,t2; +CREATE TABLE t1 (i INT) ENGINE=Aria; +CREATE TABLE t2 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE, t2 WRITE; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair status OK +select * from t1; +i +drop table t2; +unlock tables; +drop table t1; diff --git a/mysql-test/suite/maria/lock.test b/mysql-test/suite/maria/lock.test index 564cf965d17..6116f0b5f08 100644 --- a/mysql-test/suite/maria/lock.test +++ b/mysql-test/suite/maria/lock.test @@ -12,6 +12,8 @@ drop table if exists t1,t2; # under LOCK # +# Test DROP TABLE + CREATE TABLE t1 (i INT) ENGINE=Aria; CREATE TABLE t2 (i INT) ENGINE=Aria; LOCK TABLE t1 WRITE, t2 WRITE; @@ -19,3 +21,24 @@ LOCK TABLE t1 WRITE, t2 WRITE; DROP TABLE t1; UNLOCK TABLES; DROP TABLE t2; + +#Test FLUSH TABLE + +CREATE TABLE t1 (i INT) ENGINE=Aria; +CREATE TABLE t2 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE, t2 WRITE; +FLUSH TABLE t1; +select * from t1; +unlock tables; +drop table t1,t2; + +# Test REPAIR ... USE_FRM and unlock tables last + +CREATE TABLE t1 (i INT) ENGINE=Aria; +CREATE TABLE t2 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE, t2 WRITE; +repair table t1 use_frm; +select * from t1; +drop table t2; +unlock tables; +drop table t1; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 7d5012f8cdf..8d0f2e5634f 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -80,6 +80,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, { int error= 0; TABLE tmp_table, *table; + TABLE_LIST *pos_in_locked_tables= 0; TABLE_SHARE *share; bool has_mdl_lock= FALSE; char from[FN_REFLEN],tmp[FN_REFLEN+32]; @@ -194,9 +195,13 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Table was successfully open in mysql_admin_table(). Now we need to close it, but leave it protected by exclusive metadata lock. */ - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + pos_in_locked_tables= table->pos_in_locked_tables; + if (wait_while_table_is_used(thd, table, + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) goto end; - close_all_tables_for_name(thd, table_list->table->s, HA_EXTRA_NORMAL); + /* Close table but don't remove from locked list */ + close_all_tables_for_name(thd, table_list->table->s, + HA_EXTRA_NOT_USED); table_list->table= 0; } /* @@ -230,18 +235,25 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, goto end; } - if (thd->locked_tables_list.reopen_tables(thd)) - goto end; - - /* - Now we should be able to open the partially repaired table - to finish the repair in the handler later on. - */ - if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) + if (thd->locked_tables_list.locked_tables()) { - error= send_check_errmsg(thd, table_list, "repair", - "Failed to open partially repaired table"); - goto end; + if (thd->locked_tables_list.reopen_tables(thd)) + goto end; + /* Restore the table in the table list with the new opened table */ + table_list->table= pos_in_locked_tables->table; + } + else + { + /* + Now we should be able to open the partially repaired table + to finish the repair in the handler later on. + */ + if (open_table(thd, table_list, thd->mem_root, &ot_ctx)) + { + error= send_check_errmsg(thd, table_list, "repair", + "Failed to open partially repaired table"); + goto end; + } } end: diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 88f7484b52f..c5d11aa71f6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1097,7 +1097,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, TABLE_LIST *tables_to_reopen= (tables ? tables : thd->locked_tables_list.locked_tables()); - /* Close open HANLER instances to avoid self-deadlock. */ + /* Close open HANDLER instances to avoid self-deadlock. */ mysql_ha_flush_tables(thd, tables_to_reopen); for (TABLE_LIST *table_list= tables_to_reopen; table_list; @@ -1111,12 +1111,13 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, if (! table) continue; - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + if (wait_while_table_is_used(thd, table, + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) { result= TRUE; goto err_with_reopen; } - close_all_tables_for_name(thd, table->s, HA_EXTRA_NORMAL); + close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED); } } @@ -1382,9 +1383,11 @@ static void close_open_tables(THD *thd) @param[in] share table share, but is just a handy way to access the table cache key - @param[in] remove_from_locked_tables - TRUE if the table is being dropped or renamed. - In that case the documented behaviour is to + @param[in] extra + HA_EXTRA_PREPRE_FOR_DROP if the table is being dropped + HA_EXTRA_PREPARE_FOR_REANME if the table is being renamed + HA_EXTRA_NOT_USED no drop/rename + In case of drop/reanme the documented behaviour is to implicitly remove the table from LOCK TABLES list. @@ -1412,10 +1415,13 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, { thd->locked_tables_list.unlink_from_list(thd, table->pos_in_locked_tables, - extra != HA_EXTRA_NORMAL); - /* Inform handler that there is a drop table or rename going on */ - if (extra != HA_EXTRA_NORMAL && table->db_stat) + extra != HA_EXTRA_NOT_USED); + /* Inform handler that there is a drop table or a rename going on */ + if (extra != HA_EXTRA_NOT_USED && table->db_stat) + { table->file->extra(extra); + extra= HA_EXTRA_NOT_USED; // Call extra once! + } /* Does nothing if the table is not locked. @@ -2312,7 +2318,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db, @param function HA_EXTRA_PREPARE_FOR_DROP if table is to be deleted HA_EXTRA_FORCE_REOPEN if table is not be used HA_EXTRA_PREPARE_FOR_RENAME if table is to be renamed - HA_EXTRA_NORMAL Don't call extra() + HA_EXTRA_NOT_USED Don't call extra() @note When returning, the table will be unusable for other threads until metadata lock is downgraded. @@ -2337,7 +2343,7 @@ bool wait_while_table_is_used(THD *thd, TABLE *table, table->s->db.str, table->s->table_name.str, FALSE); /* extra() call must come only after all instances above are closed */ - if (function != HA_EXTRA_NORMAL) + if (function != HA_EXTRA_NOT_USED) (void) table->file->extra(function); DBUG_RETURN(FALSE); } @@ -3386,7 +3392,6 @@ Locked_tables_list::init_locked_tables(THD *thd) void Locked_tables_list::unlock_locked_tables(THD *thd) - { if (thd) { @@ -3408,7 +3413,8 @@ Locked_tables_list::unlock_locked_tables(THD *thd) Clear the position in the list, the TABLE object will be returned to the table cache. */ - table_list->table->pos_in_locked_tables= NULL; + if (table_list->table) // If not closed + table_list->table->pos_in_locked_tables= NULL; } thd->leave_locked_tables_mode(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 00fba5f331a..a9c79589faa 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6270,7 +6270,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) THD *thd= lpt->thd; if (lpt->old_table) - close_all_tables_for_name(thd, lpt->old_table->s, HA_EXTRA_NORMAL); + close_all_tables_for_name(thd, lpt->old_table->s, HA_EXTRA_NOT_USED); if (lpt->table) { /* @@ -6307,7 +6307,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt, bool close_old) } if (close_old && lpt->old_table) { - close_all_tables_for_name(lpt->thd, lpt->old_table->s, HA_EXTRA_NORMAL); + close_all_tables_for_name(lpt->thd, lpt->old_table->s, HA_EXTRA_NOT_USED); lpt->old_table= 0; } DBUG_RETURN(0); @@ -6640,7 +6640,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || ERROR_INJECT_CRASH("crash_drop_partition_2") || ERROR_INJECT_ERROR("fail_drop_partition_2") || - wait_while_table_is_used(thd, table, HA_EXTRA_NORMAL) || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || ERROR_INJECT_CRASH("crash_drop_partition_3") || ERROR_INJECT_ERROR("fail_drop_partition_3") || (close_table_on_failure= TRUE, FALSE) || @@ -6714,7 +6714,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, mysql_write_frm(lpt, WFRM_WRITE_SHADOW) || ERROR_INJECT_CRASH("crash_add_partition_2") || ERROR_INJECT_ERROR("fail_add_partition_2") || - wait_while_table_is_used(thd, table, HA_EXTRA_NORMAL) || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || ERROR_INJECT_CRASH("crash_add_partition_3") || ERROR_INJECT_ERROR("fail_add_partition_3") || (close_table_on_failure= TRUE, FALSE) || @@ -6820,7 +6820,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, mysql_change_partitions(lpt) || ERROR_INJECT_CRASH("crash_change_partition_4") || ERROR_INJECT_ERROR("fail_change_partition_4") || - wait_while_table_is_used(thd, table, HA_EXTRA_NORMAL) || + wait_while_table_is_used(thd, table, HA_EXTRA_NOT_USED) || ERROR_INJECT_CRASH("crash_change_partition_5") || ERROR_INJECT_ERROR("fail_change_partition_5") || write_log_final_change_partition(lpt) || diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index d2f118b62c9..1f3b1effff3 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -243,9 +243,9 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, { /* It is not safe to upgrade the metadata lock without GLOBAL IX lock. - This can happen with FLUSH TABLES <list> WITH READ LOCK as we in these - cases don't take a GLOBAL IX lock in order to be compatible with - global read lock. + This can happen with FLUSH TABLES <list> WITH READ LOCK as we in + these cases don't take a GLOBAL IX lock in order to be compatible + with global read lock. */ if (thd->open_tables && !thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 51d1eab14f1..6e9d1709c8a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6894,7 +6894,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, close_all_tables_for_name(thd, table->s, new_name != table_name || new_db != db ? HA_EXTRA_PREPARE_FOR_RENAME : - HA_EXTRA_NORMAL); + HA_EXTRA_NOT_USED); error=0; table_list->table= table= 0; /* Safety */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 2eefe7d2c74..1b942ecc93b 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -561,7 +561,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) if (result) goto end; - close_all_tables_for_name(thd, table->s, HA_EXTRA_NORMAL); + close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED); /* Reopen the table if we were under LOCK TABLES. Ignore the return value for now. It's better to diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index b84a00eb0fc..3c1b231d3f2 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -358,12 +358,12 @@ bool Truncate_statement::lock_table(THD *thd, TABLE_LIST *table_ref, { DEBUG_SYNC(thd, "upgrade_lock_for_truncate"); /* To remove the table from the cache we need an exclusive lock. */ - if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN)) + if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DROP)) DBUG_RETURN(TRUE); m_ticket_downgrade= table->mdl_ticket; /* Close if table is going to be recreated. */ if (*hton_can_recreate) - close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_DROP); + close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED); } else { |