#At file:///home/dlenev/src/bzr/mysql-5.5-rt-grl/ based on revid:dmitry.lenev@stripped
3184 Dmitry Lenev 2010-10-27
More changes to draft patch refactoring global read
lock implementation. Makes GRL yet another type of
metadata lock and thus exposes it to deadlock detector
in MDL subsystem.
Solves bugs #54673 "It takes too long to get readlock for
'FLUSH TABLES WITH READ LOCK'" and #57006 "Deadlock between
HANDLER and FLUSH TABLES WITH READ LOCK".
Work-in-progress. Polish code related to MDL subsystem killing
threads holding conflicting metadata locks.
modified:
sql/mdl.cc
=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc 2010-10-26 18:50:18 +0000
+++ b/sql/mdl.cc 2010-10-27 09:55:52 +0000
@@ -68,8 +68,6 @@ static void init_mdl_psi_keys(void)
}
#endif /* HAVE_PSI_INTERFACE */
-void notify_shared_lock(THD *thd, MDL_ticket *conflicting_ticket);
-
/**
Thread state names to be used in case when we have to wait on resource
@@ -359,18 +357,6 @@ public:
inline static MDL_lock *create(const MDL_key *key);
- void notify_shared_locks(MDL_context *ctx)
- {
- Ticket_iterator it(m_granted);
- MDL_ticket *conflicting_ticket;
-
- while ((conflicting_ticket= it++))
- {
- if (conflicting_ticket->get_ctx() != ctx)
- notify_shared_lock(ctx->get_thd(), conflicting_ticket);
- }
- }
-
void reschedule_waiters();
void remove_ticket(Ticket_list MDL_lock::*queue, MDL_ticket *ticket);
@@ -379,6 +365,7 @@ public:
MDL_wait_for_graph_visitor *gvisitor);
virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
+ virtual void notify_conflicting_locks(MDL_context *ctx) = 0;
/** List of granted tickets for this lock. */
Ticket_list m_granted;
@@ -453,6 +440,7 @@ public:
{
return (ticket->get_type() == MDL_SHARED);
}
+ virtual void notify_conflicting_locks(MDL_context *ctx);
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
@@ -484,6 +472,7 @@ public:
{
return ticket->is_upgradable_or_exclusive();
}
+ virtual void notify_conflicting_locks(MDL_context *ctx);
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
@@ -1716,29 +1705,67 @@ MDL_context::clone_ticket(MDL_request *m
/**
- Notify a thread holding a shared metadata lock which
- conflicts with a pending exclusive lock.
+ Notify threads holding a shared metadata locks on object which
+ conflict with a pending X, SNW or SNRW lock.
- @param thd Current thread context
- @param conflicting_ticket Conflicting metadata lock
+ @param ctx MDL_context for current thread.
*/
-void notify_shared_lock(THD *thd, MDL_ticket *conflicting_ticket)
+void MDL_object_lock::notify_conflicting_locks(MDL_context *ctx)
{
- /* Only try to abort locks on which we back off. */
- if (conflicting_ticket->get_type() < MDL_SHARED_NO_WRITE)
+ Ticket_iterator it(m_granted);
+ MDL_ticket *conflicting_ticket;
+
+ while ((conflicting_ticket= it++))
{
- MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
- THD *conflicting_thd= conflicting_ctx->get_thd();
- DBUG_ASSERT(thd != conflicting_thd); /* Self-deadlock */
+ /* Only try to abort locks on which we back off. */
+ if (conflicting_ticket->get_ctx() != ctx &&
+ conflicting_ticket->get_type() < MDL_SHARED_NO_WRITE)
- /*
- 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.
- */
- mysql_notify_thread_having_shared_lock(thd, conflicting_thd,
- conflicting_ctx->get_needs_thr_lock_abort());
+ {
+ 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.
+ */
+ mysql_notify_thread_having_shared_lock(ctx->get_thd(),
+ conflicting_ctx->get_thd(),
+ 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.
+ */
+ mysql_notify_thread_having_shared_lock(ctx->get_thd(),
+ conflicting_ctx->get_thd(),
+ conflicting_ctx->get_needs_thr_lock_abort());
+ }
}
}
@@ -1797,7 +1824,7 @@ MDL_context::acquire_lock(MDL_request *m
m_wait.reset_status();
if (lock->needs_notification(ticket))
- lock->notify_shared_locks(this);
+ lock->notify_conflicting_locks(this);
mysql_prlock_unlock(&lock->m_rwlock);
@@ -1824,7 +1851,7 @@ MDL_context::acquire_lock(MDL_request *m
break;
mysql_prlock_wrlock(&lock->m_rwlock);
- lock->notify_shared_locks(this);
+ lock->notify_conflicting_locks(this);
mysql_prlock_unlock(&lock->m_rwlock);
set_timespec(abs_shortwait, 1);
}
Attachment: [text/bzr-bundle] bzr/dmitry.lenev@oracle.com-20101027095552-i8edsx3gfausukf4.bundle
| Thread |
|---|
| • bzr commit into mysql-5.5-runtime branch (Dmitry.Lenev:3184) | Dmitry Lenev | 27 Oct |