summaryrefslogtreecommitdiff
path: root/sql/net_serv.cc
diff options
context:
space:
mode:
authorunknown <kroki/tomash@moonlight.intranet>2006-08-22 11:47:52 +0400
committerunknown <kroki/tomash@moonlight.intranet>2006-08-22 11:47:52 +0400
commit877477f173419933f1d7c2b9e06dc7cfe925eb6e (patch)
tree6da805e8e859d377d16c5f512dfe034ba5c7ecb2 /sql/net_serv.cc
parentd8180d44b81519ee1d1db8fe79caa2a6d1d6a5eb (diff)
downloadmariadb-git-877477f173419933f1d7c2b9e06dc7cfe925eb6e.tar.gz
BUG#21051: RESET QUERY CACHE very slow when query_cache_type=0
There were two problems: RESET QUERY CACHE took a long time to complete and other threads were blocked during this time. The patch does three things: 1 fixes a bug with improper use of test-lock-test_again technique. AKA Double-Checked Locking is applicable here only in few places. 2 Somewhat improves performance of RESET QUERY CACHE. Do my_hash_reset() instead of deleting elements one by one. Note however that the slowdown also happens when inserting into sorted list of free blocks, should be rewritten using balanced tree. 3 Makes RESET QUERY CACHE non-blocking. The patch adjusts the locking protocol of the query cache in the following way: it introduces a flag flush_in_progress, which is set when Query_cache::flush_cache() is in progress. This call sets the flag on enter, and then releases the lock. Every other call is able to acquire the lock, but does nothing if flush_in_progress is set (as if the query cache is disabled). The only exception is the concurrent calls to Query_cache::flush_cache(), that are blocked until the flush is over. When leaving Query_cache::flush_cache(), the lock is acquired and the flag is reset, and one thread waiting on Query_cache::flush_cache() (if any) is notified that it may proceed. include/mysql_com.h: Add comment for NET::query_cache_query. sql/net_serv.cc: Use query_cache_init_query() for initialization of NET::query_cache_query if query cache is used. Do not access net->query_cache_query without a lock. sql/sql_cache.cc: Fix bug with accessing query_cache_size, Query_cache_query::wri and thd->net.query_cache_query before acquiring the lock---leave double-check locking only in safe places. Wherever we check that cache is usable (query_cache_size > 0) we now also check that flush_in_progress is false, i.e. we are not in the middle of cache flush. Add Query_cache::not_in_flush_or_wait() method and use it in Query_cache::flush_cache(), so that threads doing cache flush will wait it to finish, while other threads will bypass the cache as if it is disabled. Extract Query_cache::free_query_internal() from Query_cache::free_query(), which does not removes elements from the hash, and use it together with my_hash_reset() in Query_cache::flush_cache(). sql/sql_cache.h: Add declarations for new members and methods. Make is_cacheable() a static method. Add query_cache_init_query() function. sql/sql_class.cc: Use query_cache_init_query() for initialization of NET::query_cache_query.
Diffstat (limited to 'sql/net_serv.cc')
-rw-r--r--sql/net_serv.cc17
1 files changed, 11 insertions, 6 deletions
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index cf9dc6e3f60..e54d3abd29d 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -96,8 +96,11 @@ extern uint test_flags;
extern ulong bytes_sent, bytes_received, net_big_packet_count;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#ifndef MYSQL_INSTANCE_MANAGER
-extern void query_cache_insert(NET *net, const char *packet, ulong length);
+#ifdef HAVE_QUERY_CACHE
#define USE_QUERY_CACHE
+extern void query_cache_init_query(NET *net);
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
+#endif // HAVE_QUERY_CACHE
#define update_statistics(A) A
#endif /* MYSQL_INSTANCE_MANGER */
#endif /* defined(MYSQL_SERVER) && !defined(MYSQL_INSTANCE_MANAGER) */
@@ -133,7 +136,11 @@ my_bool my_net_init(NET *net, Vio* vio)
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
- net->query_cache_query=0;
+#ifdef USE_QUERY_CACHE
+ query_cache_init_query(net);
+#else
+ net->query_cache_query= 0;
+#endif
net->report_error= 0;
if (vio != 0) /* If real connection */
@@ -552,10 +559,8 @@ net_real_write(NET *net,const char *packet,ulong len)
my_bool net_blocking = vio_is_blocking(net->vio);
DBUG_ENTER("net_real_write");
-#if defined(MYSQL_SERVER) && defined(HAVE_QUERY_CACHE) \
- && !defined(MYSQL_INSTANCE_MANAGER)
- if (net->query_cache_query != 0)
- query_cache_insert(net, packet, len);
+#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
+ query_cache_insert(net, packet, len);
#endif
if (net->error == 2)