diff options
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r-- | sql/sql_cache.cc | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f995b51ae68..302d5e95a28 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -377,9 +377,11 @@ TODO list: static void debug_wait_for_kill(const char *info) { - DBUG_ENTER("debug_wait_for_kill"); const char *prev_info; THD *thd; + char buff[1024]; + DBUG_ENTER("debug_wait_for_kill"); + thd= current_thd; prev_info= thd->proc_info; thd->proc_info= info; @@ -387,8 +389,16 @@ static void debug_wait_for_kill(const char *info) while(!thd->killed) my_sleep(1000); thd->killed= THD::NOT_KILLED; + /* + Remove the set debug variable, to ensure we don't get stuck on it again + This is needed as for MyISAM, invalidate_table() may be called twice + (Once from mysql_delete() and once from mi_update_status()) + */ + sprintf(buff, "-d,%s", info); + DBUG_SET(buff); sql_print_information("Exit debug_wait_for_kill"); thd->proc_info= prev_info; + DBUG_VOID_RETURN; } @@ -421,12 +431,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 +470,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); @@ -891,15 +924,18 @@ void query_cache_insert(NET *net, const char *packet, ulong length) void query_cache_abort(NET *net) { + THD *thd; DBUG_ENTER("query_cache_abort"); - THD *thd= current_thd; /* See the comment on double-check locking usage above. */ if (net->query_cache_query == 0) DBUG_VOID_RETURN; if (query_cache.try_lock()) + { + net->query_cache_query = 0; DBUG_VOID_RETURN; + } /* While we were waiting another thread might have changed the status @@ -909,6 +945,7 @@ void query_cache_abort(NET *net) net->query_cache_query); if (query_block) { + thd= current_thd; thd_proc_info(thd, "storing result in query cache"); DUMP(&query_cache); BLOCK_LOCK_WR(query_block); @@ -918,6 +955,7 @@ void query_cache_abort(NET *net) DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); } + DBUG_ASSERT(!net->query_cache_query); query_cache.unlock(); DBUG_VOID_RETURN; } @@ -947,8 +985,12 @@ void query_cache_end_of_result(THD *thd) #endif if (query_cache.try_lock()) + { + thd->net.query_cache_query= 0; DBUG_VOID_RETURN; + } + /* thd->net.query_cache_query may have changed during resize */ query_block= ((Query_cache_block*) thd->net.query_cache_query); if (query_block) { @@ -974,8 +1016,8 @@ void query_cache_end_of_result(THD *thd) to this function. In the release version that query should be ignored and removed from QC. */ - DBUG_ASSERT(0); query_cache.free_query(query_block); + thd->net.query_cache_query= 0; query_cache.unlock(); DBUG_VOID_RETURN; } @@ -1190,8 +1232,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) { @@ -1306,8 +1354,8 @@ end: to the user. RESULTS - 1 Query was not cached. - 0 The query was cached and user was sent the result. + 0 Query was not cached. + 1 The query was cached and user was sent the result. -1 The query was cached but we didn't have rights to use it. No error is sent to the client yet. @@ -1388,8 +1436,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) |