diff options
author | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-11-20 13:49:06 +0100 |
---|---|---|
committer | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-11-20 13:49:06 +0100 |
commit | 41085809c39f1dc44d530a83b59ba8d0d14c1d8d (patch) | |
tree | 24af0f76056f7acfacd3c2c81b77c7ed251ecba9 /sql/sql_cache.cc | |
parent | 8369f619d446dcf6a4e94ce98ff8e85792491ea2 (diff) | |
download | mariadb-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.cc | 39 |
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) |