diff options
author | Konstantin Osipov <kostja@sun.com> | 2010-08-12 17:50:23 +0400 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2010-08-12 17:50:23 +0400 |
commit | 8673d2b20fe3cb1353f7b9b157e72dbf45382a48 (patch) | |
tree | 9e8417877eab9778cb09f99e71c11401e7749bbc /sql/mdl.h | |
parent | 65d118b1a4cb3cb4d75226b9280ee80b0d644f70 (diff) | |
parent | 5fff906edd3d7a5d999cec5403f009f33f8dfb81 (diff) | |
download | mariadb-git-8673d2b20fe3cb1353f7b9b157e72dbf45382a48.tar.gz |
Commit on behalf of Dmitry Lenev.
Merge his patch for Bug#52044 into 5.5, and apply
review comments.
Diffstat (limited to 'sql/mdl.h')
-rw-r--r-- | sql/mdl.h | 83 |
1 files changed, 73 insertions, 10 deletions
diff --git a/sql/mdl.h b/sql/mdl.h index 3b21e503369..7938d833eac 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -34,7 +34,6 @@ class THD; class MDL_context; class MDL_lock; class MDL_ticket; -class Deadlock_detection_visitor; /** Type of metadata lock request. @@ -372,6 +371,59 @@ public: typedef void (*mdl_cached_object_release_hook)(void *); + +/** + An abstract class for inspection of a connected + subgraph of the wait-for graph. +*/ + +class MDL_wait_for_graph_visitor +{ +public: + virtual bool enter_node(MDL_context *node) = 0; + virtual void leave_node(MDL_context *node) = 0; + + virtual bool inspect_edge(MDL_context *dest) = 0; + virtual ~MDL_wait_for_graph_visitor(); + MDL_wait_for_graph_visitor() :m_lock_open_count(0) {} +public: + /** + XXX, hack: During deadlock search, we may need to + inspect TABLE_SHAREs and acquire LOCK_open. Since + LOCK_open is not a recursive mutex, count here how many + times we "took" it (but only take and release once). + Not using a native recursive mutex or rwlock in 5.5 for + LOCK_open since it has significant performance impacts. + */ + uint m_lock_open_count; +}; + +/** + Abstract class representing an edge in the waiters graph + to be traversed by deadlock detection algorithm. +*/ + +class MDL_wait_for_subgraph +{ +public: + virtual ~MDL_wait_for_subgraph(); + + /** + Accept a wait-for graph visitor to inspect the node + this edge is leading to. + */ + virtual bool accept_visitor(MDL_wait_for_graph_visitor *gvisitor) = 0; + + enum enum_deadlock_weight + { + DEADLOCK_WEIGHT_DML= 0, + DEADLOCK_WEIGHT_DDL= 100 + }; + /* A helper used to determine which lock request should be aborted. */ + virtual uint get_deadlock_weight() const = 0; +}; + + /** A granted metadata lock. @@ -392,7 +444,7 @@ typedef void (*mdl_cached_object_release_hook)(void *); threads/contexts. */ -class MDL_ticket +class MDL_ticket : public MDL_wait_for_subgraph { public: /** @@ -426,8 +478,9 @@ public: bool is_incompatible_when_granted(enum_mdl_type type) const; bool is_incompatible_when_waiting(enum_mdl_type type) const; - /* A helper used to determine which lock request should be aborted. */ - uint get_deadlock_weight() const; + /** Implement MDL_wait_for_subgraph interface. */ + virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor); + virtual uint get_deadlock_weight() const; private: friend class MDL_context; @@ -594,8 +647,6 @@ public: { return m_needs_thr_lock_abort; } - - bool find_deadlock(Deadlock_detection_visitor *dvisitor); public: /** If our request for a lock is scheduled, or aborted by the deadlock @@ -687,12 +738,13 @@ private: */ mysql_prlock_t m_LOCK_waiting_for; /** - Tell the deadlock detector what lock this session is waiting for. + Tell the deadlock detector what metadata lock or table + definition cache entry this session is waiting for. In principle, this is redundant, as information can be found by inspecting waiting queues, but we'd very much like it to be readily available to the wait-for graph iterator. */ - MDL_ticket *m_waiting_for; + MDL_wait_for_subgraph *m_waiting_for; private: MDL_ticket *find_ticket(MDL_request *mdl_req, bool *is_transactional); @@ -700,13 +752,16 @@ private: bool try_acquire_lock_impl(MDL_request *mdl_request, MDL_ticket **out_ticket); +public: void find_deadlock(); + bool visit_subgraph(MDL_wait_for_graph_visitor *dvisitor); + /** Inform the deadlock detector there is an edge in the wait-for graph. */ - void will_wait_for(MDL_ticket *pending_ticket) + void will_wait_for(MDL_wait_for_subgraph *waiting_for_arg) { mysql_prlock_wrlock(&m_LOCK_waiting_for); - m_waiting_for= pending_ticket; + m_waiting_for= waiting_for_arg; mysql_prlock_unlock(&m_LOCK_waiting_for); } @@ -717,6 +772,14 @@ private: m_waiting_for= NULL; mysql_prlock_unlock(&m_LOCK_waiting_for); } + void lock_deadlock_victim() + { + mysql_prlock_rdlock(&m_LOCK_waiting_for); + } + void unlock_deadlock_victim() + { + mysql_prlock_unlock(&m_LOCK_waiting_for); + } private: MDL_context(const MDL_context &rhs); /* not implemented */ MDL_context &operator=(MDL_context &rhs); /* not implemented */ |