summaryrefslogtreecommitdiff
path: root/sql/lock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/lock.cc')
-rw-r--r--sql/lock.cc67
1 files changed, 28 insertions, 39 deletions
diff --git a/sql/lock.cc b/sql/lock.cc
index de0f39018f7..dcee018276f 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -747,62 +747,48 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
}
-/*****************************************************************************
- Lock table based on the name.
- This is used when we need total access to a closed, not open table
-*****************************************************************************/
-
/**
- Obtain exclusive metadata locks on the list of tables.
+ Obtain an exclusive metadata lock on a schema name.
- @param thd Thread handle
- @param table_list List of tables to lock
+ @param thd Thread handle.
+ @param db The database name.
- @note This function assumes that no metadata locks were acquired
- before calling it. Also it cannot be called while holding
- LOCK_open mutex. Both these invariants are enforced by asserts
- in MDL_context::acquire_locks().
- @note Initialization of MDL_request members of TABLE_LIST elements
- is a responsibility of the caller.
+ This function cannot be called while holding LOCK_open mutex.
+ To avoid deadlocks, we do not try to obtain exclusive metadata
+ locks in LOCK TABLES mode, since in this mode there may be
+ other metadata locks already taken by the current connection,
+ and we must not wait for MDL locks while holding locks.
- @retval FALSE Success.
- @retval TRUE Failure (OOM or thread was killed).
+ @retval FALSE Success.
+ @retval TRUE Failure: we're in LOCK TABLES mode, or out of memory,
+ or this connection was killed.
*/
-bool lock_table_names(THD *thd, TABLE_LIST *table_list)
+bool lock_schema_name(THD *thd, const char *db)
{
MDL_request_list mdl_requests;
MDL_request global_request;
- TABLE_LIST *lock_table;
+ MDL_request mdl_request;
- global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
+ if (thd->locked_tables_mode)
+ {
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
+ return TRUE;
+ }
- for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
- mdl_requests.push_front(&lock_table->mdl_request);
+ global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
+ mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE);
+ mdl_requests.push_front(&mdl_request);
mdl_requests.push_front(&global_request);
if (thd->mdl_context.acquire_locks(&mdl_requests,
thd->variables.lock_wait_timeout))
- return 1;
-
- return 0;
-}
-
-
-/**
- Release all metadata locks previously obtained by lock_table_names().
-
- @param thd Thread handle.
-
- @note Cannot be called while holding LOCK_open mutex.
-*/
+ return TRUE;
-void unlock_table_names(THD *thd)
-{
- DBUG_ENTER("unlock_table_names");
- thd->mdl_context.release_transactional_locks();
- DBUG_VOID_RETURN;
+ DEBUG_SYNC(thd, "after_wait_locked_schema_name");
+ return FALSE;
}
@@ -837,6 +823,7 @@ bool lock_routine_name(THD *thd, bool is_function,
MDL_key::PROCEDURE);
MDL_request_list mdl_requests;
MDL_request global_request;
+ MDL_request schema_request;
MDL_request mdl_request;
if (thd->locked_tables_mode)
@@ -850,9 +837,11 @@ bool lock_routine_name(THD *thd, bool is_function,
DEBUG_SYNC(thd, "before_wait_locked_pname");
global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
+ schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE);
mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE);
mdl_requests.push_front(&mdl_request);
+ mdl_requests.push_front(&schema_request);
mdl_requests.push_front(&global_request);
if (thd->mdl_context.acquire_locks(&mdl_requests,