mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
MDEV-6089 - MySQL WL#7305 "Improve MDL scalability by using lock-free hash"
Simplified MDL_object_lock and MDL_scoped_lock dichotomy so that they can be stored in LF_HASH. This was done by moving out their differences to a MDL_lock_strategy structure which is referenced from the MDL_lock object by pointer.
This commit is contained in:
parent
f475a7f949
commit
f5bd1d0126
1 changed files with 150 additions and 196 deletions
346
sql/mdl.cc
346
sql/mdl.cc
|
@ -327,6 +327,101 @@ public:
|
||||||
|
|
||||||
typedef Ticket_list::List::Iterator Ticket_iterator;
|
typedef Ticket_list::List::Iterator Ticket_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper struct which defines how different types of locks are handled
|
||||||
|
for a specific MDL_lock. In practice we use only two strategies: "scoped"
|
||||||
|
lock strategy for locks in GLOBAL, COMMIT and SCHEMA namespaces and
|
||||||
|
"object" lock strategy for all other namespaces.
|
||||||
|
*/
|
||||||
|
struct MDL_lock_strategy
|
||||||
|
{
|
||||||
|
virtual const bitmap_t *incompatible_granted_types_bitmap() const = 0;
|
||||||
|
virtual const bitmap_t *incompatible_waiting_types_bitmap() const = 0;
|
||||||
|
virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
|
||||||
|
virtual bool conflicting_locks(const MDL_ticket *ticket) const = 0;
|
||||||
|
virtual bitmap_t hog_lock_types_bitmap() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of the scoped metadata lock. The only locking modes
|
||||||
|
which are supported at the moment are SHARED and INTENTION EXCLUSIVE
|
||||||
|
and EXCLUSIVE
|
||||||
|
*/
|
||||||
|
struct MDL_scoped_lock : public MDL_lock_strategy
|
||||||
|
{
|
||||||
|
virtual const bitmap_t *incompatible_granted_types_bitmap() const
|
||||||
|
{ return m_granted_incompatible; }
|
||||||
|
virtual const bitmap_t *incompatible_waiting_types_bitmap() const
|
||||||
|
{ return m_waiting_incompatible; }
|
||||||
|
virtual bool needs_notification(const MDL_ticket *ticket) const
|
||||||
|
{ return (ticket->get_type() == MDL_SHARED); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notify threads holding scoped IX locks which conflict with a pending
|
||||||
|
S lock.
|
||||||
|
|
||||||
|
Thread which holds global IX lock can be a handler thread for
|
||||||
|
insert delayed. We need to kill such threads in order to get
|
||||||
|
global shared lock. We do this my calling code outside of MDL.
|
||||||
|
*/
|
||||||
|
virtual bool conflicting_locks(const MDL_ticket *ticket) const
|
||||||
|
{ return ticket->get_type() == MDL_INTENTION_EXCLUSIVE; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
In scoped locks, only IX lock request would starve because of X/S. But that
|
||||||
|
is practically very rare case. So just return 0 from this function.
|
||||||
|
*/
|
||||||
|
virtual bitmap_t hog_lock_types_bitmap() const
|
||||||
|
{ return 0; }
|
||||||
|
private:
|
||||||
|
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
|
||||||
|
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
An implementation of a per-object lock. Supports SHARED, SHARED_UPGRADABLE,
|
||||||
|
SHARED HIGH PRIORITY and EXCLUSIVE locks.
|
||||||
|
*/
|
||||||
|
struct MDL_object_lock : public MDL_lock_strategy
|
||||||
|
{
|
||||||
|
virtual const bitmap_t *incompatible_granted_types_bitmap() const
|
||||||
|
{ return m_granted_incompatible; }
|
||||||
|
virtual const bitmap_t *incompatible_waiting_types_bitmap() const
|
||||||
|
{ return m_waiting_incompatible; }
|
||||||
|
virtual bool needs_notification(const MDL_ticket *ticket) const
|
||||||
|
{ return (ticket->get_type() >= MDL_SHARED_NO_WRITE); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notify threads holding a shared metadata locks on object which
|
||||||
|
conflict with a pending X, SNW or SNRW lock.
|
||||||
|
|
||||||
|
If thread which holds conflicting lock is waiting on table-level
|
||||||
|
lock or some other non-MDL resource we might need to wake it up
|
||||||
|
by calling code outside of MDL.
|
||||||
|
*/
|
||||||
|
virtual bool conflicting_locks(const MDL_ticket *ticket) const
|
||||||
|
{ return ticket->get_type() < MDL_SHARED_UPGRADABLE; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
To prevent starvation, these lock types that are only granted
|
||||||
|
max_write_lock_count times in a row while other lock types are
|
||||||
|
waiting.
|
||||||
|
*/
|
||||||
|
virtual bitmap_t hog_lock_types_bitmap() const
|
||||||
|
{
|
||||||
|
return (MDL_BIT(MDL_SHARED_NO_WRITE) |
|
||||||
|
MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
|
||||||
|
MDL_BIT(MDL_EXCLUSIVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
|
||||||
|
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** The key of the object (data) being protected. */
|
/** The key of the object (data) being protected. */
|
||||||
MDL_key key;
|
MDL_key key;
|
||||||
|
@ -370,16 +465,16 @@ public:
|
||||||
return (m_granted.is_empty() && m_waiting.is_empty());
|
return (m_granted.is_empty() && m_waiting.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const bitmap_t *incompatible_granted_types_bitmap() const = 0;
|
const bitmap_t *incompatible_granted_types_bitmap() const
|
||||||
virtual const bitmap_t *incompatible_waiting_types_bitmap() const = 0;
|
{ return m_strategy->incompatible_granted_types_bitmap(); }
|
||||||
|
const bitmap_t *incompatible_waiting_types_bitmap() const
|
||||||
|
{ return m_strategy->incompatible_waiting_types_bitmap(); }
|
||||||
|
|
||||||
bool has_pending_conflicting_lock(enum_mdl_type type);
|
bool has_pending_conflicting_lock(enum_mdl_type type);
|
||||||
|
|
||||||
bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
|
bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
|
||||||
bool ignore_lock_priority) const;
|
bool ignore_lock_priority) const;
|
||||||
|
|
||||||
inline static MDL_lock *create(const MDL_key *key);
|
|
||||||
|
|
||||||
inline unsigned long get_lock_owner() const;
|
inline unsigned long get_lock_owner() const;
|
||||||
|
|
||||||
void reschedule_waiters();
|
void reschedule_waiters();
|
||||||
|
@ -389,10 +484,28 @@ public:
|
||||||
bool visit_subgraph(MDL_ticket *waiting_ticket,
|
bool visit_subgraph(MDL_ticket *waiting_ticket,
|
||||||
MDL_wait_for_graph_visitor *gvisitor);
|
MDL_wait_for_graph_visitor *gvisitor);
|
||||||
|
|
||||||
virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
|
bool needs_notification(const MDL_ticket *ticket) const
|
||||||
virtual void notify_conflicting_locks(MDL_context *ctx) = 0;
|
{ return m_strategy->needs_notification(ticket); }
|
||||||
|
void notify_conflicting_locks(MDL_context *ctx)
|
||||||
|
{
|
||||||
|
Ticket_iterator it(m_granted);
|
||||||
|
MDL_ticket *conflicting_ticket;
|
||||||
|
while ((conflicting_ticket= it++))
|
||||||
|
{
|
||||||
|
if (conflicting_ticket->get_ctx() != ctx &&
|
||||||
|
m_strategy->conflicting_locks(conflicting_ticket))
|
||||||
|
{
|
||||||
|
MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
|
||||||
|
|
||||||
virtual bitmap_t hog_lock_types_bitmap() const = 0;
|
ctx->get_owner()->
|
||||||
|
notify_shared_lock(conflicting_ctx->get_owner(),
|
||||||
|
conflicting_ctx->get_needs_thr_lock_abort());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_t hog_lock_types_bitmap() const
|
||||||
|
{ return m_strategy->hog_lock_types_bitmap(); }
|
||||||
|
|
||||||
/** List of granted tickets for this lock. */
|
/** List of granted tickets for this lock. */
|
||||||
Ticket_list m_granted;
|
Ticket_list m_granted;
|
||||||
|
@ -413,106 +526,37 @@ public:
|
||||||
m_state(0)
|
m_state(0)
|
||||||
{
|
{
|
||||||
mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock);
|
mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock);
|
||||||
|
switch (key_arg->mdl_namespace())
|
||||||
|
{
|
||||||
|
case MDL_key::GLOBAL:
|
||||||
|
case MDL_key::SCHEMA:
|
||||||
|
case MDL_key::COMMIT:
|
||||||
|
m_strategy= &m_scoped_lock_strategy;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_strategy= &m_object_lock_strategy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~MDL_lock()
|
virtual ~MDL_lock()
|
||||||
{
|
{
|
||||||
mysql_prlock_destroy(&m_rwlock);
|
mysql_prlock_destroy(&m_rwlock);
|
||||||
}
|
}
|
||||||
inline static void destroy(MDL_lock *lock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Lock state: first 31 bits are reference counter, 32-nd bit is deleted flag.
|
Lock state: first 31 bits are reference counter, 32-nd bit is deleted flag.
|
||||||
*/
|
*/
|
||||||
static const int32 DELETED= 1 << 31;
|
static const int32 DELETED= 1 << 31;
|
||||||
int32 m_state;
|
int32 m_state;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
An implementation of the scoped metadata lock. The only locking modes
|
|
||||||
which are supported at the moment are SHARED and INTENTION EXCLUSIVE
|
|
||||||
and EXCLUSIVE
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MDL_scoped_lock : public MDL_lock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MDL_scoped_lock(const MDL_key *key_arg)
|
|
||||||
: MDL_lock(key_arg)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual const bitmap_t *incompatible_granted_types_bitmap() const
|
|
||||||
{
|
|
||||||
return m_granted_incompatible;
|
|
||||||
}
|
|
||||||
virtual const bitmap_t *incompatible_waiting_types_bitmap() const
|
|
||||||
{
|
|
||||||
return m_waiting_incompatible;
|
|
||||||
}
|
|
||||||
virtual bool needs_notification(const MDL_ticket *ticket) const
|
|
||||||
{
|
|
||||||
return (ticket->get_type() == MDL_SHARED);
|
|
||||||
}
|
|
||||||
virtual void notify_conflicting_locks(MDL_context *ctx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
In scoped locks, only IX lock request would starve because of X/S. But that
|
|
||||||
is practically very rare case. So just return 0 from this function.
|
|
||||||
*/
|
|
||||||
virtual bitmap_t hog_lock_types_bitmap() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
|
const MDL_lock_strategy *m_strategy;
|
||||||
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
|
static const MDL_scoped_lock m_scoped_lock_strategy;
|
||||||
|
static const MDL_object_lock m_object_lock_strategy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
const MDL_lock::MDL_scoped_lock MDL_lock::m_scoped_lock_strategy;
|
||||||
An implementation of a per-object lock. Supports SHARED, SHARED_UPGRADABLE,
|
const MDL_lock::MDL_object_lock MDL_lock::m_object_lock_strategy;
|
||||||
SHARED HIGH PRIORITY and EXCLUSIVE locks.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class MDL_object_lock : public MDL_lock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MDL_object_lock(const MDL_key *key_arg)
|
|
||||||
: MDL_lock(key_arg)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual const bitmap_t *incompatible_granted_types_bitmap() const
|
|
||||||
{
|
|
||||||
return m_granted_incompatible;
|
|
||||||
}
|
|
||||||
virtual const bitmap_t *incompatible_waiting_types_bitmap() const
|
|
||||||
{
|
|
||||||
return m_waiting_incompatible;
|
|
||||||
}
|
|
||||||
virtual bool needs_notification(const MDL_ticket *ticket) const
|
|
||||||
{
|
|
||||||
return (ticket->get_type() >= MDL_SHARED_NO_WRITE);
|
|
||||||
}
|
|
||||||
virtual void notify_conflicting_locks(MDL_context *ctx);
|
|
||||||
|
|
||||||
/*
|
|
||||||
To prevent starvation, these lock types that are only granted
|
|
||||||
max_write_lock_count times in a row while other lock types are
|
|
||||||
waiting.
|
|
||||||
*/
|
|
||||||
virtual bitmap_t hog_lock_types_bitmap() const
|
|
||||||
{
|
|
||||||
return (MDL_BIT(MDL_SHARED_NO_WRITE) |
|
|
||||||
MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
|
|
||||||
MDL_BIT(MDL_EXCLUSIVE));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
|
|
||||||
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static MDL_map mdl_locks;
|
static MDL_map mdl_locks;
|
||||||
|
@ -627,7 +671,7 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg)
|
||||||
mysql_prlock_unlock(&lock->m_rwlock);
|
mysql_prlock_unlock(&lock->m_rwlock);
|
||||||
|
|
||||||
if (unlikely(old_state == MDL_lock::DELETED + 1))
|
if (unlikely(old_state == MDL_lock::DELETED + 1))
|
||||||
MDL_lock::destroy(lock);
|
delete lock;
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
delete_dynamic(&locks);
|
delete_dynamic(&locks);
|
||||||
|
@ -650,8 +694,8 @@ void MDL_map::init()
|
||||||
MDL_key global_lock_key(MDL_key::GLOBAL, "", "");
|
MDL_key global_lock_key(MDL_key::GLOBAL, "", "");
|
||||||
MDL_key commit_lock_key(MDL_key::COMMIT, "", "");
|
MDL_key commit_lock_key(MDL_key::COMMIT, "", "");
|
||||||
|
|
||||||
m_global_lock= MDL_lock::create(&global_lock_key);
|
m_global_lock= new (std::nothrow) MDL_lock(&global_lock_key);
|
||||||
m_commit_lock= MDL_lock::create(&commit_lock_key);
|
m_commit_lock= new (std::nothrow) MDL_lock(&commit_lock_key);
|
||||||
|
|
||||||
mysql_mutex_init(key_MDL_map_mutex, &m_mutex, NULL);
|
mysql_mutex_init(key_MDL_map_mutex, &m_mutex, NULL);
|
||||||
my_hash_init2(&m_locks, 0, &my_charset_bin, 16 /* FIXME */, 0, 0,
|
my_hash_init2(&m_locks, 0, &my_charset_bin, 16 /* FIXME */, 0, 0,
|
||||||
|
@ -666,8 +710,8 @@ void MDL_map::init()
|
||||||
|
|
||||||
void MDL_map::destroy()
|
void MDL_map::destroy()
|
||||||
{
|
{
|
||||||
MDL_lock::destroy(m_global_lock);
|
delete m_global_lock;
|
||||||
MDL_lock::destroy(m_commit_lock);
|
delete m_commit_lock;
|
||||||
|
|
||||||
DBUG_ASSERT(!m_locks.records);
|
DBUG_ASSERT(!m_locks.records);
|
||||||
mysql_mutex_destroy(&m_mutex);
|
mysql_mutex_destroy(&m_mutex);
|
||||||
|
@ -718,10 +762,10 @@ retry:
|
||||||
mdl_key->length())))
|
mdl_key->length())))
|
||||||
{
|
{
|
||||||
/* No lock object found so we need to create a new one. */
|
/* No lock object found so we need to create a new one. */
|
||||||
lock= MDL_lock::create(mdl_key);
|
lock= new (std::nothrow) MDL_lock(mdl_key);
|
||||||
if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
|
if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
|
||||||
{
|
{
|
||||||
MDL_lock::destroy(lock);
|
delete lock;
|
||||||
mysql_mutex_unlock(&m_mutex);
|
mysql_mutex_unlock(&m_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +809,7 @@ bool MDL_map::move_from_hash_to_lock_mutex(MDL_lock *lock)
|
||||||
*/
|
*/
|
||||||
mysql_prlock_unlock(&lock->m_rwlock);
|
mysql_prlock_unlock(&lock->m_rwlock);
|
||||||
if (old_state == MDL_lock::DELETED + 1)
|
if (old_state == MDL_lock::DELETED + 1)
|
||||||
MDL_lock::destroy(lock);
|
delete lock;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -838,7 +882,7 @@ void MDL_map::remove(MDL_lock *lock)
|
||||||
mysql_mutex_unlock(&m_mutex);
|
mysql_mutex_unlock(&m_mutex);
|
||||||
mysql_prlock_unlock(&lock->m_rwlock);
|
mysql_prlock_unlock(&lock->m_rwlock);
|
||||||
if (!old_state)
|
if (!old_state)
|
||||||
MDL_lock::destroy(lock);
|
delete lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -933,32 +977,6 @@ void MDL_request::init(const MDL_key *key_arg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Auxiliary functions needed for creation/destruction of MDL_lock objects.
|
|
||||||
|
|
||||||
@note Also chooses an MDL_lock descendant appropriate for object namespace.
|
|
||||||
*/
|
|
||||||
|
|
||||||
inline MDL_lock *MDL_lock::create(const MDL_key *mdl_key)
|
|
||||||
{
|
|
||||||
switch (mdl_key->mdl_namespace())
|
|
||||||
{
|
|
||||||
case MDL_key::GLOBAL:
|
|
||||||
case MDL_key::SCHEMA:
|
|
||||||
case MDL_key::COMMIT:
|
|
||||||
return new (std::nothrow) MDL_scoped_lock(mdl_key);
|
|
||||||
default:
|
|
||||||
return new (std::nothrow) MDL_object_lock(mdl_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MDL_lock::destroy(MDL_lock *lock)
|
|
||||||
{
|
|
||||||
delete lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Auxiliary functions needed for creation/destruction of MDL_ticket
|
Auxiliary functions needed for creation/destruction of MDL_ticket
|
||||||
objects.
|
objects.
|
||||||
|
@ -1417,14 +1435,16 @@ void MDL_lock::reschedule_waiters()
|
||||||
on schema objects) and aren't acquired for DML.
|
on schema objects) and aren't acquired for DML.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const MDL_lock::bitmap_t MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END] =
|
const MDL_lock::bitmap_t
|
||||||
|
MDL_lock::MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END]=
|
||||||
{
|
{
|
||||||
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
|
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
|
||||||
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0, 0,
|
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0, 0,
|
||||||
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
|
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
|
||||||
};
|
};
|
||||||
|
|
||||||
const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
|
const MDL_lock::bitmap_t
|
||||||
|
MDL_lock::MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END]=
|
||||||
{
|
{
|
||||||
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
|
MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
|
||||||
MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0
|
MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0
|
||||||
|
@ -1486,7 +1506,7 @@ const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const MDL_lock::bitmap_t
|
const MDL_lock::bitmap_t
|
||||||
MDL_object_lock::m_granted_incompatible[MDL_TYPE_END] =
|
MDL_lock::MDL_object_lock::m_granted_incompatible[MDL_TYPE_END]=
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
MDL_BIT(MDL_EXCLUSIVE),
|
MDL_BIT(MDL_EXCLUSIVE),
|
||||||
|
@ -1510,7 +1530,7 @@ MDL_object_lock::m_granted_incompatible[MDL_TYPE_END] =
|
||||||
|
|
||||||
|
|
||||||
const MDL_lock::bitmap_t
|
const MDL_lock::bitmap_t
|
||||||
MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
|
MDL_lock::MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END]=
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
MDL_BIT(MDL_EXCLUSIVE),
|
MDL_BIT(MDL_EXCLUSIVE),
|
||||||
|
@ -1972,72 +1992,6 @@ MDL_context::clone_ticket(MDL_request *mdl_request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Notify threads holding a shared metadata locks on object which
|
|
||||||
conflict with a pending X, SNW or SNRW lock.
|
|
||||||
|
|
||||||
@param ctx MDL_context for current thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MDL_object_lock::notify_conflicting_locks(MDL_context *ctx)
|
|
||||||
{
|
|
||||||
Ticket_iterator it(m_granted);
|
|
||||||
MDL_ticket *conflicting_ticket;
|
|
||||||
|
|
||||||
while ((conflicting_ticket= it++))
|
|
||||||
{
|
|
||||||
/* Only try to abort locks on which we back off. */
|
|
||||||
if (conflicting_ticket->get_ctx() != ctx &&
|
|
||||||
conflicting_ticket->get_type() < MDL_SHARED_UPGRADABLE)
|
|
||||||
|
|
||||||
{
|
|
||||||
MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
|
|
||||||
|
|
||||||
/*
|
|
||||||
If thread which holds conflicting lock is waiting on table-level
|
|
||||||
lock or some other non-MDL resource we might need to wake it up
|
|
||||||
by calling code outside of MDL.
|
|
||||||
*/
|
|
||||||
ctx->get_owner()->
|
|
||||||
notify_shared_lock(conflicting_ctx->get_owner(),
|
|
||||||
conflicting_ctx->get_needs_thr_lock_abort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Notify threads holding scoped IX locks which conflict with a pending S lock.
|
|
||||||
|
|
||||||
@param ctx MDL_context for current thread.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MDL_scoped_lock::notify_conflicting_locks(MDL_context *ctx)
|
|
||||||
{
|
|
||||||
Ticket_iterator it(m_granted);
|
|
||||||
MDL_ticket *conflicting_ticket;
|
|
||||||
|
|
||||||
while ((conflicting_ticket= it++))
|
|
||||||
{
|
|
||||||
if (conflicting_ticket->get_ctx() != ctx &&
|
|
||||||
conflicting_ticket->get_type() == MDL_INTENTION_EXCLUSIVE)
|
|
||||||
|
|
||||||
{
|
|
||||||
MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Thread which holds global IX lock can be a handler thread for
|
|
||||||
insert delayed. We need to kill such threads in order to get
|
|
||||||
global shared lock. We do this my calling code outside of MDL.
|
|
||||||
*/
|
|
||||||
ctx->get_owner()->
|
|
||||||
notify_shared_lock(conflicting_ctx->get_owner(),
|
|
||||||
conflicting_ctx->get_needs_thr_lock_abort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Acquire one lock with waiting for conflicting locks to go away if needed.
|
Acquire one lock with waiting for conflicting locks to go away if needed.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue