mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Backport of:
---------------------------------------------------------- revno: 2630.10.1 committer: Konstantin Osipov <konstantin@mysql.com> branch nick: mysql-6.0-lock-tables-tidyup timestamp: Wed 2008-06-11 15:49:58 +0400 message: WL#3726, review fixes. Now that we have metadata locks, we don't need to keep a crippled TABLE instance in the table cache to indicate that a table is locked. Remove all code that used this technique. Instead, rely on metadata locks and use the standard open_table() and close_thread_table() to manipulate with the table cache tables. Removes a list of functions that have become unused (see the comment for sql_base.cc for details). Under LOCK TABLES, keep a TABLE_LIST instance for each table that may be temporarily closed. For that, implement an own class for LOCK TABLES mode, Locked_tables_list. This is a pre-requisite patch for WL#4144. This is not exactly a backport: there is no new online ALTER table in Celosia, so the old alter table code was changed to work with the new table cache API. mysql-test/r/lock.result: Update results (WL#3726 post-review patch). mysql-test/r/trigger-compat.result: We take the table from the table cache now, thus no warning. mysql-test/suite/rpl/r/rpl_trigger.result: We take the table from the table cache now, thus no warning. mysql-test/t/lock.test: Additional tests for LOCK TABLES mode (previously not covered by the test suite (WL#3726). sql/field.h: Remove reopen_table(). sql/lock.cc: Remove an obsolete parameter of mysql_lock_remove(). It's not used anywhere now either. sql/mysql_priv.h: Add 4 new open_table() flags. Remove declarations of removed functions. sql/sp_head.cc: Rename thd->mdl_el_root to thd->locked_tables_root. sql/sql_acl.cc: Use the new implementation of unlock_locked_tables(). sql/sql_base.cc: Implement class Locked_tables_list. Implement close_all_tables_for_name(). Rewrite close_cached_tables() to use the new reopen_tables(). Remove reopen_table(), reopen_tables(), reopen_table_entry() (ex. open_unireg_entry()), close_data_files_and_leave_as_placeholders(), close_handle_and_leave_table_as_placeholder(), close_cached_table(), table_def_change_share(), reattach_merge(), reopen_name_locked_table(), unlink_open_table(). Move acquisition of a metadata lock into an own function - open_table_get_mdl_lock(). sql/sql_class.cc: Deploy class Locked_tables_list. sql/sql_class.h: Declare class Locked_tables_list. Keep one instance of this class in class THD. Rename mdl_el_root to locked_tables_root. sql/sql_db.cc: Update a comment. sql/sql_insert.cc: Use the plain open_table() to open a just created table in CREATE TABLE .. SELECT. sql/sql_parse.cc: Use thd->locked_tables_list to enter and leave LTM_LOCK_TABLES mode. sql/sql_partition.cc: Deploy the new method of working with partitioned table locks. sql/sql_servers.cc: Update to the new signature of unlock_locked_tables(). sql/sql_table.cc: In mysql_rm_table_part2(), the branch that removes a table under LOCK TABLES, make sure that the table being dropped is also removed from THD::locked_tables_list. Update ALTER TABLE and CREATE TABLE LIKE implementation to use open_table() and close_all_tables_for_name() instead of reopen_tables(). sql/sql_trigger.cc: Use the new locking way. sql/table.h: Add TABLE::pos_in_locked_tables, which is used only under LOCK TABLES.
This commit is contained in:
@@ -201,3 +201,48 @@ ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
|
|||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
End of 5.1 tests.
|
End of 5.1 tests.
|
||||||
|
#
|
||||||
|
# Ensure that FLUSH TABLES doesn't substitute a base locked table
|
||||||
|
# with a temporary one.
|
||||||
|
#
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
lock table t1 write, t2 write;
|
||||||
|
create temporary table t1 (a int);
|
||||||
|
flush table t1;
|
||||||
|
drop temporary table t1;
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
unlock tables;
|
||||||
|
drop table t1, t2;
|
||||||
|
#
|
||||||
|
# Ensure that REPAIR .. USE_FRM works under LOCK TABLES.
|
||||||
|
#
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
lock table t1 write, t2 write;
|
||||||
|
repair table t1 use_frm;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 repair status OK
|
||||||
|
repair table t1 use_frm;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 repair status OK
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
select * from t2;
|
||||||
|
a
|
||||||
|
repair table t2 use_frm;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t2 repair status OK
|
||||||
|
repair table t2 use_frm;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t2 repair status OK
|
||||||
|
select * from t1;
|
||||||
|
a
|
||||||
|
unlock tables;
|
||||||
|
drop table t1, t2;
|
||||||
|
#
|
||||||
|
# End of 6.0 tests.
|
||||||
|
#
|
||||||
|
@@ -34,8 +34,6 @@ TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATA
|
|||||||
def mysqltest_db1 wl2818_trg1 INSERT def mysqltest_db1 t1 0 NULL INSERT INTO t2 VALUES(CURRENT_USER()) ROW BEFORE NULL NULL OLD NEW NULL latin1 latin1_swedish_ci latin1_swedish_ci
|
def mysqltest_db1 wl2818_trg1 INSERT def mysqltest_db1 t1 0 NULL INSERT INTO t2 VALUES(CURRENT_USER()) ROW BEFORE NULL NULL OLD NEW NULL latin1 latin1_swedish_ci latin1_swedish_ci
|
||||||
def mysqltest_db1 wl2818_trg2 INSERT def mysqltest_db1 t1 0 NULL INSERT INTO t2 VALUES(CURRENT_USER()) ROW AFTER NULL NULL OLD NEW NULL mysqltest_dfn@localhost latin1 latin1_swedish_ci latin1_swedish_ci
|
def mysqltest_db1 wl2818_trg2 INSERT def mysqltest_db1 t1 0 NULL INSERT INTO t2 VALUES(CURRENT_USER()) ROW AFTER NULL NULL OLD NEW NULL mysqltest_dfn@localhost latin1 latin1_swedish_ci latin1_swedish_ci
|
||||||
DROP TRIGGER wl2818_trg1;
|
DROP TRIGGER wl2818_trg1;
|
||||||
Warnings:
|
|
||||||
Warning 1454 No definer attribute for trigger 'mysqltest_db1'.'wl2818_trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
|
|
||||||
DROP TRIGGER wl2818_trg2;
|
DROP TRIGGER wl2818_trg2;
|
||||||
use mysqltest_db1;
|
use mysqltest_db1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@@ -893,8 +893,6 @@ s
|
|||||||
@
|
@
|
||||||
root@localhost
|
root@localhost
|
||||||
DROP TRIGGER trg1;
|
DROP TRIGGER trg1;
|
||||||
Warnings:
|
|
||||||
Warning 1454 No definer attribute for trigger 'test'.'trg1'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger.
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
STOP SLAVE;
|
STOP SLAVE;
|
||||||
|
@@ -252,3 +252,46 @@ UNLOCK TABLES;
|
|||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
--echo End of 5.1 tests.
|
--echo End of 5.1 tests.
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Ensure that FLUSH TABLES doesn't substitute a base locked table
|
||||||
|
--echo # with a temporary one.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
lock table t1 write, t2 write;
|
||||||
|
create temporary table t1 (a int);
|
||||||
|
flush table t1;
|
||||||
|
drop temporary table t1;
|
||||||
|
select * from t1;
|
||||||
|
unlock tables;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Ensure that REPAIR .. USE_FRM works under LOCK TABLES.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
lock table t1 write, t2 write;
|
||||||
|
repair table t1 use_frm;
|
||||||
|
repair table t1 use_frm;
|
||||||
|
select * from t1;
|
||||||
|
select * from t2;
|
||||||
|
repair table t2 use_frm;
|
||||||
|
repair table t2 use_frm;
|
||||||
|
select * from t1;
|
||||||
|
unlock tables;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 6.0 tests.
|
||||||
|
--echo #
|
||||||
|
@@ -478,7 +478,6 @@ public:
|
|||||||
}
|
}
|
||||||
/* Hash value */
|
/* Hash value */
|
||||||
virtual void hash(ulong *nr, ulong *nr2);
|
virtual void hash(ulong *nr, ulong *nr2);
|
||||||
friend bool reopen_table(THD *,struct st_table *,bool);
|
|
||||||
friend int cre_myisam(char * name, register TABLE *form, uint options,
|
friend int cre_myisam(char * name, register TABLE *form, uint options,
|
||||||
ulonglong auto_increment_value);
|
ulonglong auto_increment_value);
|
||||||
friend class Copy_field;
|
friend class Copy_field;
|
||||||
|
20
sql/lock.cc
20
sql/lock.cc
@@ -512,28 +512,15 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
|
|||||||
/**
|
/**
|
||||||
Try to find the table in the list of locked tables.
|
Try to find the table in the list of locked tables.
|
||||||
In case of success, unlock the table and remove it from this list.
|
In case of success, unlock the table and remove it from this list.
|
||||||
|
If a table has more than one lock instance, removes them all.
|
||||||
@note This function has a legacy side effect: the table is
|
|
||||||
unlocked even if it is not found in the locked list.
|
|
||||||
It's not clear if this side effect is intentional or still
|
|
||||||
desirable. It might lead to unmatched calls to
|
|
||||||
unlock_external(). Moreover, a discrepancy can be left
|
|
||||||
unnoticed by the storage engine, because in
|
|
||||||
unlock_external() we call handler::external_lock(F_UNLCK) only
|
|
||||||
if table->current_lock is not F_UNLCK.
|
|
||||||
|
|
||||||
@param thd thread context
|
@param thd thread context
|
||||||
@param locked list of locked tables
|
@param locked list of locked tables
|
||||||
@param table the table to unlock
|
@param table the table to unlock
|
||||||
@param always_unlock specify explicitly if the legacy side
|
|
||||||
effect is desired.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
|
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
|
||||||
bool always_unlock)
|
|
||||||
{
|
{
|
||||||
if (always_unlock == TRUE)
|
|
||||||
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
|
|
||||||
if (locked)
|
if (locked)
|
||||||
{
|
{
|
||||||
reg1 uint i;
|
reg1 uint i;
|
||||||
@@ -547,8 +534,7 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
|
|||||||
|
|
||||||
DBUG_ASSERT(table->lock_position == i);
|
DBUG_ASSERT(table->lock_position == i);
|
||||||
|
|
||||||
/* Unlock if not yet unlocked */
|
/* Unlock the table. */
|
||||||
if (always_unlock == FALSE)
|
|
||||||
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
|
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
|
||||||
|
|
||||||
/* Decrement table_count in advance, making below expressions easier */
|
/* Decrement table_count in advance, making below expressions easier */
|
||||||
|
@@ -1225,20 +1225,13 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
|
|||||||
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias,
|
||||||
char *cache_key, uint cache_key_length,
|
char *cache_key, uint cache_key_length,
|
||||||
MEM_ROOT *mem_root, uint flags);
|
MEM_ROOT *mem_root, uint flags);
|
||||||
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list);
|
|
||||||
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
|
TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
|
||||||
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
TABLE *find_write_locked_table(TABLE *list, const char *db,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
void detach_merge_children(TABLE *table, bool clear_refs);
|
void detach_merge_children(TABLE *table, bool clear_refs);
|
||||||
bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
|
bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
|
||||||
TABLE_LIST *new_child_list, TABLE_LIST **new_last);
|
TABLE_LIST *new_child_list, TABLE_LIST **new_last);
|
||||||
bool reopen_table(TABLE *table);
|
|
||||||
bool reopen_tables(THD *thd, bool get_locks);
|
|
||||||
thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table);
|
thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table);
|
||||||
void close_data_files_and_leave_as_placeholders(THD *thd, const char *db,
|
|
||||||
const char *table_name);
|
|
||||||
void close_handle_and_leave_table_as_placeholder(TABLE *table);
|
|
||||||
void unlock_locked_tables(THD *thd);
|
|
||||||
void execute_init_command(THD *thd, sys_var_str *init_command_var,
|
void execute_init_command(THD *thd, sys_var_str *init_command_var,
|
||||||
rw_lock_t *var_mutex);
|
rw_lock_t *var_mutex);
|
||||||
extern Field *not_found_field;
|
extern Field *not_found_field;
|
||||||
@@ -1388,12 +1381,12 @@ void add_join_on(TABLE_LIST *b,Item *expr);
|
|||||||
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
|
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
|
||||||
SELECT_LEX *lex);
|
SELECT_LEX *lex);
|
||||||
bool add_proc_to_list(THD *thd, Item *item);
|
bool add_proc_to_list(THD *thd, Item *item);
|
||||||
bool close_cached_table(THD *thd, TABLE *table);
|
|
||||||
bool wait_while_table_is_used(THD *thd, TABLE *table,
|
bool wait_while_table_is_used(THD *thd, TABLE *table,
|
||||||
enum ha_extra_function function);
|
enum ha_extra_function function);
|
||||||
void unlink_open_table(THD *thd, TABLE *find, bool unlock);
|
|
||||||
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
void drop_open_table(THD *thd, TABLE *table, const char *db_name,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
|
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
|
||||||
|
bool remove_from_locked_tables);
|
||||||
void update_non_unique_table_error(TABLE_LIST *update,
|
void update_non_unique_table_error(TABLE_LIST *update,
|
||||||
const char *operation,
|
const char *operation,
|
||||||
TABLE_LIST *duplicate);
|
TABLE_LIST *duplicate);
|
||||||
@@ -1515,7 +1508,6 @@ void close_temporary_table(THD *thd, TABLE *table, bool free_share,
|
|||||||
void close_temporary(TABLE *table, bool free_share, bool delete_table);
|
void close_temporary(TABLE *table, bool free_share, bool delete_table);
|
||||||
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
||||||
const char *table_name);
|
const char *table_name);
|
||||||
void remove_db_from_cache(const char *db);
|
|
||||||
void flush_tables();
|
void flush_tables();
|
||||||
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
||||||
char *make_default_log_name(char *buff,const char* log_ext);
|
char *make_default_log_name(char *buff,const char* log_ext);
|
||||||
@@ -1561,7 +1553,7 @@ void create_subpartition_name(char *out, const char *in1,
|
|||||||
|
|
||||||
typedef struct st_lock_param_type
|
typedef struct st_lock_param_type
|
||||||
{
|
{
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST *table_list;
|
||||||
ulonglong copied;
|
ulonglong copied;
|
||||||
ulonglong deleted;
|
ulonglong deleted;
|
||||||
THD *thd;
|
THD *thd;
|
||||||
@@ -1572,7 +1564,6 @@ typedef struct st_lock_param_type
|
|||||||
const char *db;
|
const char *db;
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
uchar *pack_frm_data;
|
uchar *pack_frm_data;
|
||||||
enum thr_lock_type old_lock_type;
|
|
||||||
uint key_count;
|
uint key_count;
|
||||||
uint db_options;
|
uint db_options;
|
||||||
size_t pack_frm_len;
|
size_t pack_frm_len;
|
||||||
@@ -2044,12 +2035,31 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
|
|||||||
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008
|
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008
|
||||||
#define MYSQL_LOCK_PERF_SCHEMA 0x0010
|
#define MYSQL_LOCK_PERF_SCHEMA 0x0010
|
||||||
#define MYSQL_OPEN_TAKE_UPGRADABLE_MDL 0x0020
|
#define MYSQL_OPEN_TAKE_UPGRADABLE_MDL 0x0020
|
||||||
|
/**
|
||||||
|
Do not try to acquire a metadata lock on the table: we
|
||||||
|
already have one.
|
||||||
|
*/
|
||||||
|
#define MYSQL_OPEN_HAS_MDL_LOCK 0x0040
|
||||||
|
/**
|
||||||
|
If in locked tables mode, ignore the locked tables and get
|
||||||
|
a new instance of the table.
|
||||||
|
*/
|
||||||
|
#define MYSQL_OPEN_GET_NEW_TABLE 0x0080
|
||||||
|
/** Don't look up the table in the list of temporary tables. */
|
||||||
|
#define MYSQL_OPEN_SKIP_TEMPORARY 0x0100
|
||||||
|
|
||||||
|
/** Please refer to the internals manual. */
|
||||||
|
#define MYSQL_OPEN_REOPEN (MYSQL_LOCK_IGNORE_FLUSH |\
|
||||||
|
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |\
|
||||||
|
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\
|
||||||
|
MYSQL_OPEN_GET_NEW_TABLE |\
|
||||||
|
MYSQL_OPEN_SKIP_TEMPORARY |\
|
||||||
|
MYSQL_OPEN_HAS_MDL_LOCK)
|
||||||
|
|
||||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||||
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
|
||||||
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
|
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
|
||||||
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
|
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
|
||||||
bool always_unlock);
|
|
||||||
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock);
|
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock);
|
||||||
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
|
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
|
||||||
thr_lock_type new_lock_type);
|
thr_lock_type new_lock_type);
|
||||||
|
@@ -3985,8 +3985,8 @@ sp_head::add_used_tables_to_table_list(THD *thd,
|
|||||||
table->belong_to_view= belong_to_view;
|
table->belong_to_view= belong_to_view;
|
||||||
table->trg_event_map= stab->trg_event_map;
|
table->trg_event_map= stab->trg_event_map;
|
||||||
table->mdl_lock_data= mdl_alloc_lock(0, table->db, table->table_name,
|
table->mdl_lock_data= mdl_alloc_lock(0, table->db, table->table_name,
|
||||||
thd->mdl_el_root ?
|
thd->locked_tables_root ?
|
||||||
thd->mdl_el_root :
|
thd->locked_tables_root :
|
||||||
thd->mem_root);
|
thd->mem_root);
|
||||||
|
|
||||||
/* Everyting else should be zeroed */
|
/* Everyting else should be zeroed */
|
||||||
@@ -4030,8 +4030,9 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
|
|||||||
table->select_lex= lex->current_select;
|
table->select_lex= lex->current_select;
|
||||||
table->cacheable_table= 1;
|
table->cacheable_table= 1;
|
||||||
table->mdl_lock_data= mdl_alloc_lock(0, table->db, table->table_name,
|
table->mdl_lock_data= mdl_alloc_lock(0, table->db, table->table_name,
|
||||||
thd->mdl_el_root ? thd->mdl_el_root :
|
thd->locked_tables_root ?
|
||||||
thd->mem_root);
|
thd->locked_tables_root : thd->mem_root);
|
||||||
|
|
||||||
lex->add_to_query_tables(table);
|
lex->add_to_query_tables(table);
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
@@ -676,7 +676,8 @@ my_bool acl_reload(THD *thd)
|
|||||||
my_bool return_val= 1;
|
my_bool return_val= 1;
|
||||||
DBUG_ENTER("acl_reload");
|
DBUG_ENTER("acl_reload");
|
||||||
|
|
||||||
unlock_locked_tables(thd); // Can't have locked tables here
|
/* Can't have locked tables here. */
|
||||||
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To avoid deadlocks we should obtain table locks before
|
To avoid deadlocks we should obtain table locks before
|
||||||
|
1355
sql/sql_base.cc
1355
sql/sql_base.cc
File diff suppressed because it is too large
Load Diff
@@ -469,7 +469,7 @@ THD::THD()
|
|||||||
debug_sync_control(0),
|
debug_sync_control(0),
|
||||||
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
||||||
main_warning_info(0),
|
main_warning_info(0),
|
||||||
mdl_el_root(NULL)
|
locked_tables_root(NULL)
|
||||||
{
|
{
|
||||||
ulong tmp;
|
ulong tmp;
|
||||||
|
|
||||||
@@ -574,8 +574,6 @@ THD::THD()
|
|||||||
thr_lock_owner_init(&main_lock_id, &lock_info);
|
thr_lock_owner_init(&main_lock_id, &lock_info);
|
||||||
|
|
||||||
m_internal_handler= NULL;
|
m_internal_handler= NULL;
|
||||||
|
|
||||||
init_sql_alloc(&locked_tables_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -995,7 +993,7 @@ void THD::cleanup(void)
|
|||||||
ha_rollback(this);
|
ha_rollback(this);
|
||||||
xid_cache_delete(&transaction.xid_state);
|
xid_cache_delete(&transaction.xid_state);
|
||||||
}
|
}
|
||||||
unlock_locked_tables(this);
|
locked_tables_list.unlock_locked_tables(this);
|
||||||
|
|
||||||
#if defined(ENABLED_DEBUG_SYNC)
|
#if defined(ENABLED_DEBUG_SYNC)
|
||||||
/* End the Debug Sync Facility. See debug_sync.cc. */
|
/* End the Debug Sync Facility. See debug_sync.cc. */
|
||||||
@@ -1074,7 +1072,6 @@ THD::~THD()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
free_root(&main_mem_root, MYF(0));
|
free_root(&main_mem_root, MYF(0));
|
||||||
free_root(&locked_tables_root, MYF(0));
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1169,6 +1169,58 @@ private:
|
|||||||
Internal_error_handler *m_err_handler;
|
Internal_error_handler *m_err_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Tables that were locked with LOCK TABLES statement.
|
||||||
|
|
||||||
|
Encapsulates a list of TABLE_LIST instances for tables
|
||||||
|
locked by LOCK TABLES statement, memory root for metadata locks,
|
||||||
|
and, generally, the context of LOCK TABLES statement.
|
||||||
|
|
||||||
|
In LOCK TABLES mode, the locked tables are kept open between
|
||||||
|
statements.
|
||||||
|
Therefore, we can't allocate metadata locks on execution memory
|
||||||
|
root -- as well as tables, the locks need to stay around till
|
||||||
|
UNLOCK TABLES is called.
|
||||||
|
The locks are allocated in the memory root encapsulate in this
|
||||||
|
class.
|
||||||
|
|
||||||
|
Some SQL commands, like FLUSH TABLE or ALTER TABLE, demand that
|
||||||
|
the tables they operate on are closed, at least temporarily.
|
||||||
|
This class encapsulates a list of TABLE_LIST instances, one
|
||||||
|
for each base table from LOCK TABLES list,
|
||||||
|
which helps conveniently close the TABLEs when it's necessary
|
||||||
|
and later reopen them.
|
||||||
|
|
||||||
|
Implemented in sql_base.cc
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Locked_tables_list
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
MEM_ROOT m_locked_tables_root;
|
||||||
|
TABLE_LIST *m_locked_tables;
|
||||||
|
TABLE_LIST **m_locked_tables_last;
|
||||||
|
public:
|
||||||
|
Locked_tables_list()
|
||||||
|
:m_locked_tables(NULL),
|
||||||
|
m_locked_tables_last(&m_locked_tables)
|
||||||
|
{
|
||||||
|
init_sql_alloc(&m_locked_tables_root, MEM_ROOT_BLOCK_SIZE, 0);
|
||||||
|
}
|
||||||
|
void unlock_locked_tables(THD *thd);
|
||||||
|
~Locked_tables_list()
|
||||||
|
{
|
||||||
|
unlock_locked_tables(0);
|
||||||
|
}
|
||||||
|
bool init_locked_tables(THD *thd);
|
||||||
|
TABLE_LIST *locked_tables() { return m_locked_tables; }
|
||||||
|
MEM_ROOT *locked_tables_root() { return &m_locked_tables_root; }
|
||||||
|
void unlink_from_list(THD *thd, TABLE_LIST *table_list,
|
||||||
|
bool remove_from_locked_tables);
|
||||||
|
void unlink_all_closed_tables();
|
||||||
|
bool reopen_tables(THD *thd);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Storage engine specific thread local data.
|
Storage engine specific thread local data.
|
||||||
@@ -1810,6 +1862,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
Parser_state *m_parser_state;
|
Parser_state *m_parser_state;
|
||||||
|
|
||||||
|
Locked_tables_list locked_tables_list;
|
||||||
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
partition_info *work_part_info;
|
partition_info *work_part_info;
|
||||||
#endif
|
#endif
|
||||||
@@ -1819,8 +1873,13 @@ public:
|
|||||||
struct st_debug_sync_control *debug_sync_control;
|
struct st_debug_sync_control *debug_sync_control;
|
||||||
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
#endif /* defined(ENABLED_DEBUG_SYNC) */
|
||||||
|
|
||||||
MEM_ROOT *mdl_el_root;
|
/**
|
||||||
MEM_ROOT locked_tables_root;
|
Points to the memory root of Locked_tables_list if
|
||||||
|
we're locking the tables for LOCK TABLES. Otherwise is NULL.
|
||||||
|
This is necessary to ensure that metadata locks allocated for
|
||||||
|
tables used in triggers will persist after statement end.
|
||||||
|
*/
|
||||||
|
MEM_ROOT *locked_tables_root;
|
||||||
|
|
||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
|
@@ -1956,8 +1956,8 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Step7: drop the old database.
|
Step7: drop the old database.
|
||||||
remove_db_from_cache(olddb) and query_cache_invalidate(olddb)
|
query_cache_invalidate(olddb) is done inside mysql_rm_db(), no need
|
||||||
are done inside mysql_rm_db(), no needs to execute them again.
|
to execute them again.
|
||||||
mysql_rm_db() also "unuses" if we drop the current database.
|
mysql_rm_db() also "unuses" if we drop the current database.
|
||||||
*/
|
*/
|
||||||
error= mysql_rm_db(thd, old_db->str, 0, 1);
|
error= mysql_rm_db(thd, old_db->str, 0, 1);
|
||||||
|
@@ -3542,16 +3542,22 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
|
|
||||||
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_open);
|
enum enum_open_table_action ot_action_unused;
|
||||||
if (reopen_name_locked_table(thd, create_table))
|
/*
|
||||||
|
Here we open the destination table, on which we already have
|
||||||
|
an exclusive metadata lock.
|
||||||
|
*/
|
||||||
|
if (open_table(thd, create_table, thd->mem_root,
|
||||||
|
&ot_action_unused, MYSQL_OPEN_REOPEN))
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&LOCK_open);
|
||||||
quick_rm_table(create_info->db_type, create_table->db,
|
quick_rm_table(create_info->db_type, create_table->db,
|
||||||
table_case_name(create_info, create_table->table_name),
|
table_case_name(create_info, create_table->table_name),
|
||||||
0);
|
0);
|
||||||
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
table= create_table->table;
|
table= create_table->table;
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -184,7 +184,7 @@ bool begin_trans(THD *thd)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_locked_tables(thd);
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
|
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
error= -1;
|
error= -1;
|
||||||
@@ -3583,7 +3583,7 @@ end_with_restore_list:
|
|||||||
done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
|
done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
|
||||||
false, mysqldump will not work.
|
false, mysqldump will not work.
|
||||||
*/
|
*/
|
||||||
unlock_locked_tables(thd);
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
if (thd->options & OPTION_TABLE_LOCK)
|
if (thd->options & OPTION_TABLE_LOCK)
|
||||||
{
|
{
|
||||||
end_active_trans(thd);
|
end_active_trans(thd);
|
||||||
@@ -3594,7 +3594,7 @@ end_with_restore_list:
|
|||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
break;
|
break;
|
||||||
case SQLCOM_LOCK_TABLES:
|
case SQLCOM_LOCK_TABLES:
|
||||||
unlock_locked_tables(thd);
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
/* we must end the trasaction first, regardless of anything */
|
/* we must end the trasaction first, regardless of anything */
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
@@ -3604,22 +3604,21 @@ end_with_restore_list:
|
|||||||
if (lex->protect_against_global_read_lock &&
|
if (lex->protect_against_global_read_lock &&
|
||||||
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
|
!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
|
||||||
goto error;
|
goto error;
|
||||||
thd->in_lock_tables=1;
|
|
||||||
thd->options|= OPTION_TABLE_LOCK;
|
|
||||||
alloc_mdl_locks(all_tables, &thd->locked_tables_root);
|
|
||||||
thd->mdl_el_root= &thd->locked_tables_root;
|
|
||||||
|
|
||||||
if (!(res= open_and_lock_tables_derived(thd, all_tables, FALSE,
|
alloc_mdl_locks(all_tables, thd->locked_tables_list.locked_tables_root());
|
||||||
MYSQL_OPEN_TAKE_UPGRADABLE_MDL)))
|
|
||||||
{
|
thd->options|= OPTION_TABLE_LOCK;
|
||||||
#ifdef HAVE_QUERY_CACHE
|
thd->in_lock_tables=1;
|
||||||
if (thd->variables.query_cache_wlock_invalidate)
|
thd->locked_tables_root= thd->locked_tables_list.locked_tables_root();
|
||||||
query_cache.invalidate_locked_for_write(first_table);
|
|
||||||
#endif /*HAVE_QUERY_CACHE*/
|
res= (open_and_lock_tables_derived(thd, all_tables, FALSE,
|
||||||
thd->locked_tables_mode= LTM_LOCK_TABLES;
|
MYSQL_OPEN_TAKE_UPGRADABLE_MDL) ||
|
||||||
my_ok(thd);
|
thd->locked_tables_list.init_locked_tables(thd));
|
||||||
}
|
|
||||||
else
|
thd->in_lock_tables= 0;
|
||||||
|
thd->locked_tables_root= NULL;
|
||||||
|
|
||||||
|
if (res)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Need to end the current transaction, so the storage engine (InnoDB)
|
Need to end the current transaction, so the storage engine (InnoDB)
|
||||||
@@ -3630,8 +3629,14 @@ end_with_restore_list:
|
|||||||
end_active_trans(thd);
|
end_active_trans(thd);
|
||||||
thd->options&= ~(OPTION_TABLE_LOCK);
|
thd->options&= ~(OPTION_TABLE_LOCK);
|
||||||
}
|
}
|
||||||
thd->in_lock_tables=0;
|
else
|
||||||
thd->mdl_el_root= 0;
|
{
|
||||||
|
#ifdef HAVE_QUERY_CACHE
|
||||||
|
if (thd->variables.query_cache_wlock_invalidate)
|
||||||
|
query_cache.invalidate_locked_for_write(first_table);
|
||||||
|
#endif /*HAVE_QUERY_CACHE*/
|
||||||
|
my_ok(thd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SQLCOM_CREATE_DB:
|
case SQLCOM_CREATE_DB:
|
||||||
{
|
{
|
||||||
@@ -6534,8 +6539,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
|||||||
/* Link table in global list (all used tables) */
|
/* Link table in global list (all used tables) */
|
||||||
lex->add_to_query_tables(ptr);
|
lex->add_to_query_tables(ptr);
|
||||||
ptr->mdl_lock_data= mdl_alloc_lock(0 , ptr->db, ptr->table_name,
|
ptr->mdl_lock_data= mdl_alloc_lock(0 , ptr->db, ptr->table_name,
|
||||||
thd->mdl_el_root ? thd->mdl_el_root :
|
thd->locked_tables_root ?
|
||||||
thd->mem_root);
|
thd->locked_tables_root : thd->mem_root);
|
||||||
DBUG_RETURN(ptr);
|
DBUG_RETURN(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4314,7 +4314,6 @@ set_engine_all_partitions(partition_info *part_info,
|
|||||||
|
|
||||||
static int fast_end_partition(THD *thd, ulonglong copied,
|
static int fast_end_partition(THD *thd, ulonglong copied,
|
||||||
ulonglong deleted,
|
ulonglong deleted,
|
||||||
TABLE *table,
|
|
||||||
TABLE_LIST *table_list, bool is_empty,
|
TABLE_LIST *table_list, bool is_empty,
|
||||||
ALTER_PARTITION_PARAM_TYPE *lpt,
|
ALTER_PARTITION_PARAM_TYPE *lpt,
|
||||||
bool written_bin_log)
|
bool written_bin_log)
|
||||||
@@ -4333,11 +4332,7 @@ static int fast_end_partition(THD *thd, ulonglong copied,
|
|||||||
error= 1;
|
error= 1;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
DBUG_RETURN(TRUE); /* The error has been reported */
|
||||||
/* If error during commit, no need to rollback, it's done. */
|
|
||||||
table->file->print_error(error, MYF(0));
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!is_empty) && (!written_bin_log) &&
|
if ((!is_empty) && (!written_bin_log) &&
|
||||||
(!thd->lex->no_write_to_binlog))
|
(!thd->lex->no_write_to_binlog))
|
||||||
@@ -6215,30 +6210,13 @@ static void release_log_entries(partition_info *part_info)
|
|||||||
*/
|
*/
|
||||||
static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
|
static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||||
{
|
{
|
||||||
int err;
|
THD *thd= lpt->thd;
|
||||||
if (lpt->thd->locked_tables_mode)
|
|
||||||
{
|
close_all_tables_for_name(thd, lpt->table->s, FALSE);
|
||||||
/*
|
lpt->table= 0;
|
||||||
When we have the table locked, it is necessary to reopen the table
|
lpt->table_list->table= 0;
|
||||||
since all table objects were closed and removed as part of the
|
if (thd->locked_tables_list.reopen_tables(thd))
|
||||||
ALTER TABLE of partitioning structure.
|
|
||||||
*/
|
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
lpt->thd->in_lock_tables= 1;
|
|
||||||
err= reopen_tables(lpt->thd, 1);
|
|
||||||
lpt->thd->in_lock_tables= 0;
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Issue a warning since we weren't able to regain the lock again.
|
|
||||||
We also need to unlink table from thread's open list and from
|
|
||||||
table_cache
|
|
||||||
*/
|
|
||||||
unlink_open_table(lpt->thd, lpt->table, FALSE);
|
|
||||||
sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE");
|
sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE");
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6252,17 +6230,37 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
|
|||||||
|
|
||||||
static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
|
static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||||
{
|
{
|
||||||
|
TABLE_SHARE *share= lpt->table->s;
|
||||||
THD *thd= lpt->thd;
|
THD *thd= lpt->thd;
|
||||||
const char *db= lpt->db;
|
TABLE *table;
|
||||||
const char *table_name= lpt->table_name;
|
|
||||||
DBUG_ENTER("alter_close_tables");
|
DBUG_ENTER("alter_close_tables");
|
||||||
/*
|
/*
|
||||||
We need to also unlock tables and close all handlers.
|
We must keep LOCK_open while manipulating with thd->open_tables.
|
||||||
We set lock to zero to ensure we don't do this twice
|
Another thread may be working on it.
|
||||||
and we set db_stat to zero to ensure we don't close twice.
|
|
||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
close_data_files_and_leave_as_placeholders(thd, db, table_name);
|
/*
|
||||||
|
We can safely remove locks for all tables with the same name:
|
||||||
|
later they will all be closed anyway in
|
||||||
|
alter_partition_lock_handling().
|
||||||
|
*/
|
||||||
|
for (table= thd->open_tables; table ; table= table->next)
|
||||||
|
{
|
||||||
|
if (!strcmp(table->s->table_name.str, share->table_name.str) &&
|
||||||
|
!strcmp(table->s->db.str, share->db.str))
|
||||||
|
{
|
||||||
|
mysql_lock_remove(thd, thd->lock, table);
|
||||||
|
table->file->close();
|
||||||
|
table->db_stat= 0; // Mark file closed
|
||||||
|
/*
|
||||||
|
Ensure that we won't end up with a crippled table instance
|
||||||
|
in the table cache if an error occurs before we reach
|
||||||
|
alter_partition_lock_handling() and the table is closed
|
||||||
|
by close_thread_tables() instead.
|
||||||
|
*/
|
||||||
|
table->s->version= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@@ -6429,6 +6427,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||||||
DBUG_ENTER("fast_alter_partition_table");
|
DBUG_ENTER("fast_alter_partition_table");
|
||||||
|
|
||||||
lpt->thd= thd;
|
lpt->thd= thd;
|
||||||
|
lpt->table_list= table_list;
|
||||||
lpt->part_info= part_info;
|
lpt->part_info= part_info;
|
||||||
lpt->alter_info= alter_info;
|
lpt->alter_info= alter_info;
|
||||||
lpt->create_info= create_info;
|
lpt->create_info= create_info;
|
||||||
@@ -6745,7 +6744,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
|
|||||||
user
|
user
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted,
|
DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted,
|
||||||
table, table_list, FALSE, NULL,
|
table_list, FALSE, NULL,
|
||||||
written_bin_log));
|
written_bin_log));
|
||||||
err:
|
err:
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
@@ -224,7 +224,8 @@ bool servers_reload(THD *thd)
|
|||||||
bool return_val= TRUE;
|
bool return_val= TRUE;
|
||||||
DBUG_ENTER("servers_reload");
|
DBUG_ENTER("servers_reload");
|
||||||
|
|
||||||
unlock_locked_tables(thd); // Can't have locked tables here
|
/* Can't have locked tables here */
|
||||||
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("locking servers_cache"));
|
DBUG_PRINT("info", ("locking servers_cache"));
|
||||||
rw_wrlock(&THR_LOCK_servers);
|
rw_wrlock(&THR_LOCK_servers);
|
||||||
|
159
sql/sql_table.cc
159
sql/sql_table.cc
@@ -1966,7 +1966,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
case -1:
|
case -1:
|
||||||
DBUG_ASSERT(thd->in_sub_stmt);
|
DBUG_ASSERT(thd->in_sub_stmt);
|
||||||
error= 1;
|
error= 1;
|
||||||
goto err_with_placeholders;
|
goto err;
|
||||||
default:
|
default:
|
||||||
// temporary table not found
|
// temporary table not found
|
||||||
error= 0;
|
error= 0;
|
||||||
@@ -2003,18 +2003,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
{
|
{
|
||||||
if (thd->locked_tables_mode)
|
if (thd->locked_tables_mode)
|
||||||
{
|
{
|
||||||
if (close_cached_table(thd, table->table))
|
if (wait_while_table_is_used(thd, table->table, HA_EXTRA_FORCE_REOPEN))
|
||||||
{
|
{
|
||||||
error= -1;
|
error= -1;
|
||||||
goto err_with_placeholders;
|
goto err;
|
||||||
}
|
}
|
||||||
|
close_all_tables_for_name(thd, table->table->s, TRUE);
|
||||||
table->table= 0;
|
table->table= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->killed)
|
if (thd->killed)
|
||||||
{
|
{
|
||||||
error= -1;
|
error= -1;
|
||||||
goto err_with_placeholders;
|
goto err;
|
||||||
}
|
}
|
||||||
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
|
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
|
||||||
/* remove .frm file and engine files */
|
/* remove .frm file and engine files */
|
||||||
@@ -2178,7 +2179,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err_with_placeholders:
|
err:
|
||||||
if (!drop_temporary)
|
if (!drop_temporary)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -2195,7 +2196,7 @@ err_with_placeholders:
|
|||||||
if (thd->locked_tables_mode &&
|
if (thd->locked_tables_mode &&
|
||||||
thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0)
|
thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0)
|
||||||
{
|
{
|
||||||
unlock_locked_tables(thd);
|
thd->locked_tables_list.unlock_locked_tables(thd);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
for (table= tables; table; table= table->next_local)
|
for (table= tables; table; table= table->next_local)
|
||||||
@@ -4315,6 +4316,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
|
|||||||
HA_CHECK_OPT *check_opt)
|
HA_CHECK_OPT *check_opt)
|
||||||
{
|
{
|
||||||
MDL_LOCK_DATA *mdl_lock_data= 0;
|
MDL_LOCK_DATA *mdl_lock_data= 0;
|
||||||
|
enum enum_open_table_action ot_action_unused;
|
||||||
DBUG_ENTER("prepare_for_restore");
|
DBUG_ENTER("prepare_for_restore");
|
||||||
|
|
||||||
if (table->table) // do not overwrite existing tables on restore
|
if (table->table) // do not overwrite existing tables on restore
|
||||||
@@ -4360,16 +4362,16 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
|
|||||||
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
|
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
|
||||||
"Failed generating table from .frm file"));
|
"Failed generating table from .frm file"));
|
||||||
}
|
}
|
||||||
|
table->mdl_lock_data= mdl_lock_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we should be able to open the partially restored table
|
Now we should be able to open the partially restored table
|
||||||
to finish the restore in the handler later on
|
to finish the restore in the handler later on
|
||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&LOCK_open);
|
if (open_table(thd, table, thd->mem_root,
|
||||||
if (reopen_name_locked_table(thd, table))
|
&ot_action_unused, MYSQL_OPEN_REOPEN))
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
if (mdl_lock_data)
|
if (mdl_lock_data)
|
||||||
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
|
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
|
||||||
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
|
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
|
||||||
@@ -4377,7 +4379,6 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
|
|||||||
}
|
}
|
||||||
/* A MERGE table must not come here. */
|
/* A MERGE table must not come here. */
|
||||||
DBUG_ASSERT(!table->table || !table->table->child_l);
|
DBUG_ASSERT(!table->table || !table->table->child_l);
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4392,7 +4393,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
const char **ext;
|
const char **ext;
|
||||||
MY_STAT stat_info;
|
MY_STAT stat_info;
|
||||||
MDL_LOCK_DATA *mdl_lock_data;
|
MDL_LOCK_DATA *mdl_lock_data;
|
||||||
|
enum enum_open_table_action ot_action_unused;
|
||||||
DBUG_ENTER("prepare_for_repair");
|
DBUG_ENTER("prepare_for_repair");
|
||||||
|
uint reopen_for_repair_flags= (MYSQL_LOCK_IGNORE_FLUSH |
|
||||||
|
MYSQL_OPEN_HAS_MDL_LOCK);
|
||||||
|
|
||||||
if (!(check_opt->sql_flags & TT_USEFRM))
|
if (!(check_opt->sql_flags & TT_USEFRM))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@@ -4428,8 +4432,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
DBUG_RETURN(0); // Out of memory
|
DBUG_RETURN(0); // Out of memory
|
||||||
}
|
}
|
||||||
table= &tmp_table;
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
table= &tmp_table;
|
||||||
|
table_list->mdl_lock_data= mdl_lock_data;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4490,8 +4495,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
Table was successfully open in mysql_admin_table(). Now we need
|
Table was successfully open in mysql_admin_table(). Now we need
|
||||||
to close it, but leave it protected by exclusive metadata lock.
|
to close it, but leave it protected by exclusive metadata lock.
|
||||||
*/
|
*/
|
||||||
if (close_cached_table(thd, table))
|
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
|
||||||
goto end;
|
goto end;
|
||||||
|
close_all_tables_for_name(thd, table_list->table->s, FALSE);
|
||||||
table_list->table= 0;
|
table_list->table= 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -4519,21 +4525,23 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thd->locked_tables_list.reopen_tables(thd))
|
||||||
|
goto end;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we should be able to open the partially repaired table
|
Now we should be able to open the partially repaired table
|
||||||
to finish the repair in the handler later on.
|
to finish the repair in the handler later on.
|
||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&LOCK_open);
|
if (open_table(thd, table_list, thd->mem_root,
|
||||||
if (reopen_name_locked_table(thd, table_list))
|
&ot_action_unused, reopen_for_repair_flags))
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
error= send_check_errmsg(thd, table_list, "repair",
|
error= send_check_errmsg(thd, table_list, "repair",
|
||||||
"Failed to open partially repaired table");
|
"Failed to open partially repaired table");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
thd->locked_tables_list.unlink_all_closed_tables();
|
||||||
if (table == &tmp_table)
|
if (table == &tmp_table)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
@@ -5334,6 +5342,11 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
|
|||||||
db, table_name, reg_ext, 0);
|
db, table_name, reg_ext, 0);
|
||||||
if (!access(dst_path, F_OK))
|
if (!access(dst_path, F_OK))
|
||||||
goto table_exists;
|
goto table_exists;
|
||||||
|
/*
|
||||||
|
Make the metadata lock available to open_table() called to
|
||||||
|
reopen the table down the road.
|
||||||
|
*/
|
||||||
|
table->mdl_lock_data= target_lock_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
|
DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
|
||||||
@@ -5463,20 +5476,16 @@ binlog:
|
|||||||
char buf[2048];
|
char buf[2048];
|
||||||
String query(buf, sizeof(buf), system_charset_info);
|
String query(buf, sizeof(buf), system_charset_info);
|
||||||
query.length(0); // Have to zero it since constructor doesn't
|
query.length(0); // Have to zero it since constructor doesn't
|
||||||
|
enum enum_open_table_action ot_action_unused;
|
||||||
/*
|
/*
|
||||||
Here we open the destination table, on which we already have
|
Here we open the destination table, on which we already have
|
||||||
exclusive metada lock. This is needed for store_create_info()
|
exclusive metadata lock. This is needed for store_create_info()
|
||||||
to work. The table will be closed by unlink_open_table() at
|
to work. The table will be closed by close_thread_table() at
|
||||||
the end of this function.
|
the end of this branch.
|
||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&LOCK_open);
|
if (open_table(thd, table, thd->mem_root, &ot_action_unused,
|
||||||
if (reopen_name_locked_table(thd, table))
|
MYSQL_OPEN_REOPEN))
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
|
|
||||||
int result __attribute__((unused))=
|
int result __attribute__((unused))=
|
||||||
store_create_info(thd, table, &query,
|
store_create_info(thd, table, &query,
|
||||||
@@ -5485,8 +5494,14 @@ binlog:
|
|||||||
DBUG_ASSERT(result == 0); // store_create_info() always return 0
|
DBUG_ASSERT(result == 0); // store_create_info() always return 0
|
||||||
write_bin_log(thd, TRUE, query.ptr(), query.length());
|
write_bin_log(thd, TRUE, query.ptr(), query.length());
|
||||||
|
|
||||||
|
DBUG_ASSERT(thd->open_tables == table->table);
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
unlink_open_table(thd, table->table, FALSE);
|
/*
|
||||||
|
When opening the table, we ignored the locked tables
|
||||||
|
(MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table without
|
||||||
|
risking to close some locked table.
|
||||||
|
*/
|
||||||
|
close_thread_table(thd, &thd->open_tables);
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
}
|
}
|
||||||
else // Case 1
|
else // Case 1
|
||||||
@@ -6789,13 +6804,14 @@ view_err:
|
|||||||
/*
|
/*
|
||||||
Then do a 'simple' rename of the table. First we need to close all
|
Then do a 'simple' rename of the table. First we need to close all
|
||||||
instances of 'source' table.
|
instances of 'source' table.
|
||||||
Note that if close_cached_table() returns error here (i.e. if
|
Note that if wait_while_table_is_used() returns error here (i.e. if
|
||||||
this thread was killed) then it must be that previous step of
|
this thread was killed) then it must be that previous step of
|
||||||
simple rename did nothing and therefore we can safely reture
|
simple rename did nothing and therefore we can safely return
|
||||||
without additional clean-up.
|
without additional clean-up.
|
||||||
*/
|
*/
|
||||||
if (close_cached_table(thd, table))
|
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
|
||||||
goto err;
|
goto err;
|
||||||
|
close_all_tables_for_name(thd, table->s, TRUE);
|
||||||
/*
|
/*
|
||||||
Then, we want check once again that target table does not exist.
|
Then, we want check once again that target table does not exist.
|
||||||
Actually the order of these two steps does not matter since
|
Actually the order of these two steps does not matter since
|
||||||
@@ -7384,11 +7400,12 @@ view_err:
|
|||||||
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
|
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
|
||||||
goto err_new_table_cleanup;
|
goto err_new_table_cleanup;
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
|
|
||||||
close_data_files_and_leave_as_placeholders(thd, db, table_name);
|
close_all_tables_for_name(thd, table->s,
|
||||||
|
new_name != table_name || new_db != db);
|
||||||
|
|
||||||
error=0;
|
error=0;
|
||||||
|
table_list->table= table= 0; /* Safety */
|
||||||
save_old_db_type= old_db_type;
|
save_old_db_type= old_db_type;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -7410,6 +7427,7 @@ view_err:
|
|||||||
/* This type cannot happen in regular ALTER. */
|
/* This type cannot happen in regular ALTER. */
|
||||||
new_db_type= old_db_type= NULL;
|
new_db_type= old_db_type= NULL;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_lock(&LOCK_open);
|
||||||
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
|
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
|
||||||
FN_TO_IS_TMP))
|
FN_TO_IS_TMP))
|
||||||
{
|
{
|
||||||
@@ -7433,10 +7451,15 @@ view_err:
|
|||||||
FN_FROM_IS_TMP);
|
FN_FROM_IS_TMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! error)
|
||||||
|
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
/* This shouldn't happen. But let us play it safe. */
|
/* This shouldn't happen. But let us play it safe. */
|
||||||
goto err_with_placeholders;
|
goto err_with_mdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
|
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
|
||||||
@@ -7446,6 +7469,7 @@ view_err:
|
|||||||
To do this we need to obtain a handler object for it.
|
To do this we need to obtain a handler object for it.
|
||||||
NO need to tamper with MERGE tables. The real open is done later.
|
NO need to tamper with MERGE tables. The real open is done later.
|
||||||
*/
|
*/
|
||||||
|
enum enum_open_table_action ot_action_unused;
|
||||||
TABLE *t_table;
|
TABLE *t_table;
|
||||||
if (new_name != table_name || new_db != db)
|
if (new_name != table_name || new_db != db)
|
||||||
{
|
{
|
||||||
@@ -7454,51 +7478,39 @@ view_err:
|
|||||||
table_list->table_name_length= strlen(new_name);
|
table_list->table_name_length= strlen(new_name);
|
||||||
table_list->db= new_db;
|
table_list->db= new_db;
|
||||||
table_list->db_length= strlen(new_db);
|
table_list->db_length= strlen(new_db);
|
||||||
if (reopen_name_locked_table(thd, table_list))
|
table_list->mdl_lock_data= target_lock_data;
|
||||||
goto err_with_placeholders;
|
|
||||||
t_table= table_list->table;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (reopen_table(table))
|
|
||||||
goto err_with_placeholders;
|
|
||||||
t_table= table;
|
|
||||||
}
|
|
||||||
/* Tell the handler that a new frm file is in place. */
|
|
||||||
if (t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG,
|
|
||||||
create_info))
|
|
||||||
goto err_with_placeholders;
|
|
||||||
if (thd->locked_tables_mode)
|
|
||||||
{
|
|
||||||
if (new_name == table_name && new_db == db)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We are going to reopen table down on the road, so we have to restore
|
Under LOCK TABLES, we have a different mdl_lock_data
|
||||||
state of the TABLE object which we used for obtaining of handler
|
points to a different instance than the one set initially
|
||||||
object to make it suitable for reopening.
|
to request the lock.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(t_table == table);
|
table_list->mdl_lock_data= mdl_lock_data;
|
||||||
close_handle_and_leave_table_as_placeholder(table);
|
|
||||||
}
|
}
|
||||||
else
|
if (open_table(thd, table_list, thd->mem_root,
|
||||||
|
&ot_action_unused, MYSQL_OPEN_REOPEN))
|
||||||
{
|
{
|
||||||
/* Unlink the new name from the list of locked tables. */
|
goto err_with_mdl;
|
||||||
unlink_open_table(thd, t_table, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
t_table= table_list->table;
|
||||||
|
|
||||||
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
/* Tell the handler that a new frm file is in place. */
|
||||||
|
error= t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG,
|
||||||
|
create_info);
|
||||||
|
|
||||||
if (thd->locked_tables_mode && new_name == table_name && new_db == db)
|
DBUG_ASSERT(thd->open_tables == t_table);
|
||||||
{
|
pthread_mutex_lock(&LOCK_open);
|
||||||
thd->in_lock_tables= 1;
|
close_thread_table(thd, &thd->open_tables);
|
||||||
error= reopen_tables(thd, 1);
|
|
||||||
thd->in_lock_tables= 0;
|
|
||||||
if (error)
|
|
||||||
goto err_with_placeholders;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
table_list->table= 0;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
goto err_with_mdl;
|
||||||
|
}
|
||||||
|
if (thd->locked_tables_list.reopen_tables(thd))
|
||||||
|
goto err_with_mdl;
|
||||||
|
|
||||||
thd_proc_info(thd, "end");
|
thd_proc_info(thd, "end");
|
||||||
|
|
||||||
@@ -7541,9 +7553,6 @@ view_err:
|
|||||||
{
|
{
|
||||||
if ((new_name != table_name || new_db != db))
|
if ((new_name != table_name || new_db != db))
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
unlink_open_table(thd, table, FALSE);
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
||||||
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
|
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
|
||||||
}
|
}
|
||||||
@@ -7607,14 +7616,14 @@ err:
|
|||||||
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
err_with_placeholders:
|
err_with_mdl:
|
||||||
/*
|
/*
|
||||||
An error happened while we were holding exclusive name metadata lock
|
An error happened while we were holding exclusive name metadata lock
|
||||||
on table being altered. To be safe under LOCK TABLES we should remove
|
on table being altered. To be safe under LOCK TABLES we should
|
||||||
placeholders from the list of open tables and relese metadata lock.
|
remove all references to the altered table from the list of locked
|
||||||
|
tables and release the exclusive metadata lock.
|
||||||
*/
|
*/
|
||||||
unlink_open_table(thd, table, FALSE);
|
thd->locked_tables_list.unlink_all_closed_tables();
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
if (target_lock_data)
|
if (target_lock_data)
|
||||||
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
mdl_release_lock(&thd->mdl_context, target_lock_data);
|
||||||
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
|
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
|
||||||
|
@@ -328,6 +328,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||||||
bool result= TRUE;
|
bool result= TRUE;
|
||||||
String stmt_query;
|
String stmt_query;
|
||||||
bool need_start_waiting= FALSE;
|
bool need_start_waiting= FALSE;
|
||||||
|
bool lock_upgrade_done= FALSE;
|
||||||
|
|
||||||
DBUG_ENTER("mysql_create_or_drop_trigger");
|
DBUG_ENTER("mysql_create_or_drop_trigger");
|
||||||
|
|
||||||
@@ -450,72 +451,54 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||||||
if (!(tables->table= find_write_locked_table(thd->open_tables, tables->db,
|
if (!(tables->table= find_write_locked_table(thd->open_tables, tables->db,
|
||||||
tables->table_name)))
|
tables->table_name)))
|
||||||
goto end;
|
goto end;
|
||||||
/*
|
/* Later on we will need it to downgrade the lock */
|
||||||
Ensure that table is opened only by this thread and that no other
|
tables->mdl_lock_data= tables->table->mdl_lock_data;
|
||||||
statement will open this table.
|
|
||||||
*/
|
|
||||||
if (wait_while_table_is_used(thd, tables->table, HA_EXTRA_FORCE_REOPEN))
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
tables->table= open_n_lock_single_table(thd, tables,
|
||||||
Obtain exlusive meta-data lock on the table and remove TABLE
|
TL_WRITE_ALLOW_READ,
|
||||||
instances from cache.
|
MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
|
||||||
*/
|
if (! tables->table)
|
||||||
if (lock_table_names(thd, tables))
|
|
||||||
goto end;
|
goto end;
|
||||||
|
tables->table->use_all_columns();
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, tables->db, tables->table_name);
|
|
||||||
|
|
||||||
if (reopen_name_locked_table(thd, tables))
|
|
||||||
goto end_unlock;
|
|
||||||
}
|
}
|
||||||
table= tables->table;
|
table= tables->table;
|
||||||
|
|
||||||
|
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
lock_upgrade_done= TRUE;
|
||||||
|
|
||||||
if (!table->triggers)
|
if (!table->triggers)
|
||||||
{
|
{
|
||||||
if (!create)
|
if (!create)
|
||||||
{
|
{
|
||||||
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
||||||
goto end_unlock;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
|
if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
|
||||||
goto end_unlock;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&LOCK_open);
|
||||||
result= (create ?
|
result= (create ?
|
||||||
table->triggers->create_trigger(thd, tables, &stmt_query):
|
table->triggers->create_trigger(thd, tables, &stmt_query):
|
||||||
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
table->triggers->drop_trigger(thd, tables, &stmt_query));
|
||||||
|
|
||||||
/* Under LOCK TABLES we must reopen the table to activate the trigger. */
|
|
||||||
if (!result && thd->locked_tables_mode)
|
|
||||||
{
|
|
||||||
/* Make table suitable for reopening */
|
|
||||||
close_data_files_and_leave_as_placeholders(thd, tables->db,
|
|
||||||
tables->table_name);
|
|
||||||
thd->in_lock_tables= 1;
|
|
||||||
if (reopen_tables(thd, 1))
|
|
||||||
{
|
|
||||||
/* To be safe remove this table from the set of LOCKED TABLES */
|
|
||||||
unlink_open_table(thd, tables->table, FALSE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Ignore reopen_tables errors for now. It's better not leave master/slave
|
|
||||||
in a inconsistent state.
|
|
||||||
*/
|
|
||||||
thd->clear_error();
|
|
||||||
}
|
|
||||||
thd->in_lock_tables= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
end_unlock:
|
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
pthread_mutex_unlock(&LOCK_open);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
close_all_tables_for_name(thd, table->s, FALSE);
|
||||||
|
/*
|
||||||
|
Reopen the table if we were under LOCK TABLES.
|
||||||
|
Ignore the return value for now. It's better to
|
||||||
|
keep master/slave in consistent state.
|
||||||
|
*/
|
||||||
|
thd->locked_tables_list.reopen_tables(thd);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
@@ -525,11 +508,11 @@ end:
|
|||||||
/*
|
/*
|
||||||
If we are under LOCK TABLES we should restore original state of meta-data
|
If we are under LOCK TABLES we should restore original state of meta-data
|
||||||
locks. Otherwise call to close_thread_tables() will take care about both
|
locks. Otherwise call to close_thread_tables() will take care about both
|
||||||
TABLE instance created by reopen_name_locked_table() and metadata lock.
|
TABLE instance created by open_n_lock_single_table() and metadata lock.
|
||||||
*/
|
*/
|
||||||
if (thd->locked_tables_mode && tables && tables->table)
|
if (thd->locked_tables_mode && tables && lock_upgrade_done)
|
||||||
mdl_downgrade_exclusive_lock(&thd->mdl_context,
|
mdl_downgrade_exclusive_lock(&thd->mdl_context,
|
||||||
tables->table->mdl_lock_data);
|
tables->mdl_lock_data);
|
||||||
|
|
||||||
if (need_start_waiting)
|
if (need_start_waiting)
|
||||||
start_waiting_global_read_lock(thd);
|
start_waiting_global_read_lock(thd);
|
||||||
|
@@ -632,7 +632,6 @@ private:
|
|||||||
TABLE *share_next, **share_prev;
|
TABLE *share_next, **share_prev;
|
||||||
|
|
||||||
friend struct TABLE_share;
|
friend struct TABLE_share;
|
||||||
friend bool reopen_table(TABLE *table);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -679,6 +678,8 @@ public:
|
|||||||
/* Table's triggers, 0 if there are no of them */
|
/* Table's triggers, 0 if there are no of them */
|
||||||
Table_triggers_list *triggers;
|
Table_triggers_list *triggers;
|
||||||
TABLE_LIST *pos_in_table_list;/* Element referring to this table */
|
TABLE_LIST *pos_in_table_list;/* Element referring to this table */
|
||||||
|
/* Position in thd->locked_table_list under LOCK TABLES */
|
||||||
|
TABLE_LIST *pos_in_locked_tables;
|
||||||
ORDER *group;
|
ORDER *group;
|
||||||
const char *alias; /* alias or table name */
|
const char *alias; /* alias or table name */
|
||||||
uchar *null_flags;
|
uchar *null_flags;
|
||||||
|
Reference in New Issue
Block a user