List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:November 8 2010 9:55am
Subject:bzr commit into mysql-5.5-runtime branch (Dmitry.Lenev:3189)
View as plain text  
#At file:///home/dlenev/src/bzr/mysql-5.5-rt-grl/ based on revid:dmitry.lenev@stripped

 3189 Dmitry Lenev	2010-11-08
      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. Minor after review fixes.

    modified:
      sql/lock.cc
      sql/sql_base.cc
      sql/sql_class.h
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_parse.h
=== modified file 'sql/lock.cc'
--- a/sql/lock.cc	2010-11-03 18:09:02 +0000
+++ b/sql/lock.cc	2010-11-08 09:55:43 +0000
@@ -779,17 +779,8 @@ bool lock_schema_name(THD *thd, const ch
 
   if (thd->global_read_lock.can_acquire_protection())
     return TRUE;
-
-  /*
-    This function can be only called during execution of a DDL statement.
-    Since such statements release all metadata locks at its end we don't
-    need to do anything special to ensure that protection against GRL is
-    released.
-  */
-  DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
-
-  thd->global_read_lock.init_protection_request(&global_request);
-
+  global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
+                      MDL_STATEMENT);
   mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE, MDL_TRANSACTION);
 
   mdl_requests.push_front(&mdl_request);
@@ -847,16 +838,8 @@ bool lock_object_name(THD *thd, MDL_key:
 
   if (thd->global_read_lock.can_acquire_protection())
     return TRUE;
-
-  /*
-    This function can be only called during execution of a DDL statement.
-    Since such statements release all metadata locks at its end we don't
-    need to do anything special to ensure that protection against GRL is
-    released.
-  */
-  DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
-
-  thd->global_read_lock.init_protection_request(&global_request);
+  global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
+                      MDL_STATEMENT);
   schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE,
                       MDL_TRANSACTION);
   mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE, MDL_TRANSACTION);
@@ -1034,38 +1017,6 @@ void Global_read_lock::unlock_global_rea
 
 
 /**
-  Check if this connection can acquire protecting against GRL and
-  emit error if otherwise.
-
-  QQ: Does it make sense to make it inline?
-*/
-
-bool Global_read_lock::can_acquire_protection()
-{
-  if (m_state)
-  {
-    my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0));
-    return TRUE;
-  }
-  return FALSE;
-}
-
-
-/**
-  Initialize request for lock protecting normal statement from GRL
-  (and vice versa).
-
-  QQ: Does it make sense to make it inline?
-*/
-
-void Global_read_lock::init_protection_request(MDL_request *request)
-{
-  request->init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
-                MDL_STATEMENT);
-}
-
-
-/**
   Make global read lock also block commits.
 
   The scenario is:

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-11-03 14:30:33 +0000
+++ b/sql/sql_base.cc	2010-11-08 09:55:43 +0000
@@ -2822,7 +2822,8 @@ bool open_table(THD *thd, TABLE_LIST *ta
     if (thd->global_read_lock.can_acquire_protection())
       DBUG_RETURN(TRUE);
 
-    thd->global_read_lock.init_protection_request(&protection_request);
+    protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
+                            MDL_STATEMENT);
     /*
       Install error handler which if possible will convert deadlock error
       into request to back-off and restart process of opening tables.
@@ -4579,18 +4580,15 @@ lock_table_names(THD *thd,
       mdl_requests.push_front(schema_request);
     }
 
-    if (thd->global_read_lock.can_acquire_protection())
-      return TRUE;
-
     /*
-      We can get here only during execution of code which will release
-      all metadata locks by the statement's end. So we don't need to do
-      anything special to ensure that protection against GRL is released.
-
-      QQ: This assumption is kind of ugly and hard to enforce using asserts.
-          Is there any nice way to get rid of it?
+      Protect this statement against concurrent global read lock
+      by acquiring global intention exclusive lock with statement
+      duration.
     */
-    thd->global_read_lock.init_protection_request(&global_request);
+    if (thd->global_read_lock.can_acquire_protection())
+      return TRUE;
+    global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
+                        MDL_STATEMENT);
     mdl_requests.push_front(&global_request);
   }
 

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-11-03 18:09:02 +0000
+++ b/sql/sql_class.h	2010-11-08 09:55:43 +0000
@@ -1343,9 +1343,19 @@ public:
 
   bool lock_global_read_lock(THD *thd);
   void unlock_global_read_lock(THD *thd);
-  bool can_acquire_protection();
-  bool has_read_lock() const { return (m_state != GRL_NONE); }
-  void init_protection_request(MDL_request *request);
+  /**
+    Check if this connection can acquire protection against GRL and
+    emit error if otherwise.
+  */
+  bool can_acquire_protection() const
+  {
+    if (m_state)
+    {
+      my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0));
+      return TRUE;
+    }
+    return FALSE;
+  }
   bool make_global_read_lock_block_commit(THD *thd);
   bool is_acquired() const { return m_state != GRL_NONE; }
   void set_explicit_lock_duration(THD *thd);

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-11-03 14:30:33 +0000
+++ b/sql/sql_insert.cc	2010-11-08 09:55:43 +0000
@@ -545,7 +545,8 @@ bool open_and_lock_for_insert_delayed(TH
   if (thd->global_read_lock.can_acquire_protection())
     DBUG_RETURN(TRUE);
 
-  thd->global_read_lock.init_protection_request(&protection_request);
+  protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
+                          MDL_STATEMENT);
 
   if (thd->mdl_context.acquire_lock(&protection_request,
                                     thd->variables.lock_wait_timeout))

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-11-03 18:09:02 +0000
+++ b/sql/sql_parse.cc	2010-11-08 09:55:43 +0000
@@ -187,7 +187,7 @@ static bool some_non_temp_table_to_be_up
   @param mask   Bitmask used for the SQL command match.
 
 */
-bool stmt_causes_implicit_commit(THD *thd, uint mask)
+static bool stmt_causes_implicit_commit(THD *thd, uint mask)
 {
   LEX *lex= thd->lex;
   bool skip= FALSE;

=== modified file 'sql/sql_parse.h'
--- a/sql/sql_parse.h	2010-10-18 12:33:49 +0000
+++ b/sql/sql_parse.h	2010-11-08 09:55:43 +0000
@@ -78,7 +78,6 @@ bool check_host_name(LEX_STRING *str);
 bool check_identifier_name(LEX_STRING *str, uint max_char_length,
                            uint err_code, const char *param_for_err_msg);
 bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
-bool stmt_causes_implicit_commit(THD *thd, uint mask);
 bool sqlcom_can_generate_row_events(const THD *thd);
 bool is_update_query(enum enum_sql_command command);
 bool is_log_table_write_query(enum enum_sql_command command);


Attachment: [text/bzr-bundle] bzr/dmitry.lenev@oracle.com-20101108095543-dx7wpum9xxf21pq8.bundle
Thread
bzr commit into mysql-5.5-runtime branch (Dmitry.Lenev:3189) Dmitry Lenev8 Nov