diff options
author | unknown <kroki/tomash@moonlight.intranet> | 2006-08-22 11:47:52 +0400 |
---|---|---|
committer | unknown <kroki/tomash@moonlight.intranet> | 2006-08-22 11:47:52 +0400 |
commit | 877477f173419933f1d7c2b9e06dc7cfe925eb6e (patch) | |
tree | 6da805e8e859d377d16c5f512dfe034ba5c7ecb2 /sql/net_serv.cc | |
parent | d8180d44b81519ee1d1db8fe79caa2a6d1d6a5eb (diff) | |
download | mariadb-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.cc | 17 |
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) |