一直以來,對于mysql的query_cache,在網上就流行著這樣的說法,對于mysql的query_cache鍵值就是mysql的query,所以,如果在query中有任何的不同,包括多了個空格,都會導致mysql認為是不同的查詢
其實,這一種說法是不完全正確的。首先第一點,mysql的query_cache的鍵值并不是簡單的query,而是query加databasename加flag。這個從源碼中就可以看出。在這里不做重點描述,后續可以針對于這一點再具體分析。重要的是第二點,是不是加了空格,mysql就認為是不同的查詢呢?實際上這個是要分情況而言的,要看這個空格加在哪。 如果空格是加在query之前,比如是在query的起始處加了空格,這樣是絲毫不影響query cache的結果的,mysql認為這是一條query, 而如果空格是在query中,那會影響query cache的結果,mysql會認為是不同的query。
下面我們通過實驗及源碼具體分析。首先,我們先試驗一下:
首先,我們看一下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 :==
‘
久久精品国产亚洲AV香蕉|
99久久国产热无码精品免费久久久久|
91精品国产高清91久久久久久|
日韩精品久久久肉伦网站|
狠狠88综合久久久久综合网
|
久久这里的只有是精品23|
人妻精品久久无码专区精东影业|
国产精品女同久久久久电影院|
精品综合久久久久久97超人|
亚洲国产成人久久综合野外|
色综合久久综合中文综合网|
久久婷婷色综合一区二区|
久久久久亚洲AV无码专区体验|
久久久九九有精品国产|
伊人久久久AV老熟妇色|
亚洲美日韩Av中文字幕无码久久久妻妇|
久久噜噜久久久精品66|
精品久久久久久久久中文字幕|
日日狠狠久久偷偷色综合免费|
国产成人综合久久精品尤物|
精品久久久久久久久午夜福利|
久久乐国产精品亚洲综合|
国产精品久久一区二区三区|
久久久久久综合网天天|
97精品依人久久久大香线蕉97|
99久久综合狠狠综合久久|
九九精品99久久久香蕉|
色偷偷偷久久伊人大杳蕉|
午夜精品久久久久久|
精品无码久久久久久久久久|
久久国产福利免费|
久久国产精品99久久久久久老狼|
亚洲va久久久噜噜噜久久狠狠|
亚州日韩精品专区久久久|
久久嫩草影院免费看夜色|
久久久久亚洲AV综合波多野结衣|
超级碰久久免费公开视频|
久久久综合九色合综国产|
天天综合久久久网|
国内精品久久久久久久亚洲|
久久91精品综合国产首页|