summaryrefslogtreecommitdiff
path: root/sql/table.h
diff options
context:
space:
mode:
authorDmitry Lenev <dlenev@mysql.com>2010-07-27 17:34:58 +0400
committerDmitry Lenev <dlenev@mysql.com>2010-07-27 17:34:58 +0400
commit5fff906edd3d7a5d999cec5403f009f33f8dfb81 (patch)
treebef62913efddc244d466f7ff730bcc4205357491 /sql/table.h
parentec2c3bf2c1c27e4401c767a6cdcb3172453ff42c (diff)
downloadmariadb-git-5fff906edd3d7a5d999cec5403f009f33f8dfb81.tar.gz
Fix for bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH
TABLES <list> WITH READ LOCK are incompatible". The problem was that FLUSH TABLES <list> WITH READ LOCK which was issued when other connection has acquired global read lock using FLUSH TABLES WITH READ LOCK was blocked and has to wait until global read lock is released. This issue stemmed from the fact that FLUSH TABLES <list> WITH READ LOCK implementation has acquired X metadata locks on tables to be flushed. Since these locks required acquiring of global IX lock this statement was incompatible with global read lock. This patch addresses problem by using SNW metadata type of lock for tables to be flushed by FLUSH TABLES <list> WITH READ LOCK. It is OK to acquire them without global IX lock as long as we won't try to upgrade those locks. Since SNW locks allow concurrent statements using same table FLUSH TABLE <list> WITH READ LOCK now has to wait until old versions of tables to be flushed go away after acquiring metadata locks. Since such waiting can lead to deadlock MDL deadlock detector was extended to take into account waits for flush and resolve such deadlocks. As a bonus code in open_tables() which was responsible for waiting old versions of tables to go away was refactored. Now when we encounter old version of table in open_table() we don't back-off and wait for all old version to go away, but instead wait for this particular table to be flushed. Such approach supported by deadlock detection should reduce number of scenarios in which FLUSH TABLES aborts concurrent multi-statement transactions. Note that active FLUSH TABLES <list> WITH READ LOCK still blocks concurrent FLUSH TABLES WITH READ LOCK statement as the former keeps tables open and thus prevents the latter statement from doing flush.
Diffstat (limited to 'sql/table.h')
-rw-r--r--sql/table.h51
1 files changed, 51 insertions, 0 deletions
diff --git a/sql/table.h b/sql/table.h
index 2bf390aee4d..46015f4425a 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -45,6 +45,7 @@ class ACL_internal_schema_access;
class ACL_internal_table_access;
struct TABLE_LIST;
class Field;
+class Deadlock_detection_visitor;
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
@@ -508,6 +509,45 @@ public:
};
+/**
+ Class representing the fact that some thread waits for table
+ share to be flushed. Is used to represent information about
+ such waits in MDL deadlock detector.
+*/
+
+class Flush_ticket : public Wait_for_edge
+{
+ MDL_context *m_ctx;
+ TABLE_SHARE *m_share;
+ uint m_deadlock_weight;
+public:
+ Flush_ticket(MDL_context *ctx_arg, TABLE_SHARE *share_arg,
+ uint deadlock_weight_arg)
+ : m_ctx(ctx_arg), m_share(share_arg),
+ m_deadlock_weight(deadlock_weight_arg)
+ {}
+
+ MDL_context *get_ctx() const { return m_ctx; }
+
+ bool find_deadlock(Deadlock_detection_visitor *dvisitor);
+
+ uint get_deadlock_weight() const;
+
+ /**
+ Pointers for participating in the list of waiters for table share.
+ */
+ Flush_ticket *next_in_share;
+ Flush_ticket **prev_in_share;
+};
+
+
+typedef I_P_List <Flush_ticket,
+ I_P_List_adapter<Flush_ticket,
+ &Flush_ticket::next_in_share,
+ &Flush_ticket::prev_in_share> >
+ Flush_ticket_list;
+
+
/*
This structure is shared between different table objects. There is one
instance of table share per one table in the database.
@@ -662,6 +702,11 @@ struct TABLE_SHARE
/** Instrumentation for this table share. */
PSI_table_share *m_psi;
+ /**
+ List of tickets representing threads waiting for the share to be flushed.
+ */
+ Flush_ticket_list m_flush_tickets;
+
/*
Set share's table cache key and update its db and table name appropriately.
@@ -837,6 +882,12 @@ struct TABLE_SHARE
return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id;
}
+ bool find_deadlock(Flush_ticket *waiting_ticket,
+ Deadlock_detection_visitor *dvisitor);
+
+ bool wait_until_flushed(MDL_context *mdl_context,
+ struct timespec *abstime,
+ uint deadlock_weight);
};