List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:October 27 2010 9:56am
Subject:bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3183 to 3184)
View as plain text  
 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
 3183 Dmitry Lenev	2010-10-26
      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. Add separate thread state name for waiting
      on commit blocker lock.

    modified:
      mysql-test/include/check_ftwrl_incompatible.inc
      mysql-test/t/flush_block_commit.test
      mysql-test/t/flush_read_lock.test
      mysql-test/t/flush_read_lock_kill.test
      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);
     }

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3183 to 3184) Dmitry Lenev27 Oct