關於mysql的query_cache熟悉的誤區。本站提示廣大學習愛好者:(關於mysql的query_cache熟悉的誤區)文章只能為提供參考,不一定能成為您想要的結果。以下是關於mysql的query_cache熟悉的誤區正文
上面我們經由過程試驗及源碼詳細剖析。起首,我們先實驗一下:
起首,我們看一下mysql query_cache的狀況:
起首,我們可以確認,mysql的query_cache功效是翻開的。
其次,我們看一下狀況:
由於這個db是新的db,所以hits,inset都為0,如今我們履行一條select語句:
狀況變成:
可以看到,履行一條select後,如今的qcache狀況為,insert+1,如許我們便可以揣摸出,如今適才那條select語句曾經參加了qcache中。那我們如今再將適才那條sql後面加上空格,看看會如何呢?
請留意,這條sql,比適才那條sql後面多了一個空格。
依照網上的實際,這條sql應當會作為另外一個鍵而拔出另外一個cache,不會復用先前的cache,但成果呢?
我們可以看到,hits變成了1,而inserts基本沒變,這就解釋了,這條在後面加了空格的query射中了沒有空格的query的成果集。從這,我們便可以得出結論,網上先前傳播的說法,是不嚴謹的。
那畢竟是怎樣回事呢?究竟應當若何呢?為何後面有空格的會射中了沒有空格的query的成果集。其實,這些我們可以經由過程源碼取得謎底。
翻看下mysql的源碼,我這翻看的是5.1的,在send_result_to_client(這個函數既是mysql挪用query_cache的函數)這個函數外面有如許一段,這段代碼,、
/*
Test if the query is a SELECT
(pre-space is removed in dispatch_command).
First '/' looks like comment before command it is not
frequently appeared in real life, consequently we can
check all such queries, too.
*/
if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
sql[i] != '/')
{
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
}
是在磨練語句能否為select語句,重點是下面那段正文。特殊是括弧中的,pre-space is removed in dispatch_command,也就是說,在語句開端之前的過剩的空格曾經被處置過了,在dispache_command這個函數中去失落了。
我們看下dispache_command這個辦法,在這個辦法裡有如許一段:
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query() + thd->query_length();
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
const char* end_of_stmt= NULL;
在這裡,會挪用alloc_query辦法,我們看下這個辦法的內容:
bool alloc_query(THD *thd, const char *packet, uint packet_length)
{
char *query;
/* Remove garbage at start and end of query */
while (packet_length > 0 && my_isspace(thd->charset(), packet[0]))
{
packet++;
packet_length--;
}
const char *pos= packet + packet_length; // Point at end null
while (packet_length > 0 &&
(pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
{
pos--;
packet_length--;
}
/* We must allocate some extra memory for query cache
The query buffer layout is:
buffer :==
<statement> The input statement(s)
'\0' Terminating null char (1 byte)
<length> Length of following current database name (size_t)
<db_name> Name of current database
<flags> Flags struct
*/
if (! (query= (char*) thd->memdup_w_gap(packet,
packet_length,
1 + sizeof(size_t) + thd->db_length +
QUERY_CACHE_FLAGS_SIZE)))
return TRUE;
query[packet_length]= '\0';
/*
Space to hold the name of the current database is allocated. We
also store this length, in case current database is changed during
execution. We might need to reallocate the 'query' buffer
*/
char *len_pos = (query + packet_length + 1);
memcpy(len_pos, (char *) &thd->db_length, sizeof(size_t));
thd->set_query(query, packet_length);
/* Reclaim some memory */
thd->packet.shrink(thd->variables.net_buffer_length);
thd->convert_buffer.shrink(thd->variables.net_buffer_length);
return FALSE;
}
這個辦法在一開端就會對query停止處置(代碼第4行),將開首和末尾的garbage remove失落。
看到這裡,我們根本曾經清楚明了了,mysql會對輸出的query停止預處置,將空格等器械給處置失落,所以不會開首的空格不會影響到query_cache,由於對mysql來講,就是一條query。