Commit 4c628c04 authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2630.4.24
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Fri 2008-06-06 14:28:58 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

  Get rid of upgradability and priority attributes of
  metadata lock requests by replacing them with two
  new types of lock requests MDL_SHARED_UPGRADABLE and
  MDL_SHARED_HIGH_PRIO correspondingly.
parent 8227a34e
...@@ -261,8 +261,7 @@ void mdl_context_merge(MDL_CONTEXT *dst, MDL_CONTEXT *src) ...@@ -261,8 +261,7 @@ void mdl_context_merge(MDL_CONTEXT *dst, MDL_CONTEXT *src)
by-pointer because of the underlying HASH implementation by-pointer because of the underlying HASH implementation
requires the key to be a contiguous buffer. requires the key to be a contiguous buffer.
The initialized lock request will have MDL_SHARED type and The initialized lock request will have MDL_SHARED type.
normal priority.
Suggested lock types: TABLE - 0 PROCEDURE - 1 FUNCTION - 2 Suggested lock types: TABLE - 0 PROCEDURE - 1 FUNCTION - 2
Note that tables and views have the same lock type, since Note that tables and views have the same lock type, since
...@@ -277,8 +276,6 @@ void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type, ...@@ -277,8 +276,6 @@ void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type,
lock_data->key= key; lock_data->key= key;
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED;
lock_data->state= MDL_PENDING; lock_data->state= MDL_PENDING;
lock_data->prio= MDL_NORMAL_PRIO;
lock_data->is_upgradable= FALSE;
#ifndef DBUG_OFF #ifndef DBUG_OFF
lock_data->ctx= 0; lock_data->ctx= 0;
lock_data->lock= 0; lock_data->lock= 0;
...@@ -298,8 +295,7 @@ void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type, ...@@ -298,8 +295,7 @@ void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type,
@param name Name of of object @param name Name of of object
@param root MEM_ROOT on which object should be allocated @param root MEM_ROOT on which object should be allocated
@note The allocated lock request will have MDL_SHARED type and @note The allocated lock request will have MDL_SHARED type.
normal priority.
@retval 0 Error @retval 0 Error
@retval non-0 Pointer to an object representing a lock request @retval non-0 Pointer to an object representing a lock request
...@@ -364,8 +360,7 @@ void mdl_add_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data) ...@@ -364,8 +360,7 @@ void mdl_add_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data)
we release all the locks acquired so-far but do not free them, since we release all the locks acquired so-far but do not free them, since
we know that the respective lock requests will be used again. we know that the respective lock requests will be used again.
Also resets lock requests back to their initial state (i.e. Also resets lock requests back to their initial state (i.e. MDL_SHARED).
sets type and priority to MDL_SHARED and MDL_NORMAL_PRIO).
@param context Context to be cleared. @param context Context to be cleared.
*/ */
...@@ -378,8 +373,6 @@ void mdl_remove_all_locks(MDL_CONTEXT *context) ...@@ -378,8 +373,6 @@ void mdl_remove_all_locks(MDL_CONTEXT *context)
{ {
/* Reset lock request back to its initial state. */ /* Reset lock request back to its initial state. */
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED;
lock_data->prio= MDL_NORMAL_PRIO;
lock_data->is_upgradable= FALSE;
#ifndef DBUG_OFF #ifndef DBUG_OFF
lock_data->ctx= 0; lock_data->ctx= 0;
#endif #endif
...@@ -408,6 +401,16 @@ static void release_lock_object(MDL_LOCK *lock) ...@@ -408,6 +401,16 @@ static void release_lock_object(MDL_LOCK *lock)
} }
/**
Helper functions which simplifies writing various checks and asserts.
*/
static bool is_shared(MDL_LOCK_DATA *lock_data)
{
return (lock_data->type < MDL_EXCLUSIVE);
}
/** /**
Check if request for the lock on particular object can be satisfied given Check if request for the lock on particular object can be satisfied given
current state of the global metadata lock. current state of the global metadata lock.
...@@ -430,7 +433,7 @@ static void release_lock_object(MDL_LOCK *lock) ...@@ -430,7 +433,7 @@ static void release_lock_object(MDL_LOCK *lock)
Type of request | Correspond. | Type of request | Correspond. |
for indiv. lock | global lock | Active-S Pending-S Active-IS(**) Active-IX for indiv. lock | global lock | Active-S Pending-S Active-IS(**) Active-IX
----------------+-------------+-------------------------------------------- ----------------+-------------+--------------------------------------------
S | IS | + + + + S, high-prio S | IS | + + + +
upgradable S | IX | - - + + upgradable S | IX | - - + +
X | IX | - - + + X | IX | - - + +
S upgraded to X | IX (*) | 0 + + + S upgraded to X | IX (*) | 0 + + +
...@@ -451,8 +454,11 @@ static bool can_grant_global_lock(MDL_LOCK_DATA *lock_data) ...@@ -451,8 +454,11 @@ static bool can_grant_global_lock(MDL_LOCK_DATA *lock_data)
switch (lock_data->type) switch (lock_data->type)
{ {
case MDL_SHARED: case MDL_SHARED:
if (lock_data->is_upgradable && case MDL_SHARED_HIGH_PRIO:
(global_lock.active_shared || global_lock.waiting_shared)) return TRUE;
break;
case MDL_SHARED_UPGRADABLE:
if (global_lock.active_shared || global_lock.waiting_shared)
{ {
/* /*
We are going to obtain intention exclusive global lock and We are going to obtain intention exclusive global lock and
...@@ -512,7 +518,7 @@ static bool can_grant_global_lock(MDL_LOCK_DATA *lock_data) ...@@ -512,7 +518,7 @@ static bool can_grant_global_lock(MDL_LOCK_DATA *lock_data)
----------------+--------------------------------------------------------- ----------------+---------------------------------------------------------
Current request | Active-S Pending-X Active-X Act-S-pend-upgrade-to-X Current request | Active-S Pending-X Active-X Act-S-pend-upgrade-to-X
----------------+--------------------------------------------------------- ----------------+---------------------------------------------------------
S | + - - (*) - S, upgradable S | + - - (*) -
High-prio S | + + - + High-prio S | + + - +
X | - + - - X | - + - -
S upgraded to X | - (**) + 0 0 S upgraded to X | - (**) + 0 0
...@@ -532,8 +538,10 @@ static bool can_grant_lock(MDL_LOCK *lock, MDL_LOCK_DATA *lock_data) ...@@ -532,8 +538,10 @@ static bool can_grant_lock(MDL_LOCK *lock, MDL_LOCK_DATA *lock_data)
switch (lock_data->type) switch (lock_data->type)
{ {
case MDL_SHARED: case MDL_SHARED:
case MDL_SHARED_UPGRADABLE:
case MDL_SHARED_HIGH_PRIO:
if ((lock->active_exclusive.is_empty() && if ((lock->active_exclusive.is_empty() &&
(lock_data->prio == MDL_HIGH_PRIO || (lock_data->type == MDL_SHARED_HIGH_PRIO ||
lock->waiting_exclusive.is_empty() && lock->waiting_exclusive.is_empty() &&
lock->active_shared_waiting_upgrade.is_empty())) || lock->active_shared_waiting_upgrade.is_empty())) ||
(!lock->active_exclusive.is_empty() && (!lock->active_exclusive.is_empty() &&
...@@ -619,11 +627,12 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry) ...@@ -619,11 +627,12 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry)
MDL_LOCK *lock; MDL_LOCK *lock;
*retry= FALSE; *retry= FALSE;
DBUG_ASSERT(lock_data->type == MDL_SHARED && lock_data->state == MDL_PENDING); DBUG_ASSERT(is_shared(lock_data) && lock_data->state == MDL_PENDING);
safe_mutex_assert_not_owner(&LOCK_open); safe_mutex_assert_not_owner(&LOCK_open);
if (lock_data->ctx->has_global_shared_lock && lock_data->is_upgradable) if (lock_data->ctx->has_global_shared_lock &&
lock_data->type == MDL_SHARED_UPGRADABLE)
{ {
my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0));
return TRUE; return TRUE;
...@@ -652,7 +661,7 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry) ...@@ -652,7 +661,7 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry)
my_hash_insert(&mdl_locks, (uchar*)lock); my_hash_insert(&mdl_locks, (uchar*)lock);
lock_data->state= MDL_ACQUIRED; lock_data->state= MDL_ACQUIRED;
lock_data->lock= lock; lock_data->lock= lock;
if (lock_data->is_upgradable) if (lock_data->type == MDL_SHARED_UPGRADABLE)
global_lock.active_intention_exclusive++; global_lock.active_intention_exclusive++;
} }
else else
...@@ -663,7 +672,7 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry) ...@@ -663,7 +672,7 @@ bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry)
lock->lock_data_count++; lock->lock_data_count++;
lock_data->state= MDL_ACQUIRED; lock_data->state= MDL_ACQUIRED;
lock_data->lock= lock; lock_data->lock= lock;
if (lock_data->is_upgradable) if (lock_data->type == MDL_SHARED_UPGRADABLE)
global_lock.active_intention_exclusive++; global_lock.active_intention_exclusive++;
} }
else else
...@@ -690,8 +699,7 @@ static void release_lock(MDL_LOCK_DATA *lock_data); ...@@ -690,8 +699,7 @@ static void release_lock(MDL_LOCK_DATA *lock_data);
The context may not have other lock requests. The context may not have other lock requests.
@note In case of failure (for example, if our thread was killed) @note In case of failure (for example, if our thread was killed)
resets lock requests back to their initial state (MDL_SHARED resets lock requests back to their initial state (MDL_SHARED)
and MDL_NORMAL_PRIO).
@retval FALSE Success @retval FALSE Success
@retval TRUE Failure @retval TRUE Failure
...@@ -804,8 +812,6 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context) ...@@ -804,8 +812,6 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
release_lock(lock_data); release_lock(lock_data);
/* Return lock request to its initial state. */ /* Return lock request to its initial state. */
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED;
lock_data->prio= MDL_NORMAL_PRIO;
lock_data->is_upgradable= FALSE;
context->locks.remove(lock_data); context->locks.remove(lock_data);
} }
/* Pending requests for shared locks can be satisfied now. */ /* Pending requests for shared locks can be satisfied now. */
...@@ -868,7 +874,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context, ...@@ -868,7 +874,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
if (lock_data->type == MDL_EXCLUSIVE) if (lock_data->type == MDL_EXCLUSIVE)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
DBUG_ASSERT(lock_data->is_upgradable); DBUG_ASSERT(lock_data->type == MDL_SHARED_UPGRADABLE);
lock= lock_data->lock; lock= lock_data->lock;
...@@ -929,7 +935,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context, ...@@ -929,7 +935,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
if (thd->killed) if (thd->killed)
{ {
lock_data->state= MDL_ACQUIRED; lock_data->state= MDL_ACQUIRED;
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED_UPGRADABLE;
lock->active_shared_waiting_upgrade.remove(lock_data); lock->active_shared_waiting_upgrade.remove(lock_data);
lock->active_shared.push_front(lock_data); lock->active_shared.push_front(lock_data);
/* Pending requests for shared locks can be satisfied now. */ /* Pending requests for shared locks can be satisfied now. */
...@@ -1017,8 +1023,7 @@ bool mdl_try_acquire_exclusive_lock(MDL_CONTEXT *context, ...@@ -1017,8 +1023,7 @@ bool mdl_try_acquire_exclusive_lock(MDL_CONTEXT *context,
Acquire global shared metadata lock. Acquire global shared metadata lock.
Holding this lock will block all requests for exclusive locks Holding this lock will block all requests for exclusive locks
and shared locks which can be potentially upgraded to exclusive and shared locks which can be potentially upgraded to exclusive.
(see MDL_LOCK_DATA::is_upgradable).
@param context Current metadata locking context. @param context Current metadata locking context.
...@@ -1108,7 +1113,7 @@ bool mdl_wait_for_locks(MDL_CONTEXT *context) ...@@ -1108,7 +1113,7 @@ bool mdl_wait_for_locks(MDL_CONTEXT *context)
/* /*
To avoid starvation we don't wait if we have pending MDL_EXCLUSIVE lock. To avoid starvation we don't wait if we have pending MDL_EXCLUSIVE lock.
*/ */
if (lock_data->type == MDL_SHARED && if (is_shared(lock_data) &&
(lock= (MDL_LOCK *)my_hash_search(&mdl_locks, (uchar*)lock_data->key, (lock= (MDL_LOCK *)my_hash_search(&mdl_locks, (uchar*)lock_data->key,
lock_data->key_length)) && lock_data->key_length)) &&
!can_grant_lock(lock, lock_data)) !can_grant_lock(lock, lock_data))
...@@ -1149,19 +1154,21 @@ static void release_lock(MDL_LOCK_DATA *lock_data) ...@@ -1149,19 +1154,21 @@ static void release_lock(MDL_LOCK_DATA *lock_data)
if (lock->cached_object) if (lock->cached_object)
(*lock->cached_object_release_hook)(lock->cached_object); (*lock->cached_object_release_hook)(lock->cached_object);
release_lock_object(lock); release_lock_object(lock);
if (lock_data->type == MDL_EXCLUSIVE && lock_data->state == MDL_ACQUIRED || if (lock_data->state == MDL_ACQUIRED &&
lock_data->type == MDL_SHARED && lock_data->state == MDL_ACQUIRED && (lock_data->type == MDL_EXCLUSIVE ||
lock_data->is_upgradable) lock_data->type == MDL_SHARED_UPGRADABLE))
global_lock.active_intention_exclusive--; global_lock.active_intention_exclusive--;
} }
else else
{ {
switch (lock_data->type) switch (lock_data->type)
{ {
case MDL_SHARED_UPGRADABLE:
global_lock.active_intention_exclusive--;
/* Fallthrough. */
case MDL_SHARED: case MDL_SHARED:
case MDL_SHARED_HIGH_PRIO:
lock->active_shared.remove(lock_data); lock->active_shared.remove(lock_data);
if (lock_data->is_upgradable)
global_lock.active_intention_exclusive--;
break; break;
case MDL_EXCLUSIVE: case MDL_EXCLUSIVE:
if (lock_data->state == MDL_PENDING) if (lock_data->state == MDL_PENDING)
...@@ -1213,7 +1220,7 @@ void mdl_release_locks(MDL_CONTEXT *context) ...@@ -1213,7 +1220,7 @@ void mdl_release_locks(MDL_CONTEXT *context)
lists. Allows us to avoid problems in open_tables() in case of lists. Allows us to avoid problems in open_tables() in case of
back-off back-off
*/ */
if (!(lock_data->type == MDL_SHARED && lock_data->state == MDL_PENDING)) if (!(is_shared(lock_data) && lock_data->state == MDL_PENDING))
{ {
release_lock(lock_data); release_lock(lock_data);
lock_data->state= MDL_PENDING; lock_data->state= MDL_PENDING;
...@@ -1224,7 +1231,7 @@ void mdl_release_locks(MDL_CONTEXT *context) ...@@ -1224,7 +1231,7 @@ void mdl_release_locks(MDL_CONTEXT *context)
/* /*
We will return lock request to its initial state only in We will return lock request to its initial state only in
mdl_remove_all_locks() since we need to know type of lock mdl_remove_all_locks() since we need to know type of lock
request and if it is upgradable in mdl_wait_for_locks(). request in mdl_wait_for_locks().
*/ */
} }
/* Inefficient but will do for a while */ /* Inefficient but will do for a while */
...@@ -1242,7 +1249,7 @@ void mdl_release_locks(MDL_CONTEXT *context) ...@@ -1242,7 +1249,7 @@ void mdl_release_locks(MDL_CONTEXT *context)
@param lock_data Lock to be released @param lock_data Lock to be released
@note Resets lock request for lock released back to its initial state @note Resets lock request for lock released back to its initial state
(i.e.sets type and priority to MDL_SHARED and MDL_NORMAL_PRIO). (i.e. sets type to MDL_SHARED).
*/ */
void mdl_release_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data) void mdl_release_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data)
...@@ -1258,8 +1265,6 @@ void mdl_release_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data) ...@@ -1258,8 +1265,6 @@ void mdl_release_lock(MDL_CONTEXT *context, MDL_LOCK_DATA *lock_data)
lock_data->state= MDL_PENDING; lock_data->state= MDL_PENDING;
/* Return lock request to its initial state. */ /* Return lock request to its initial state. */
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED;
lock_data->prio= MDL_NORMAL_PRIO;
lock_data->is_upgradable= FALSE;
context->locks.remove(lock_data); context->locks.remove(lock_data);
pthread_cond_broadcast(&COND_mdl); pthread_cond_broadcast(&COND_mdl);
pthread_mutex_unlock(&LOCK_mdl); pthread_mutex_unlock(&LOCK_mdl);
...@@ -1318,16 +1323,14 @@ void mdl_downgrade_exclusive_lock(MDL_CONTEXT *context, ...@@ -1318,16 +1323,14 @@ void mdl_downgrade_exclusive_lock(MDL_CONTEXT *context,
DBUG_ASSERT(lock_data->state == MDL_ACQUIRED); DBUG_ASSERT(lock_data->state == MDL_ACQUIRED);
if (lock_data->type == MDL_SHARED) if (is_shared(lock_data))
return; return;
lock= lock_data->lock; lock= lock_data->lock;
pthread_mutex_lock(&LOCK_mdl); pthread_mutex_lock(&LOCK_mdl);
if (!lock_data->is_upgradable)
global_lock.active_intention_exclusive--;
lock->active_exclusive.remove(lock_data); lock->active_exclusive.remove(lock_data);
lock_data->type= MDL_SHARED; lock_data->type= MDL_SHARED_UPGRADABLE;
lock->active_shared.push_front(lock_data); lock->active_shared.push_front(lock_data);
pthread_cond_broadcast(&COND_mdl); pthread_cond_broadcast(&COND_mdl);
pthread_mutex_unlock(&LOCK_mdl); pthread_mutex_unlock(&LOCK_mdl);
...@@ -1379,10 +1382,11 @@ bool mdl_is_exclusive_lock_owner(MDL_CONTEXT *context, int type, ...@@ -1379,10 +1382,11 @@ bool mdl_is_exclusive_lock_owner(MDL_CONTEXT *context, int type,
while ((lock_data= it++) && while ((lock_data= it++) &&
(lock_data->key_length != key_length || (lock_data->key_length != key_length ||
memcmp(lock_data->key, key, key_length))) memcmp(lock_data->key, key, key_length) ||
!(lock_data->type == MDL_EXCLUSIVE &&
lock_data->state == MDL_ACQUIRED)))
continue; continue;
return (lock_data && lock_data->type == MDL_EXCLUSIVE && return lock_data;
lock_data->state == MDL_ACQUIRED);
} }
...@@ -1432,8 +1436,7 @@ bool mdl_has_pending_conflicting_lock(MDL_LOCK_DATA *lock_data) ...@@ -1432,8 +1436,7 @@ bool mdl_has_pending_conflicting_lock(MDL_LOCK_DATA *lock_data)
{ {
bool result; bool result;
DBUG_ASSERT(lock_data->type == MDL_SHARED && DBUG_ASSERT(is_shared(lock_data) && lock_data->state == MDL_ACQUIRED);
lock_data->state == MDL_ACQUIRED);
safe_mutex_assert_not_owner(&LOCK_open); safe_mutex_assert_not_owner(&LOCK_open);
pthread_mutex_lock(&LOCK_mdl); pthread_mutex_lock(&LOCK_mdl);
......
...@@ -26,24 +26,25 @@ struct MDL_LOCK_DATA; ...@@ -26,24 +26,25 @@ struct MDL_LOCK_DATA;
struct MDL_LOCK; struct MDL_LOCK;
struct MDL_CONTEXT; struct MDL_CONTEXT;
/** Type of metadata lock request. */ /**
Type of metadata lock request.
enum enum_mdl_type {MDL_SHARED=0, MDL_EXCLUSIVE};
- High-priority shared locks differ from ordinary shared locks by
that they ignore pending requests for exclusive locks.
- Upgradable shared locks can be later upgraded to exclusive
(because of that their acquisition involves implicit
acquisition of global intention-exclusive lock).
/** States which metadata lock request can have. */ @see Comments for can_grant_lock() and can_grant_global_lock() for details.
*/
enum enum_mdl_state {MDL_PENDING=0, MDL_ACQUIRED, MDL_PENDING_UPGRADE}; enum enum_mdl_type {MDL_SHARED=0, MDL_SHARED_HIGH_PRIO,
MDL_SHARED_UPGRADABLE, MDL_EXCLUSIVE};
/** /** States which metadata lock request can have. */
Priority of metadata lock requests. High priority attribute is
applicable only to requests for shared locks and indicates that
such request should ignore pending requests for exclusive locks
and for upgrading of shared locks to exclusive.
*/
enum enum_mdl_prio {MDL_NORMAL_PRIO=0, MDL_HIGH_PRIO}; enum enum_mdl_state {MDL_PENDING=0, MDL_ACQUIRED, MDL_PENDING_UPGRADE};
/** /**
...@@ -60,13 +61,6 @@ struct MDL_LOCK_DATA ...@@ -60,13 +61,6 @@ struct MDL_LOCK_DATA
uint key_length; uint key_length;
enum enum_mdl_type type; enum enum_mdl_type type;
enum enum_mdl_state state; enum enum_mdl_state state;
enum enum_mdl_prio prio;
/**
TRUE -- if shared lock corresponding to this lock request at some
point might be upgraded to an exclusive lock and therefore conflicts
with global shared lock, FALSE -- otherwise.
*/
bool is_upgradable;
private: private:
/** /**
...@@ -170,28 +164,6 @@ inline void mdl_set_lock_type(MDL_LOCK_DATA *lock_data, enum_mdl_type lock_type) ...@@ -170,28 +164,6 @@ inline void mdl_set_lock_type(MDL_LOCK_DATA *lock_data, enum_mdl_type lock_type)
lock_data->type= lock_type; lock_data->type= lock_type;
} }
/**
Set priority for lock request. High priority can be only set
for shared locks.
*/
inline void mdl_set_lock_priority(MDL_LOCK_DATA *lock_data, enum_mdl_prio prio)
{
DBUG_ASSERT(lock_data->type == MDL_SHARED && lock_data->state == MDL_PENDING);
lock_data->prio= prio;
}
/**
Mark request for shared lock as upgradable. Can be only applied
to pending locks.
*/
inline void mdl_set_upgradable(MDL_LOCK_DATA *lock_data)
{
DBUG_ASSERT(lock_data->type == MDL_SHARED && lock_data->state == MDL_PENDING);
lock_data->is_upgradable= TRUE;
}
bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry); bool mdl_acquire_shared_lock(MDL_LOCK_DATA *lock_data, bool *retry);
bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context); bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context);
bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context, bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
......
...@@ -2822,11 +2822,19 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, ...@@ -2822,11 +2822,19 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{ {
bool retry; bool retry;
/*
There is no MDL_SHARED_UPGRADABLE_HIGH_PRIO type of metadata lock so we
want to be sure that caller doesn't pass us both flags simultaneously.
*/
DBUG_ASSERT(!(flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) ||
!(flags & MYSQL_LOCK_IGNORE_FLUSH));
if (flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL && if (flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL &&
table_list->lock_type >= TL_WRITE_ALLOW_WRITE) table_list->lock_type >= TL_WRITE_ALLOW_WRITE)
mdl_set_upgradable(mdl_lock_data); mdl_set_lock_type(mdl_lock_data, MDL_SHARED_UPGRADABLE);
mdl_set_lock_priority(mdl_lock_data, (flags & MYSQL_LOCK_IGNORE_FLUSH) ? if (flags & MYSQL_LOCK_IGNORE_FLUSH)
MDL_HIGH_PRIO : MDL_NORMAL_PRIO); mdl_set_lock_type(mdl_lock_data, MDL_SHARED_HIGH_PRIO);
if (mdl_acquire_shared_lock(mdl_lock_data, &retry)) if (mdl_acquire_shared_lock(mdl_lock_data, &retry))
{ {
if (retry) if (retry)
......
...@@ -3136,7 +3136,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table, ...@@ -3136,7 +3136,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table,
mdl_init_lock(&mdl_lock_data, mdlkey, 0, db_name->str, table_name->str); mdl_init_lock(&mdl_lock_data, mdlkey, 0, db_name->str, table_name->str);
table_list.mdl_lock_data= &mdl_lock_data; table_list.mdl_lock_data= &mdl_lock_data;
mdl_add_lock(&thd->mdl_context, &mdl_lock_data); mdl_add_lock(&thd->mdl_context, &mdl_lock_data);
mdl_set_lock_priority(&mdl_lock_data, MDL_HIGH_PRIO); mdl_set_lock_type(&mdl_lock_data, MDL_SHARED_HIGH_PRIO);
/* /*
TODO: investigate if in this particular situation we can get by TODO: investigate if in this particular situation we can get by
......
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