From: Dmitry Lenev Date: October 27 2010 9:56am Subject: bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3183 to 3184) List-Archive: http://lists.mysql.com/commits/122061 Message-Id: <20101027095648.AFD782F0E23@mockturtle> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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).