summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
authorKristofer Pettersson <kristofer.pettersson@sun.com>2009-11-20 13:49:06 +0100
committerKristofer Pettersson <kristofer.pettersson@sun.com>2009-11-20 13:49:06 +0100
commit41085809c39f1dc44d530a83b59ba8d0d14c1d8d (patch)
tree24af0f76056f7acfacd3c2c81b77c7ed251ecba9 /sql/sql_cache.cc
parent8369f619d446dcf6a4e94ce98ff8e85792491ea2 (diff)
downloadmariadb-git-41085809c39f1dc44d530a83b59ba8d0d14c1d8d.tar.gz
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()
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc39
1 files changed, 35 insertions, 4 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 861bd97928d..f862cbed4f1 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -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, autocommit: %d",
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 *thd, char *sql, uint query_length)
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)