List:Commits« Previous MessageNext Message »
From:Kristofer Pettersson Date:November 20 2009 12:49pm
Subject:bzr commit into mysql-5.1-bugteam branch (kristofer.pettersson:3191)
Bug#21074 Bug#39253
View as plain text  
#At file:///Users/thek/Development/mysql-5.1-qc/ based on revid:kristofer.pettersson@stripped

 3191 Kristofer Pettersson	2009-11-20
      Bug#39253 Large query cache still freezes server after fix for bug #21074
      
      This patch introduce a limit on the time the query cache can
      block with a lock on SELECTs.
      
      Other operations which causes a change in the table
      data will still be blocked.
     @ sql/sql_cache.cc
        * Introduced a timeout value for the qc lock when entering send_result_to_client()
        and store_query() methods.
     @ sql/sql_cache.h
        * New signature for Query_cache::try_lock()

    modified:
      sql/sql_cache.cc
      sql/sql_cache.h
=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc	2009-10-16 10:29:42 +0000
+++ b/sql/sql_cache.cc	2009-11-20 12:49:06 +0000
@@ -421,12 +421,16 @@ TYPELIB query_cache_type_typelib=
   effect by another thread. This enables a quick path in execution to skip waits
   when the outcome is known.
 
+  @param use_timeout TRUE if the lock can abort because of a timeout.
+
+  @note use_timeout is optional and default value is FALSE.
+
   @return
    @retval FALSE An exclusive lock was taken
    @retval TRUE The locking attempt failed
 */
 
-bool Query_cache::try_lock(void)
+bool Query_cache::try_lock(bool use_timeout)
 {
   bool interrupt= FALSE;
   DBUG_ENTER("Query_cache::try_lock");
@@ -456,7 +460,26 @@ bool Query_cache::try_lock(void)
     else
     {
       DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED);
-      pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
+      /*
+        To prevent send_result_to_client() and query_cache_insert() from
+        blocking execution for too long a timeout is put on the lock.
+      */
+      if (use_timeout)
+      {
+        struct timespec waittime;
+        set_timespec_nsec(waittime,(ulong)(50000000L));  /* Wait for 50 msec */
+        int res= pthread_cond_timedwait(&COND_cache_status_changed,
+                                        &structure_guard_mutex,&waittime);
+        if (res == ETIMEDOUT)
+        {
+          interrupt= TRUE;
+          break;
+        }
+      }
+      else
+      {
+        pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
+      }
     }
   }
   pthread_mutex_unlock(&structure_guard_mutex);
@@ -1190,8 +1213,14 @@ def_week_frmt: %lu, in_trans: %d, autoco
       A table- or a full flush operation can potentially take a long time to
       finish. We choose not to wait for them and skip caching statements
       instead.
+
+      In case the wait time can't be determined there is an upper limit which
+      causes try_lock() to abort with a time out.
+
+      The 'TRUE' parameter indicate that the lock is allowed to timeout
+
     */
-    if (try_lock())
+    if (try_lock(TRUE))
       DBUG_VOID_RETURN;
     if (query_cache_size == 0)
     {
@@ -1385,8 +1414,10 @@ Query_cache::send_result_to_client(THD *
     Try to obtain an exclusive lock on the query cache. If the cache is
     disabled or if a full cache flush is in progress, the attempt to
     get the lock is aborted.
+
+    The 'TRUE' parameter indicate that the lock is allowed to timeout
   */
-  if (try_lock())
+  if (try_lock(TRUE))
     goto err;
 
   if (query_cache_size == 0)

=== modified file 'sql/sql_cache.h'
--- a/sql/sql_cache.h	2009-06-16 08:34:47 +0000
+++ b/sql/sql_cache.h	2009-11-20 12:49:06 +0000
@@ -485,7 +485,7 @@ protected:
 			const char *name);
   my_bool in_blocks(Query_cache_block * point);
 
-  bool try_lock(void);
+  bool try_lock(bool use_timeout= FALSE);
   void lock(void);
   void lock_and_suspend(void);
   void unlock(void);


Attachment: [text/bzr-bundle]
Thread
bzr commit into mysql-5.1-bugteam branch (kristofer.pettersson:3191)Bug#21074 Bug#39253Kristofer Pettersson20 Nov