對(duì)于mysql的query_cache認(rèn)識(shí)的誤區(qū)
下面我們通過實(shí)驗(yàn)及源碼具體分析。首先,我們先試驗(yàn)一下:
首先,我們看一下mysql query_cache的狀態(tài):

首先,我們可以確認(rèn),mysql的query_cache功能是打開的。
其次,我們看一下狀態(tài):

因?yàn)檫@個(gè)db是新的db,所以hits,inset都為0,現(xiàn)在我們執(zhí)行一條select語(yǔ)句:
狀態(tài)變?yōu)椋?/P>

可以看到,執(zhí)行一條select后,現(xiàn)在的qcache狀態(tài)為,insert+1,這樣我們就可以推斷出,現(xiàn)在剛才那條select語(yǔ)句已經(jīng)加入了qcache中。那我們現(xiàn)在再將剛才那條sql前面加上空格,看看會(huì)怎樣呢?

請(qǐng)注意,這條sql,比剛才那條sql前面多了一個(gè)空格。
按照網(wǎng)上的理論,這條sql應(yīng)該會(huì)作為另一個(gè)鍵而插入另一個(gè)cache,不會(huì)復(fù)用先前的cache,但結(jié)果呢?

我們可以看到,hits變?yōu)榱?,而inserts根本沒變,這就說明了,這條在前面加了空格的query命中了沒有空格的query的結(jié)果集。從這,我們就可以得出結(jié)論,網(wǎng)上先前流傳的說法,是不嚴(yán)謹(jǐn)?shù)摹?/P>
那究竟是怎么回事呢?到底應(yīng)該如何呢?為什么前面有空格的會(huì)命中了沒有空格的query的結(jié)果集。其實(shí),這些我們可以通過源碼獲得答案。
翻看下mysql的源碼,我這翻看的是5.1的,在send_result_to_client(這個(gè)函數(shù)既是mysql調(diào)用query_cache的函數(shù))這個(gè)函數(shù)里面有這樣一段,這段代碼,、
/*
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;
}
是在檢驗(yàn)語(yǔ)句是否為select語(yǔ)句,重點(diǎn)是上面那段注釋。特別是括弧中的,pre-space is removed in dispatch_command,也就是說,在語(yǔ)句開始之前的多余的空格已經(jīng)被處理過了,在dispache_command這個(gè)函數(shù)中去掉了。
我們看下dispache_command這個(gè)方法,在這個(gè)方法里有這樣一段:
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;
在這里,會(huì)調(diào)用alloc_query方法,我們看下這個(gè)方法的內(nèi)容:
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;
}
這個(gè)方法在一開始就會(huì)對(duì)query進(jìn)行處理(代碼第4行),將開頭和末尾的garbage remove掉。
看到這里,我們基本已經(jīng)明了了,mysql會(huì)對(duì)輸入的query進(jìn)行預(yù)處理,將空格等東西給處理掉,所以不會(huì)開頭的空格不會(huì)影響到query_cache,因?yàn)閷?duì)mysql來說,就是一條query。
相關(guān)文章
MySQL時(shí)區(qū)差8小時(shí)的多種問題解決方法
mybatis將本地的數(shù)據(jù)傳入到mysql數(shù)據(jù)庫(kù)服務(wù)器的時(shí)候,服務(wù)器會(huì)對(duì)數(shù)據(jù)進(jìn)行檢測(cè),會(huì)把date類型的數(shù)據(jù)自動(dòng)轉(zhuǎn)換為mysql服務(wù)器所對(duì)應(yīng)的時(shí)區(qū),即0時(shí)區(qū),所以會(huì)相差8小時(shí),本文給大家介紹了MySQL時(shí)區(qū)差8小時(shí)的問題解決方法,需要的朋友可以參考下2024-01-01
Linux下安裝mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz
這篇文章主要介紹了Linux下安裝mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
MYSQL數(shù)據(jù)庫(kù)管理之權(quán)限管理解讀
這篇文章主要介紹了MYSQL數(shù)據(jù)庫(kù)管理之權(quán)限管理解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
10個(gè)mysql中select語(yǔ)句的簡(jiǎn)單用法
本篇文章主要講述的是MySQL SELECT句法的簡(jiǎn)單分析,我們大家都知道MySQL數(shù)據(jù)庫(kù)是我們大家經(jīng)常使用的數(shù)據(jù)庫(kù),其相關(guān)的應(yīng)用也是備受關(guān)注的,那么以下的文章主要是對(duì)MySQL SELECT句法的簡(jiǎn)單分析。2014-08-08
sql語(yǔ)句中l(wèi)ike的用法詳細(xì)解析
以下是對(duì)sql語(yǔ)句中l(wèi)ike的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-08-08

