- 客户端发送一个查询给服务器。
- 服务器先检查查询缓存,如果命中,则直接返回缓存中的结果。如果没有没有命中,则进入下一阶段(解析器)。
- 服务器由解析器检查sql语法是否正确,然后由预处理器检查sql中的表和字段是否存在,最后由查询优器生成执行计划。这一步很耗资源。
- mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。
- 将结果返回给客户端。
MySQL客户端和服务器之间的通信
- 在mysql服务器和客户端之间的通信时“半双工”的。就是在同一时刻要么由客户向Mysql服务器发送数据,要么由MySQL服务器向客户端发送数据。就像来回抛球游戏,任何时候只有一个人能控制球,而且只有控制球的人才能将球抛出去(发送消息)。
- 当客户端从MySQL服务器获取数据时,看起来像像是客户端向MySQL服务器拉取数据,但实际上是MySQL服务器向客户端推送数据。客户端不断的接受从服务推送过来的数据,客户端也没有办法让服务器停下来。
- 大多数连接MySQL的库函数都可以获取全部的结果集并缓存到内存中。MySQL通常需要等到数据全部推送给客户端后才能释放这条语句查询所暂用的资源。
查询缓存
对执行计划的缓存
对于很多的数据库系统都能够缓存执行计划,对于完全相同的sql,可以使用已经已经存在的执行计划,从而跳过解析和生成执行计划的过程。
对完整的select查询结果的缓存
查询缓存的工作机制
Mysql 判断是否命中缓存的办法很简单,首先会将要缓存的结果放在引用表中,然后使用查询语句,数据库名称,客户端协议的版本等因素算出一个hash值,这个hash值与引用表中的结果相关联。如果在执行查询时,根据一些相关的条件算出的hash值能与引用表中的数据相关联,则表示查询命中通过have_query_cache服务器系统变量指示查询缓存是否可用:
mysql> SHOW VARIABLES LIKE ‘have_query_cache’;
变量名 值
Variable_name Value
have_query_cache YES
为了监视查询缓存性能,使用SHOW STATUS查看缓存状态变量:
mysql> SHOW STATUS LIKE ‘Qcache%’;
变量名 值
Qcache_free_blocks 36
Qcache_free_memory 138488
Qcache_hits 79570
Qcache_inserts 27087
Qcache_lowmem_prunes 3114
Qcache_not_cached 22989
Qcache_queries_in_cache 415
Qcache_total_blocks 912
查询缓存机制失效的场景
如果查询语句中包含一些不确定因素时(例如包含函数Current()),该查询不会被缓存,不确定因素主要包含以下情况。
引用了一些返回值不确定的函数
函数名 函数名 函数名 函数名
BENCHMARK() CONNECTION_ID() CURDATE() CURRENT_DATE()
CURRENT_TIME() CURRENT_TIMESTAMP() CURTIME() DATABASE()
带一个参数的ENCRYPT() FOUND_ROWS() GET_LOCK() LAST_INSERT_ID()
LOAD_FILE() MASTER_POS_WAIT() NOW() RAND()
RELEASE_LOCK() SYSDATE() 不带参数的UNIX_TIMESTAMP() USER()
引用自定义函数(UDFs)。
引用自定义变量
引用mysql系统数据库中的表。
引用临时表
引用存储函数
任何包含列级别权限的表
不使用任何表
下面方式中的任何一种:
查询缓存的额外的消耗
如果使用查询缓存,在进行读写操作时会带来额外的资源消耗,消耗主要体现在以下几个方面:
查询的时候会检查是否命中缓存,这个消耗相对较小
如果没有命中查询缓存,MYSQL会判断该查询是否可以被缓存,而且系统中还没有对应的缓存,则会将其结果写入查询缓存
如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。
对于InnoDB而言,事物的一些特性还会限制查询缓存的使用。当在事物A中修改了B表时,因为在事物提交之前,对B表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事物A提交之前是不可缓存的。如果A事物长时间运行,会严重影响查询缓存的命中率
查询缓存的空间不要设置的太大。
因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况。