Introduce thd->query_cache_tls (thread
local storage for query cache). We need more than one pointer in a thread to represent the query cache and net->query_cache_query can not be used any more (due to ABI compatibility issues and to different life time of NET and THD). This is a backport of the following patch from 6.0: ---------------------------------------------------------- revno: 2476.1157.2 committer: kostja@bodhi.(none) timestamp: Sat 2007-06-16 13:29:24 +0400 include/mysql.h.pp: Update the ABI (NET::query_cache_query is now unused). include/mysql_com.h: NET::query_cache_query is now unused. sql/mysql_priv.h: Update signatures of ex-functios now member functions. sql/sql_cache.cc: Introduce THD::query_cache_tls. sql/sql_cache.h: Introduce THD::query_cache_tls. sql/sql_class.cc: Introduce THD::query_cache_tls. sql/sql_class.h: Introduce THD::query_cache_tls. sql/sql_parse.cc: Use THD::query_cache_tls. sql/sql_select.cc: Use THD::query_cache_tls.
This commit is contained in:
parent
9a65687bd9
commit
99420dd913
@ -32,7 +32,7 @@ typedef struct st_net {
|
|||||||
my_bool unused2;
|
my_bool unused2;
|
||||||
my_bool compress;
|
my_bool compress;
|
||||||
my_bool unused3;
|
my_bool unused3;
|
||||||
unsigned char *query_cache_query;
|
unsigned char *unused;
|
||||||
unsigned int last_errno;
|
unsigned int last_errno;
|
||||||
unsigned char error;
|
unsigned char error;
|
||||||
my_bool unused4;
|
my_bool unused4;
|
||||||
|
@ -264,10 +264,9 @@ typedef struct st_net {
|
|||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
'query_cache_query' should be accessed only via query cache
|
Unused, please remove with the next incompatible ABI change.
|
||||||
functions and methods to maintain proper locking.
|
|
||||||
*/
|
*/
|
||||||
unsigned char *query_cache_query;
|
unsigned char *unused;
|
||||||
unsigned int last_errno;
|
unsigned int last_errno;
|
||||||
unsigned char error;
|
unsigned char error;
|
||||||
my_bool unused4; /* Please remove with the next incompatible ABI change. */
|
my_bool unused4; /* Please remove with the next incompatible ABI change. */
|
||||||
|
@ -905,6 +905,8 @@ struct Query_cache_query_flags
|
|||||||
};
|
};
|
||||||
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
|
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
|
||||||
#include "sql_cache.h"
|
#include "sql_cache.h"
|
||||||
|
#define query_cache_abort(A) query_cache.abort(A)
|
||||||
|
#define query_cache_end_of_result(A) query_cache.end_of_result(A)
|
||||||
#define query_cache_store_query(A, B) query_cache.store_query(A, B)
|
#define query_cache_store_query(A, B) query_cache.store_query(A, B)
|
||||||
#define query_cache_destroy() query_cache.destroy()
|
#define query_cache_destroy() query_cache.destroy()
|
||||||
#define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
|
#define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
|
||||||
|
@ -95,8 +95,8 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
|
|||||||
#ifndef MYSQL_INSTANCE_MANAGER
|
#ifndef MYSQL_INSTANCE_MANAGER
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
#define USE_QUERY_CACHE
|
#define USE_QUERY_CACHE
|
||||||
extern void query_cache_init_query(NET *net);
|
extern void query_cache_insert(const char *packet, ulong length,
|
||||||
extern void query_cache_insert(NET *net, const char *packet, ulong length);
|
unsigned pkt_nr);
|
||||||
#endif // HAVE_QUERY_CACHE
|
#endif // HAVE_QUERY_CACHE
|
||||||
#define update_statistics(A) A
|
#define update_statistics(A) A
|
||||||
#endif /* MYSQL_INSTANCE_MANGER */
|
#endif /* MYSQL_INSTANCE_MANGER */
|
||||||
@ -132,11 +132,7 @@ my_bool my_net_init(NET *net, Vio* vio)
|
|||||||
net->compress=0; net->reading_or_writing=0;
|
net->compress=0; net->reading_or_writing=0;
|
||||||
net->where_b = net->remain_in_buf=0;
|
net->where_b = net->remain_in_buf=0;
|
||||||
net->last_errno=0;
|
net->last_errno=0;
|
||||||
#ifdef USE_QUERY_CACHE
|
net->unused= 0;
|
||||||
query_cache_init_query(net);
|
|
||||||
#else
|
|
||||||
net->query_cache_query= 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vio != 0) /* If real connection */
|
if (vio != 0) /* If real connection */
|
||||||
{
|
{
|
||||||
@ -586,7 +582,7 @@ net_real_write(NET *net,const uchar *packet, size_t len)
|
|||||||
DBUG_ENTER("net_real_write");
|
DBUG_ENTER("net_real_write");
|
||||||
|
|
||||||
#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
|
#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
|
||||||
query_cache_insert(net, (char*) packet, len);
|
query_cache_insert((char*) packet, len, net->pkt_nr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (net->error == 2)
|
if (net->error == 2)
|
||||||
|
162
sql/sql_cache.cc
162
sql/sql_cache.cc
@ -789,19 +789,20 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
|
|||||||
Note on double-check locking (DCL) usage.
|
Note on double-check locking (DCL) usage.
|
||||||
|
|
||||||
Below, in query_cache_insert(), query_cache_abort() and
|
Below, in query_cache_insert(), query_cache_abort() and
|
||||||
query_cache_end_of_result() we use what is called double-check
|
Query_cache::end_of_result() we use what is called double-check
|
||||||
locking (DCL) for NET::query_cache_query. I.e. we test it first
|
locking (DCL) for Query_cache_tls::first_query_block.
|
||||||
without a lock, and, if positive, test again under the lock.
|
I.e. we test it first without a lock, and, if positive, test again
|
||||||
|
under the lock.
|
||||||
|
|
||||||
This means that if we see 'NET::query_cache_query == 0' without a
|
This means that if we see 'first_query_block == 0' without a
|
||||||
lock we will skip the operation. But this is safe here: when we
|
lock we will skip the operation. But this is safe here: when we
|
||||||
started to cache a query, we called Query_cache::store_query(), and
|
started to cache a query, we called Query_cache::store_query(), and
|
||||||
NET::query_cache_query was set to non-zero in this thread (and the
|
'first_query_block' was set to non-zero in this thread (and the
|
||||||
thread always sees results of its memory operations, mutex or not).
|
thread always sees results of its memory operations, mutex or not).
|
||||||
If later we see 'NET::query_cache_query == 0' without locking a
|
If later we see 'first_query_block == 0' without locking a
|
||||||
mutex, that may only mean that some other thread have reset it by
|
mutex, that may only mean that some other thread have reset it by
|
||||||
invalidating the query. Skipping the operation in this case is the
|
invalidating the query. Skipping the operation in this case is the
|
||||||
right thing to do, as NET::query_cache_query won't get non-zero for
|
right thing to do, as first_query_block won't get non-zero for
|
||||||
this query again.
|
this query again.
|
||||||
|
|
||||||
See also comments in Query_cache::store_query() and
|
See also comments in Query_cache::store_query() and
|
||||||
@ -810,56 +811,71 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
|
|||||||
NOTE, however, that double-check locking is not applicable in
|
NOTE, however, that double-check locking is not applicable in
|
||||||
'invalidate' functions, as we may erroneously skip invalidation,
|
'invalidate' functions, as we may erroneously skip invalidation,
|
||||||
because the thread doing invalidation may never see non-zero
|
because the thread doing invalidation may never see non-zero
|
||||||
NET::query_cache_query.
|
'first_query_block'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void query_cache_init_query(NET *net)
|
/**
|
||||||
|
libmysql convenience wrapper to insert data into query cache.
|
||||||
|
*/
|
||||||
|
void query_cache_insert(const char *packet, ulong length,
|
||||||
|
unsigned pkt_nr)
|
||||||
{
|
{
|
||||||
|
THD *thd= current_thd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
It is safe to initialize 'NET::query_cache_query' without a lock
|
Current_thd can be NULL when a new connection is immediately ended
|
||||||
here, because before it will be accessed from different threads it
|
due to "Too many connections". thd->store_globals() has not been
|
||||||
will be set in this thread under a lock, and access from the same
|
called at this time and hence my_pthread_setspecific_ptr(THR_THD,
|
||||||
thread is always safe.
|
this) has not been called for this thread.
|
||||||
*/
|
*/
|
||||||
net->query_cache_query= 0;
|
|
||||||
|
if (!thd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
query_cache.insert(&thd->query_cache_tls,
|
||||||
|
packet, length,
|
||||||
|
pkt_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Insert the packet into the query cache.
|
Insert the packet into the query cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void query_cache_insert(NET *net, const char *packet, ulong length)
|
void
|
||||||
|
Query_cache::insert(Query_cache_tls *query_cache_tls,
|
||||||
|
const char *packet, ulong length,
|
||||||
|
unsigned pkt_nr)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("query_cache_insert");
|
DBUG_ENTER("Query_cache::insert");
|
||||||
|
|
||||||
/* See the comment on double-check locking usage above. */
|
/* See the comment on double-check locking usage above. */
|
||||||
if (net->query_cache_query == 0)
|
if (query_cache_tls->first_query_block == NULL)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
|
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
|
||||||
debug_wait_for_kill("wait_in_query_cache_insert"); );
|
debug_wait_for_kill("wait_in_query_cache_insert"); );
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
|
||||||
|
if (try_lock())
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
Query_cache_block *query_block= (Query_cache_block*)net->query_cache_query;
|
Query_cache_block *query_block = query_cache_tls->first_query_block;
|
||||||
if (!query_block)
|
if (query_block == NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We lost the writer and the currently processed query has been
|
We lost the writer and the currently processed query has been
|
||||||
invalidated; there is nothing left to do.
|
invalidated; there is nothing left to do.
|
||||||
*/
|
*/
|
||||||
query_cache.unlock();
|
unlock();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCK_LOCK_WR(query_block);
|
BLOCK_LOCK_WR(query_block);
|
||||||
Query_cache_query *header= query_block->query();
|
Query_cache_query *header= query_block->query();
|
||||||
Query_cache_block *result= header->result();
|
Query_cache_block *result= header->result();
|
||||||
|
|
||||||
DUMP(&query_cache);
|
DUMP(this);
|
||||||
DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
|
DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -867,8 +883,8 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
|
|||||||
still need structure_guard_mutex to free the query, and therefore unlock
|
still need structure_guard_mutex to free the query, and therefore unlock
|
||||||
it later in this function.
|
it later in this function.
|
||||||
*/
|
*/
|
||||||
if (!query_cache.append_result_data(&result, length, (uchar*) packet,
|
if (!append_result_data(&result, length, (uchar*) packet,
|
||||||
query_block))
|
query_block))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("warning", ("Can't append data"));
|
DBUG_PRINT("warning", ("Can't append data"));
|
||||||
header->result(result);
|
header->result(result);
|
||||||
@ -877,60 +893,63 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
|
|||||||
query_cache.free_query(query_block);
|
query_cache.free_query(query_block);
|
||||||
query_cache.refused++;
|
query_cache.refused++;
|
||||||
// append_result_data no success => we need unlock
|
// append_result_data no success => we need unlock
|
||||||
query_cache.unlock();
|
unlock();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
header->result(result);
|
header->result(result);
|
||||||
header->last_pkt_nr= net->pkt_nr;
|
header->last_pkt_nr= pkt_nr;
|
||||||
BLOCK_UNLOCK_WR(query_block);
|
BLOCK_UNLOCK_WR(query_block);
|
||||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
|
DBUG_EXECUTE("check_querycache",check_integrity(0););
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void query_cache_abort(NET *net)
|
void
|
||||||
|
Query_cache::abort(Query_cache_tls *query_cache_tls)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("query_cache_abort");
|
DBUG_ENTER("query_cache_abort");
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
|
|
||||||
/* See the comment on double-check locking usage above. */
|
/* See the comment on double-check locking usage above. */
|
||||||
if (net->query_cache_query == 0)
|
if (query_cache_tls->first_query_block == NULL)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
if (try_lock())
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
While we were waiting another thread might have changed the status
|
While we were waiting another thread might have changed the status
|
||||||
of the writer. Make sure the writer still exists before continue.
|
of the writer. Make sure the writer still exists before continue.
|
||||||
*/
|
*/
|
||||||
Query_cache_block *query_block= ((Query_cache_block*)
|
Query_cache_block *query_block= query_cache_tls->first_query_block;
|
||||||
net->query_cache_query);
|
|
||||||
if (query_block)
|
if (query_block)
|
||||||
{
|
{
|
||||||
thd_proc_info(thd, "storing result in query cache");
|
thd_proc_info(thd, "storing result in query cache");
|
||||||
DUMP(&query_cache);
|
DUMP(this);
|
||||||
BLOCK_LOCK_WR(query_block);
|
BLOCK_LOCK_WR(query_block);
|
||||||
// The following call will remove the lock on query_block
|
// The following call will remove the lock on query_block
|
||||||
query_cache.free_query(query_block);
|
free_query(query_block);
|
||||||
net->query_cache_query= 0;
|
query_cache_tls->first_query_block= NULL;
|
||||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
|
DBUG_EXECUTE("check_querycache", check_integrity(1););
|
||||||
}
|
}
|
||||||
|
|
||||||
query_cache.unlock();
|
unlock();
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void query_cache_end_of_result(THD *thd)
|
void Query_cache::end_of_result(THD *thd)
|
||||||
{
|
{
|
||||||
Query_cache_block *query_block;
|
Query_cache_block *query_block;
|
||||||
DBUG_ENTER("query_cache_end_of_result");
|
Query_cache_tls *query_cache_tls= &thd->query_cache_tls;
|
||||||
|
ulonglong limit_found_rows= thd->limit_found_rows;
|
||||||
|
DBUG_ENTER("Query_cache::end_of_result");
|
||||||
|
|
||||||
/* See the comment on double-check locking usage above. */
|
/* See the comment on double-check locking usage above. */
|
||||||
if (thd->net.query_cache_query == 0)
|
if (query_cache_tls->first_query_block == NULL)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
/* Ensure that only complete results are cached. */
|
/* Ensure that only complete results are cached. */
|
||||||
@ -938,19 +957,19 @@ void query_cache_end_of_result(THD *thd)
|
|||||||
|
|
||||||
if (thd->killed)
|
if (thd->killed)
|
||||||
{
|
{
|
||||||
query_cache_abort(&thd->net);
|
query_cache_abort(&thd->query_cache_tls);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
query_cache_insert(&thd->net, (char*)thd,
|
insert(query_cache_tls, (char*)thd,
|
||||||
emb_count_querycache_size(thd));
|
emb_count_querycache_size(thd), 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
if (try_lock())
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
query_block= ((Query_cache_block*) thd->net.query_cache_query);
|
query_block= query_cache_tls->first_query_block;
|
||||||
if (query_block)
|
if (query_block)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -959,7 +978,7 @@ void query_cache_end_of_result(THD *thd)
|
|||||||
block, the writer should be dropped.
|
block, the writer should be dropped.
|
||||||
*/
|
*/
|
||||||
thd_proc_info(thd, "storing result in query cache");
|
thd_proc_info(thd, "storing result in query cache");
|
||||||
DUMP(&query_cache);
|
DUMP(this);
|
||||||
BLOCK_LOCK_WR(query_block);
|
BLOCK_LOCK_WR(query_block);
|
||||||
Query_cache_query *header= query_block->query();
|
Query_cache_query *header= query_block->query();
|
||||||
Query_cache_block *last_result_block;
|
Query_cache_block *last_result_block;
|
||||||
@ -976,8 +995,8 @@ void query_cache_end_of_result(THD *thd)
|
|||||||
and removed from QC.
|
and removed from QC.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
query_cache.free_query(query_block);
|
free_query(query_block);
|
||||||
query_cache.unlock();
|
unlock();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
last_result_block= header->result()->prev;
|
last_result_block= header->result()->prev;
|
||||||
@ -986,17 +1005,17 @@ void query_cache_end_of_result(THD *thd)
|
|||||||
if (last_result_block->length >= query_cache.min_allocation_unit + len)
|
if (last_result_block->length >= query_cache.min_allocation_unit + len)
|
||||||
query_cache.split_block(last_result_block,len);
|
query_cache.split_block(last_result_block,len);
|
||||||
|
|
||||||
header->found_rows(current_thd->limit_found_rows);
|
header->found_rows(limit_found_rows);
|
||||||
header->result()->type= Query_cache_block::RESULT;
|
header->result()->type= Query_cache_block::RESULT;
|
||||||
|
|
||||||
/* Drop the writer. */
|
/* Drop the writer. */
|
||||||
header->writer(0);
|
header->writer(0);
|
||||||
thd->net.query_cache_query= 0;
|
query_cache_tls->first_query_block= NULL;
|
||||||
BLOCK_UNLOCK_WR(query_block);
|
BLOCK_UNLOCK_WR(query_block);
|
||||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
|
DBUG_EXECUTE("check_querycache", check_integrity(1););
|
||||||
|
|
||||||
}
|
}
|
||||||
query_cache.unlock();
|
|
||||||
|
unlock();
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,7 +1093,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
|
|||||||
Drop the writer; this will cancel any attempts to store
|
Drop the writer; this will cancel any attempts to store
|
||||||
the processed statement associated with this writer.
|
the processed statement associated with this writer.
|
||||||
*/
|
*/
|
||||||
query->writer()->query_cache_query= 0;
|
query->writer()->first_query_block= NULL;
|
||||||
query->writer(0);
|
query->writer(0);
|
||||||
refused++;
|
refused++;
|
||||||
}
|
}
|
||||||
@ -1268,8 +1287,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
double_linked_list_simple_include(query_block, &queries_blocks);
|
double_linked_list_simple_include(query_block, &queries_blocks);
|
||||||
inserts++;
|
inserts++;
|
||||||
queries_in_cache++;
|
queries_in_cache++;
|
||||||
net->query_cache_query= (uchar*) query_block;
|
thd->query_cache_tls.first_query_block= query_block;
|
||||||
header->writer(net);
|
header->writer(&thd->query_cache_tls);
|
||||||
header->tables_type(tables_type);
|
header->tables_type(tables_type);
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
@ -1325,7 +1344,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
{
|
{
|
||||||
ulonglong engine_data;
|
ulonglong engine_data;
|
||||||
Query_cache_query *query;
|
Query_cache_query *query;
|
||||||
Query_cache_block *first_result_block, *result_block;
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
Query_cache_block *first_result_block;
|
||||||
|
#endif
|
||||||
|
Query_cache_block *result_block;
|
||||||
Query_cache_block_table *block_table, *block_table_end;
|
Query_cache_block_table *block_table, *block_table_end;
|
||||||
ulong tot_length;
|
ulong tot_length;
|
||||||
Query_cache_query_flags flags;
|
Query_cache_query_flags flags;
|
||||||
@ -1396,12 +1418,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
if (query_cache_size == 0)
|
if (query_cache_size == 0)
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
|
|
||||||
/*
|
|
||||||
Check that we haven't forgot to reset the query cache variables;
|
|
||||||
make sure there are no attached query cache writer to this thread.
|
|
||||||
*/
|
|
||||||
DBUG_ASSERT(thd->net.query_cache_query == 0);
|
|
||||||
|
|
||||||
Query_cache_block *query_block;
|
Query_cache_block *query_block;
|
||||||
|
|
||||||
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
|
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
|
||||||
@ -1483,7 +1499,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
BLOCK_LOCK_RD(query_block);
|
BLOCK_LOCK_RD(query_block);
|
||||||
|
|
||||||
query = query_block->query();
|
query = query_block->query();
|
||||||
result_block= first_result_block= query->result();
|
result_block= query->result();
|
||||||
|
#ifndef EMBEDDED_LIBRARY
|
||||||
|
first_result_block= result_block;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
|
if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
|
||||||
{
|
{
|
||||||
@ -2261,7 +2280,7 @@ void Query_cache::free_query_internal(Query_cache_block *query_block)
|
|||||||
if (query->writer() != 0)
|
if (query->writer() != 0)
|
||||||
{
|
{
|
||||||
/* Tell MySQL that this query should not be cached anymore */
|
/* Tell MySQL that this query should not be cached anymore */
|
||||||
query->writer()->query_cache_query= 0;
|
query->writer()->first_query_block= NULL;
|
||||||
query->writer(0);
|
query->writer(0);
|
||||||
}
|
}
|
||||||
double_linked_list_exclude(query_block, &queries_blocks);
|
double_linked_list_exclude(query_block, &queries_blocks);
|
||||||
@ -3474,7 +3493,8 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE_COUNTER_TYPE
|
TABLE_COUNTER_TYPE
|
||||||
Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
|
Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,
|
||||||
|
LEX *lex,
|
||||||
TABLE_LIST *tables_used, uint8 *tables_type)
|
TABLE_LIST *tables_used, uint8 *tables_type)
|
||||||
{
|
{
|
||||||
TABLE_COUNTER_TYPE table_count;
|
TABLE_COUNTER_TYPE table_count;
|
||||||
@ -3773,10 +3793,10 @@ my_bool Query_cache::move_by_type(uchar **border,
|
|||||||
If someone is writing to this block, inform the writer that the block
|
If someone is writing to this block, inform the writer that the block
|
||||||
has been moved.
|
has been moved.
|
||||||
*/
|
*/
|
||||||
NET *net = new_block->query()->writer();
|
Query_cache_tls *query_cache_tls= new_block->query()->writer();
|
||||||
if (net != 0)
|
if (query_cache_tls != NULL)
|
||||||
{
|
{
|
||||||
net->query_cache_query= (uchar*) new_block;
|
query_cache_tls->first_query_block= new_block;
|
||||||
}
|
}
|
||||||
/* Fix hash to point at moved block */
|
/* Fix hash to point at moved block */
|
||||||
hash_replace(&queries, &record_idx, (uchar*) new_block);
|
hash_replace(&queries, &record_idx, (uchar*) new_block);
|
||||||
|
@ -64,6 +64,8 @@ struct Query_cache_table;
|
|||||||
struct Query_cache_query;
|
struct Query_cache_query;
|
||||||
struct Query_cache_result;
|
struct Query_cache_result;
|
||||||
class Query_cache;
|
class Query_cache;
|
||||||
|
struct Query_cache_tls;
|
||||||
|
struct st_lex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class represents a node in the linked chain of queries
|
This class represents a node in the linked chain of queries
|
||||||
@ -137,7 +139,7 @@ struct Query_cache_query
|
|||||||
ulonglong limit_found_rows;
|
ulonglong limit_found_rows;
|
||||||
rw_lock_t lock;
|
rw_lock_t lock;
|
||||||
Query_cache_block *res;
|
Query_cache_block *res;
|
||||||
NET *wri;
|
Query_cache_tls *wri;
|
||||||
ulong len;
|
ulong len;
|
||||||
uint8 tbls_type;
|
uint8 tbls_type;
|
||||||
unsigned int last_pkt_nr;
|
unsigned int last_pkt_nr;
|
||||||
@ -149,8 +151,8 @@ struct Query_cache_query
|
|||||||
inline void found_rows(ulonglong rows) { limit_found_rows= rows; }
|
inline void found_rows(ulonglong rows) { limit_found_rows= rows; }
|
||||||
inline Query_cache_block *result() { return res; }
|
inline Query_cache_block *result() { return res; }
|
||||||
inline void result(Query_cache_block *p) { res= p; }
|
inline void result(Query_cache_block *p) { res= p; }
|
||||||
inline NET *writer() { return wri; }
|
inline Query_cache_tls *writer() { return wri; }
|
||||||
inline void writer(NET *p) { wri= p; }
|
inline void writer(Query_cache_tls *p) { wri= p; }
|
||||||
inline uint8 tables_type() { return tbls_type; }
|
inline uint8 tables_type() { return tbls_type; }
|
||||||
inline void tables_type(uint8 type) { tbls_type= type; }
|
inline void tables_type(uint8 type) { tbls_type= type; }
|
||||||
inline ulong length() { return len; }
|
inline ulong length() { return len; }
|
||||||
@ -407,7 +409,8 @@ protected:
|
|||||||
If query is cacheable return number tables in query
|
If query is cacheable return number tables in query
|
||||||
(query without tables not cached)
|
(query without tables not cached)
|
||||||
*/
|
*/
|
||||||
TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
|
TABLE_COUNTER_TYPE is_cacheable(THD *thd, size_t query_len,
|
||||||
|
const char *query,
|
||||||
LEX *lex, TABLE_LIST *tables_used,
|
LEX *lex, TABLE_LIST *tables_used,
|
||||||
uint8 *tables_type);
|
uint8 *tables_type);
|
||||||
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
|
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
|
||||||
@ -462,10 +465,13 @@ protected:
|
|||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
friend void query_cache_init_query(NET *net);
|
void insert(Query_cache_tls *query_cache_tls,
|
||||||
friend void query_cache_insert(NET *net, const char *packet, ulong length);
|
const char *packet,
|
||||||
friend void query_cache_end_of_result(THD *thd);
|
ulong length,
|
||||||
friend void query_cache_abort(NET *net);
|
unsigned pkt_nr);
|
||||||
|
|
||||||
|
void end_of_result(THD *thd);
|
||||||
|
void abort(Query_cache_tls *query_cache_tls);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following functions are only used when debugging
|
The following functions are only used when debugging
|
||||||
@ -493,9 +499,4 @@ protected:
|
|||||||
|
|
||||||
extern Query_cache query_cache;
|
extern Query_cache query_cache;
|
||||||
extern TYPELIB query_cache_type_typelib;
|
extern TYPELIB query_cache_type_typelib;
|
||||||
void query_cache_init_query(NET *net);
|
|
||||||
void query_cache_insert(NET *net, const char *packet, ulong length);
|
|
||||||
void query_cache_end_of_result(THD *thd);
|
|
||||||
void query_cache_abort(NET *net);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -501,9 +501,6 @@ THD::THD()
|
|||||||
net.vio=0;
|
net.vio=0;
|
||||||
#endif
|
#endif
|
||||||
client_capabilities= 0; // minimalistic client
|
client_capabilities= 0; // minimalistic client
|
||||||
#ifdef HAVE_QUERY_CACHE
|
|
||||||
query_cache_init_query(&net); // If error on boot
|
|
||||||
#endif
|
|
||||||
ull=0;
|
ull=0;
|
||||||
system_thread= NON_SYSTEM_THREAD;
|
system_thread= NON_SYSTEM_THREAD;
|
||||||
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
|
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
|
||||||
@ -796,7 +793,7 @@ THD::raise_condition_no_handler(uint sql_errno,
|
|||||||
MYSQL_ERROR *cond= NULL;
|
MYSQL_ERROR *cond= NULL;
|
||||||
DBUG_ENTER("THD::raise_condition_no_handler");
|
DBUG_ENTER("THD::raise_condition_no_handler");
|
||||||
|
|
||||||
query_cache_abort(& net);
|
query_cache_abort(&query_cache_tls);
|
||||||
|
|
||||||
/* FIXME: broken special case */
|
/* FIXME: broken special case */
|
||||||
if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
|
if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
|
||||||
|
@ -315,6 +315,27 @@ typedef enum enum_diag_condition_item_name
|
|||||||
*/
|
*/
|
||||||
extern const LEX_STRING Diag_condition_item_names[];
|
extern const LEX_STRING Diag_condition_item_names[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query_cache_tls -- query cache thread local data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Query_cache_block;
|
||||||
|
|
||||||
|
struct Query_cache_tls
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
'first_query_block' should be accessed only via query cache
|
||||||
|
functions and methods to maintain proper locking.
|
||||||
|
*/
|
||||||
|
Query_cache_block *first_query_block;
|
||||||
|
void set_first_query_block(Query_cache_block *first_query_block_arg)
|
||||||
|
{
|
||||||
|
first_query_block= first_query_block_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Query_cache_tls() :first_query_block(NULL) {}
|
||||||
|
};
|
||||||
|
|
||||||
#include "sql_lex.h" /* Must be here */
|
#include "sql_lex.h" /* Must be here */
|
||||||
|
|
||||||
class Delayed_insert;
|
class Delayed_insert;
|
||||||
@ -1239,6 +1260,9 @@ public:
|
|||||||
fields then.
|
fields then.
|
||||||
*/
|
*/
|
||||||
struct st_mysql_stmt *current_stmt;
|
struct st_mysql_stmt *current_stmt;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_QUERY_CACHE
|
||||||
|
Query_cache_tls query_cache_tls;
|
||||||
#endif
|
#endif
|
||||||
NET net; // client connection descriptor
|
NET net; // client connection descriptor
|
||||||
Protocol *protocol; // Current protocol
|
Protocol *protocol; // Current protocol
|
||||||
|
@ -6026,7 +6026,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
|
|||||||
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
|
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
|
||||||
thd->is_fatal_error));
|
thd->is_fatal_error));
|
||||||
|
|
||||||
query_cache_abort(&thd->net);
|
query_cache_abort(&thd->query_cache_tls);
|
||||||
}
|
}
|
||||||
if (thd->lex->sphead)
|
if (thd->lex->sphead)
|
||||||
{
|
{
|
||||||
|
@ -9187,7 +9187,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||||||
thd->substitute_null_with_insert_id))
|
thd->substitute_null_with_insert_id))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache_abort(&thd->net);
|
query_cache_abort(&thd->query_cache_tls);
|
||||||
#endif
|
#endif
|
||||||
COND *new_cond;
|
COND *new_cond;
|
||||||
if ((new_cond= new Item_func_eq(args[0],
|
if ((new_cond= new Item_func_eq(args[0],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user