Commit e3b3907c authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2630.4.32
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Thu 2008-06-19 16:39:58 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After-review fixes in progress.

  Ensure that metadata locking subsystem properly handles
  out-of-memory conditions. Clarified MDL interface by
  separating release of locks and removal of lock requests
  from the context.

sql/lock.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/mdl.cc:
  Ensured that metadata locking subsystem properly handles
  out-of-memory conditions.
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired 
  and we have not associated request with object respesenting 
  lock.
  
  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to 
  emphasize that it also actually removes lock requests
  from the context.
  
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/mdl.h:
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired 
  and we have not associated request with object respesenting 
  lock.
  
  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to 
  emphasize that it also actually removes lock requests
  from the context.
  
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/sql_base.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Also adjusted open_table() to ensure that it 
  releases/removes metadata locks in case of error 
  after adding/acquiring them (unless keeping these
  lock requests is required for recovering action).
sql/sql_delete.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_handler.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_show.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_table.cc:
  Renamed mdl_release_all_locks_for_name() to emphasize
  that it also actually removes lock requests from the context.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
parent b7e8b016
......@@ -965,7 +965,7 @@ bool lock_table_names(THD *thd, TABLE_LIST *table_list)
lock_table->mdl_lock_data= mdl_lock_data;
}
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
return 1;
goto end;
return 0;
end:
......
This diff is collapsed.
......@@ -44,7 +44,8 @@ enum enum_mdl_type {MDL_SHARED=0, MDL_SHARED_HIGH_PRIO,
/** States which metadata lock request can have. */
enum enum_mdl_state {MDL_PENDING=0, MDL_ACQUIRED, MDL_PENDING_UPGRADE};
enum enum_mdl_state {MDL_INITIALIZED=0, MDL_PENDING,
MDL_ACQUIRED, MDL_PENDING_UPGRADE};
/**
......@@ -152,6 +153,7 @@ void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type,
MDL_LOCK_DATA *mdl_alloc_lock(int type, const char *db, const char *name,
MEM_ROOT *root);
void mdl_add_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data);
void mdl_remove_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data);
void mdl_remove_all_locks(MDL_CONTEXT *context);
/**
......@@ -160,7 +162,7 @@ void mdl_remove_all_locks(MDL_CONTEXT *context);
inline void mdl_set_lock_type(MDL_LOCK_DATA *lock_data, enum_mdl_type lock_type)
{
DBUG_ASSERT(lock_data->state == MDL_PENDING);
DBUG_ASSERT(lock_data->state == MDL_INITIALIZED);
lock_data->type= lock_type;
}
......@@ -170,14 +172,15 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context);
bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
MDL_LOCK_DATA *lock_data);
bool mdl_try_acquire_exclusive_lock(MDL_CONTEXT *context,
MDL_LOCK_DATA *lock_data);
MDL_LOCK_DATA *lock_data,
bool *conflict);
bool mdl_acquire_global_shared_lock(MDL_CONTEXT *context);
bool mdl_wait_for_locks(MDL_CONTEXT *context);
void mdl_release_locks(MDL_CONTEXT *context);
void mdl_release_all_locks_for_name(MDL_CONTEXT *context,
MDL_LOCK_DATA *lock_data);
void mdl_release_and_remove_all_locks_for_name(MDL_CONTEXT *context,
MDL_LOCK_DATA *lock_data);
void mdl_release_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data);
void mdl_downgrade_exclusive_lock(MDL_CONTEXT *context,
MDL_LOCK_DATA *lock_data);
......
......@@ -2278,9 +2278,9 @@ void table_share_release_hook(void *share)
}
/*
A helper function that acquires an MDL lock for a table
being opened.
/**
A helper function that acquires an MDL lock for a table
being opened.
*/
static bool
......@@ -2304,7 +2304,10 @@ open_table_get_mdl_lock(THD *thd, TABLE_LIST *table_list,
*/
mdl_set_lock_type(mdl_lock_data, MDL_EXCLUSIVE);
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
{
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
return 1;
}
}
else
{
......@@ -2327,6 +2330,8 @@ open_table_get_mdl_lock(THD *thd, TABLE_LIST *table_list,
{
if (retry)
*action= OT_BACK_OFF_AND_RETRY;
else
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
return 1;
}
}
......@@ -2833,7 +2838,11 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
release_table_share(share);
err_unlock2:
pthread_mutex_unlock(&LOCK_open);
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK))
{
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
}
DBUG_RETURN(TRUE);
}
......@@ -3497,7 +3506,10 @@ recover_from_failed_open_table_attempt(THD *thd, TABLE_LIST *table,
mdl_set_lock_type(table->mdl_lock_data, MDL_EXCLUSIVE);
mdl_add_lock(&thd->mdl_context, table->mdl_lock_data);
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
{
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
return TRUE;
}
pthread_mutex_lock(&LOCK_open);
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name);
ha_create_table_from_engine(thd, table->db, table->table_name);
......@@ -3506,18 +3518,23 @@ recover_from_failed_open_table_attempt(THD *thd, TABLE_LIST *table,
thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
mdl_release_lock(&thd->mdl_context, table->mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
break;
case OT_REPAIR:
mdl_set_lock_type(table->mdl_lock_data, MDL_EXCLUSIVE);
mdl_add_lock(&thd->mdl_context, table->mdl_lock_data);
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
{
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
return TRUE;
}
pthread_mutex_lock(&LOCK_open);
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name);
pthread_mutex_unlock(&LOCK_open);
result= auto_repair_table(thd, table);
mdl_release_lock(&thd->mdl_context, table->mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
break;
default:
DBUG_ASSERT(0);
......
......@@ -1170,7 +1170,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
mdl_set_lock_type(mdl_lock_data, MDL_EXCLUSIVE);
mdl_add_lock(&thd->mdl_context, mdl_lock_data);
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
{
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
DBUG_RETURN(TRUE);
}
pthread_mutex_lock(&LOCK_open);
tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db,
table_list->table_name);
......@@ -1200,12 +1203,18 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
my_ok(thd); // This should return record count
}
if (mdl_lock_data)
{
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
}
}
else if (error)
{
if (mdl_lock_data)
{
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
}
}
DBUG_RETURN(error);
......
......@@ -150,6 +150,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
}
pthread_mutex_unlock(&LOCK_open);
mdl_release_lock(&thd->handler_mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->handler_mdl_context, mdl_lock_data);
}
else if (tables->table)
{
......
......@@ -3250,6 +3250,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table,
err:
mdl_release_lock(&thd->mdl_context, &mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, &mdl_lock_data);
thd->clear_error();
return res;
}
......
......@@ -2208,7 +2208,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
and locked and therefore have to remove several metadata lock
requests associated with them.
*/
mdl_release_all_locks_for_name(&thd->mdl_context, table->mdl_lock_data);
mdl_release_and_remove_all_locks_for_name(&thd->mdl_context,
table->mdl_lock_data);
}
}
}
......@@ -4080,13 +4081,27 @@ static bool lock_table_name_if_not_cached(THD *thd, const char *db,
const char *table_name,
MDL_LOCK_DATA **lock_data)
{
bool conflict;
if (!(*lock_data= mdl_alloc_lock(0, db, table_name, thd->mem_root)))
return TRUE;
mdl_set_lock_type(*lock_data, MDL_EXCLUSIVE);
mdl_add_lock(&thd->mdl_context, *lock_data);
if (mdl_try_acquire_exclusive_lock(&thd->mdl_context, *lock_data))
if (mdl_try_acquire_exclusive_lock(&thd->mdl_context, *lock_data,
&conflict))
{
*lock_data= 0;
/*
To simplify our life under LOCK TABLES we remove unsatisfied
lock request from the context.
*/
mdl_remove_lock(&thd->mdl_context, *lock_data);
if (!conflict)
{
/* Probably OOM. */
return TRUE;
}
else
*lock_data= 0;
}
return FALSE;
}
......@@ -4157,7 +4172,10 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
unlock:
if (target_lock_data)
{
mdl_release_lock(&thd->mdl_context, target_lock_data);
mdl_remove_lock(&thd->mdl_context, target_lock_data);
}
pthread_mutex_lock(&LOCK_lock_db);
if (!--creating_table && creating_database)
pthread_cond_signal(&COND_refresh);
......@@ -4416,7 +4434,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
mdl_set_lock_type(mdl_lock_data, MDL_EXCLUSIVE);
mdl_add_lock(&thd->mdl_context, mdl_lock_data);
if (mdl_acquire_exclusive_locks(&thd->mdl_context))
{
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
DBUG_RETURN(0);
}
pthread_mutex_lock(&LOCK_open);
if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
......@@ -4550,7 +4571,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
}
/* In case of a temporary table there will be no metadata lock. */
if (error && mdl_lock_data)
{
mdl_release_lock(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
}
DBUG_RETURN(error);
}
......@@ -5518,7 +5542,10 @@ goto binlog;
err:
if (target_lock_data)
{
mdl_release_lock(&thd->mdl_context, target_lock_data);
mdl_remove_lock(&thd->mdl_context, target_lock_data);
}
DBUG_RETURN(res);
}
......@@ -6876,7 +6903,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (new_name != table_name || new_db != db)
{
mdl_release_lock(&thd->mdl_context, target_lock_data);
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, target_lock_data);
mdl_release_and_remove_all_locks_for_name(&thd->mdl_context,
mdl_lock_data);
}
else
mdl_downgrade_exclusive_lock(&thd->mdl_context, mdl_lock_data);
......@@ -7554,7 +7583,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if ((new_name != table_name || new_db != db))
{
mdl_release_lock(&thd->mdl_context, target_lock_data);
mdl_release_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, target_lock_data);
mdl_release_and_remove_all_locks_for_name(&thd->mdl_context,
mdl_lock_data);
}
else
mdl_downgrade_exclusive_lock(&thd->mdl_context, mdl_lock_data);
......@@ -7613,7 +7644,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd->abort_on_warning= save_abort_on_warning;
}
if (target_lock_data)
{
mdl_release_lock(&thd->mdl_context, target_lock_data);
mdl_remove_lock(&thd->mdl_context, target_lock_data);
}
DBUG_RETURN(TRUE);
err_with_mdl:
......@@ -7625,8 +7659,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
thd->locked_tables_list.unlink_all_closed_tables();
if (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_remove_lock(&thd->mdl_context, target_lock_data);
}
mdl_release_and_remove_all_locks_for_name(&thd->mdl_context, mdl_lock_data);
DBUG_RETURN(TRUE);
}
/* mysql_alter_table */
......
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