0

0

对于mysql的query_cache认识的误区

高洛峰

高洛峰

发布时间:2016-12-22 15:30:27

|

1205人浏览过

|

来源于php中文网

原创

其实,这一种说法是不完全正确的。首先第一点,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认识的误区

首先,我们可以确认,mysql的query_cache功能是打开的。

其次,我们看一下状态:

对于mysql的query_cache认识的误区

因为这个db是新的db,所以hits,inset都为0,现在我们执行一条select语句:

状态变为:

对于mysql的query_cache认识的误区

可以看到,执行一条select后,现在的qcache状态为,insert+1,这样我们就可以推断出,现在刚才那条select语句已经加入了qcache中。那我们现在再将刚才那条sql前面加上空格,看看会怎样呢?

对于mysql的query_cache认识的误区

请注意,这条sql,比刚才那条sql前面多了一个空格。

医院网站系统
医院网站系统

HTML医院网站系统基于PHP+MYSQL开发,在文章内容网站的基础上,预设了医院概况、新闻动态、环境设备、名医荟萃、专科介绍、就医指南、专家门诊值班表、网上挂号、医疗保健知识、在线咨询等医院网站常用的栏目和测试数据,采用适合医院网站的专用模版,增强了系统的针对性和易用性。系统具有文章、图文、下载、社区、表单、用户等基本系统模块和一系列网站辅助功能,用户也可根据自身特点任意创建和修改栏目,适合创建

下载

按照网上的理论,这条sql应该会作为另一个键而插入另一个cache,不会复用先前的cache,但结果呢?

对于mysql的query_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 :== 
 The input statement(s) 
'\0' Terminating null char (1 byte) 
 Length of following current database name (size_t) 
 Name of current database 
 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。

更多对于mysql的query_cache认识的误区相关文章请关注PHP中文网!

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java学习网站推荐汇总
java学习网站推荐汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.08

java学习网站汇总
java学习网站汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.01.08

正则表达式 删除
正则表达式 删除

本专题整合了正则表达式删除教程大全,阅读专题下面的文章了解更多详细教程。

1

2026.01.08

java 元空间 永久代
java 元空间 永久代

本专题整合了java中元空间和永久代的区别,阅读专题下面的文章了解更多详细内容。

2

2026.01.08

java 永久代和元空间
java 永久代和元空间

本专题整合了java中元空间和永久代的区别,阅读专题下面的文章了解更多详细内容。

0

2026.01.08

java成品网站源码资源大全
java成品网站源码资源大全

本专题整合了java成品网站源码相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.01.08

java过滤器教程大全
java过滤器教程大全

本专题整合了java过滤器相关教程,阅读专题下面的文章了解更多详细内容。

4

2026.01.08

作业帮网页版入口地址大全
作业帮网页版入口地址大全

本专题整合了作业帮网页版地址整理,阅读专题下面的文章了解更多详细内容。

3

2026.01.08

学习通网页版入口地址大全
学习通网页版入口地址大全

本专题整合了学生通网页版入口相关整理,阅读专题下面的文章了解更多详细内容。

6

2026.01.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

相关下载

更多

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号