Commit ded46870 authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2630.4.20
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Wed 2008-06-04 16:27:06 +0400
message:
  WL#3726 "DDL locking for all metadata objects"

  After review fixes in progress.

  Got rid of TABLE_LIST::mdl_upgradable member and related functions
  by using special flag which to be passed to open_table() which
  asks it to take upgradable metadata lock on table being opened.
parent 11eb7b94
...@@ -1488,7 +1488,7 @@ inline int open_and_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -1488,7 +1488,7 @@ inline int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
} }
/* simple open_and_lock_tables without derived handling for single table */ /* simple open_and_lock_tables without derived handling for single table */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type); thr_lock_type lock_type, uint flags);
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags); bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags, int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags,
bool *need_reopen); bool *need_reopen);
...@@ -2040,6 +2040,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, ...@@ -2040,6 +2040,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0004 #define MYSQL_OPEN_TEMPORARY_ONLY 0x0004
#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
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);
......
...@@ -2598,6 +2598,9 @@ void table_share_release_hook(void *share) ...@@ -2598,6 +2598,9 @@ void table_share_release_hook(void *share)
No version number checking is done. No version number checking is done.
MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary
table not the base table or view. table not the base table or view.
MYSQL_OPEN_TAKE_UPGRADABLE_MDL - Obtain upgradable
metadata lock for tables on which we are going to
take some kind of write table-level lock.
IMPLEMENTATION IMPLEMENTATION
Uses a cache of open tables to find a table not in use. Uses a cache of open tables to find a table not in use.
...@@ -2825,7 +2828,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -2825,7 +2828,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{ {
bool retry; bool retry;
if (table_list->mdl_upgradable) if (flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL &&
table_list->lock_type >= TL_WRITE_ALLOW_WRITE)
mdl_set_upgradable(mdl_lock_data); mdl_set_upgradable(mdl_lock_data);
mdl_set_lock_priority(mdl_lock_data, (flags & MYSQL_LOCK_IGNORE_FLUSH) ? mdl_set_lock_priority(mdl_lock_data, (flags & MYSQL_LOCK_IGNORE_FLUSH) ?
MDL_HIGH_PRIO : MDL_NORMAL_PRIO); MDL_HIGH_PRIO : MDL_NORMAL_PRIO);
...@@ -4146,7 +4150,6 @@ static int add_merge_table_list(TABLE_LIST *tlist) ...@@ -4146,7 +4150,6 @@ static int add_merge_table_list(TABLE_LIST *tlist)
/* Set lock type. */ /* Set lock type. */
child_l->lock_type= tlist->lock_type; child_l->lock_type= tlist->lock_type;
child_l->mdl_upgradable= tlist->mdl_upgradable;
/* Set parent reference. */ /* Set parent reference. */
child_l->parent_l= tlist; child_l->parent_l= tlist;
...@@ -4905,6 +4908,8 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, ...@@ -4905,6 +4908,8 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
@param[in] thd thread handle @param[in] thd thread handle
@param[in] table_l table to open is first table in this list @param[in] table_l table to open is first table in this list
@param[in] lock_type lock to use for table @param[in] lock_type lock to use for table
@param[in] flags options to be used while opening and locking
table (see open_table(), mysql_lock_tables())
@return table @return table
@retval != NULL OK, opened table returned @retval != NULL OK, opened table returned
...@@ -4930,7 +4935,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, ...@@ -4930,7 +4935,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
*/ */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type) thr_lock_type lock_type, uint flags)
{ {
TABLE_LIST *save_next_global; TABLE_LIST *save_next_global;
DBUG_ENTER("open_n_lock_single_table"); DBUG_ENTER("open_n_lock_single_table");
...@@ -4946,7 +4951,7 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, ...@@ -4946,7 +4951,7 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
table_l->required_type= FRMTYPE_TABLE; table_l->required_type= FRMTYPE_TABLE;
/* Open the table. */ /* Open the table. */
if (simple_open_n_lock_tables(thd, table_l)) if (open_and_lock_tables_derived(thd, table_l, FALSE, flags))
table_l->table= NULL; /* Just to be sure. */ table_l->table= NULL; /* Just to be sure. */
/* Restore list. */ /* Restore list. */
......
...@@ -2304,7 +2304,7 @@ void kill_delayed_threads(void) ...@@ -2304,7 +2304,7 @@ void kill_delayed_threads(void)
bool Delayed_insert::open_and_lock_table() bool Delayed_insert::open_and_lock_table()
{ {
if (!(table= open_n_lock_single_table(&thd, &table_list, if (!(table= open_n_lock_single_table(&thd, &table_list,
TL_WRITE_DELAYED))) TL_WRITE_DELAYED, 0)))
{ {
thd.fatal_error(); // Abort waiting inserts thd.fatal_error(); // Abort waiting inserts
return TRUE; return TRUE;
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
"FUNCTION" : "PROCEDURE") "FUNCTION" : "PROCEDURE")
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
static void adjust_mdl_locks_upgradability(TABLE_LIST *tables);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
...@@ -3608,9 +3607,9 @@ case SQLCOM_PREPARE: ...@@ -3608,9 +3607,9 @@ case SQLCOM_PREPARE:
thd->options|= OPTION_TABLE_LOCK; thd->options|= OPTION_TABLE_LOCK;
alloc_mdl_locks(all_tables, &thd->locked_tables_root); alloc_mdl_locks(all_tables, &thd->locked_tables_root);
thd->mdl_el_root= &thd->locked_tables_root; thd->mdl_el_root= &thd->locked_tables_root;
adjust_mdl_locks_upgradability(all_tables);
if (!(res= simple_open_n_lock_tables(thd, all_tables))) if (!(res= open_and_lock_tables_derived(thd, all_tables, FALSE,
MYSQL_OPEN_TAKE_UPGRADABLE_MDL)))
{ {
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
if (thd->variables.query_cache_wlock_invalidate) if (thd->variables.query_cache_wlock_invalidate)
...@@ -8106,21 +8105,6 @@ bool parse_sql(THD *thd, ...@@ -8106,21 +8105,6 @@ bool parse_sql(THD *thd,
return ret_value; return ret_value;
} }
/**
Auxiliary function which marks metadata locks for all tables
on which we plan to take write lock as upgradable.
*/
static void adjust_mdl_locks_upgradability(TABLE_LIST *tables)
{
for (TABLE_LIST *tab= tables; tab; tab= tab->next_global)
{
if (tab->lock_type >= TL_WRITE_ALLOW_WRITE)
tab->mdl_upgradable= TRUE;
}
}
/** /**
@} (end of group Runtime_Environment) @} (end of group Runtime_Environment)
*/ */
...@@ -4617,7 +4617,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -4617,7 +4617,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (view_operator_func == NULL) if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE; table->required_type=FRMTYPE_TABLE;
open_and_lock_tables(thd, table); open_and_lock_tables_derived(thd, table, TRUE,
MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
thd->no_warnings_for_error= 0; thd->no_warnings_for_error= 0;
table->next_global= save_next_global; table->next_global= save_next_global;
table->next_local= save_next_local; table->next_local= save_next_local;
...@@ -5074,7 +5075,6 @@ bool mysql_restore_table(THD* thd, TABLE_LIST* table_list) ...@@ -5074,7 +5075,6 @@ bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{ {
DBUG_ENTER("mysql_repair_table"); DBUG_ENTER("mysql_repair_table");
set_all_mdl_upgradable(tables);
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"repair", TL_WRITE, 1, "repair", TL_WRITE, 1,
test(check_opt->sql_flags & TT_USEFRM), test(check_opt->sql_flags & TT_USEFRM),
...@@ -5087,7 +5087,6 @@ bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) ...@@ -5087,7 +5087,6 @@ bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{ {
DBUG_ENTER("mysql_optimize_table"); DBUG_ENTER("mysql_optimize_table");
set_all_mdl_upgradable(tables);
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt, DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"optimize", TL_WRITE, 1,0,0,0, "optimize", TL_WRITE, 1,0,0,0,
&handler::ha_optimize, 0)); &handler::ha_optimize, 0));
...@@ -6604,9 +6603,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -6604,9 +6603,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(error); DBUG_RETURN(error);
} }
table_list->mdl_upgradable= TRUE; if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ,
MYSQL_OPEN_TAKE_UPGRADABLE_MDL)))
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
table->use_all_columns(); table->use_all_columns();
mdl_lock_data= table->mdl_lock_data; mdl_lock_data= table->mdl_lock_data;
...@@ -7898,7 +7896,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, ...@@ -7898,7 +7896,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
strxmov(table_name, table->db ,".", table->table_name, NullS); strxmov(table_name, table->db ,".", table->table_name, NullS);
t= table->table= open_n_lock_single_table(thd, table, TL_READ); t= table->table= open_n_lock_single_table(thd, table, TL_READ, 0);
thd->clear_error(); // these errors shouldn't get client thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend(); protocol->prepare_for_resend();
......
...@@ -1329,10 +1329,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, ...@@ -1329,10 +1329,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
anyway. anyway.
*/ */
for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local) for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
{
tbl->lock_type= table->lock_type; tbl->lock_type= table->lock_type;
tbl->mdl_upgradable= table->mdl_upgradable;
}
/* /*
If the view is mergeable, we might want to If the view is mergeable, we might want to
INSERT/UPDATE/DELETE into tables of this view. Preserve the INSERT/UPDATE/DELETE into tables of this view. Preserve the
......
...@@ -1371,11 +1371,6 @@ struct TABLE_LIST ...@@ -1371,11 +1371,6 @@ struct TABLE_LIST
*/ */
TAKE_EXCLUSIVE_MDL TAKE_EXCLUSIVE_MDL
} open_type; } open_type;
/**
Indicates that for this table/view we need to take shared metadata
lock which should be upgradable to exclusive metadata lock.
*/
bool mdl_upgradable;
bool internal_tmp_table; bool internal_tmp_table;
/** TRUE if an alias for this table was specified in the SQL. */ /** TRUE if an alias for this table was specified in the SQL. */
bool is_alias; bool is_alias;
...@@ -1796,14 +1791,4 @@ size_t max_row_length(TABLE *table, const uchar *data); ...@@ -1796,14 +1791,4 @@ size_t max_row_length(TABLE *table, const uchar *data);
void alloc_mdl_locks(TABLE_LIST *table_list, MEM_ROOT *root); void alloc_mdl_locks(TABLE_LIST *table_list, MEM_ROOT *root);
/**
Helper function which allows to mark all elements in table list
as requiring upgradable metadata locks.
*/
inline void set_all_mdl_upgradable(TABLE_LIST *tables)
{
for (; tables; tables= tables->next_global)
tables->mdl_upgradable= TRUE;
}
#endif /* TABLE_INCLUDED */ #endif /* TABLE_INCLUDED */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment