mysql的缓存大致分为2种,一种是对执行计划的缓存,可以跳过sql解析和执行计划阶段。这中缓存只有在某些场景下可以实现。另外一种是缓存完整的select查询。这次主要说说mysql第二种缓存的机制。
先简单提一下第一种缓存形式。在这之前,先说说mysql的整个执行过程。
这是一个简单的mysql的执行过程的图片,mysql缓存的第一种方式就是可以跳过解析,预处理,执行计划等阶段,直接与用api和底层的存储引擎进行交互。这种一般用到的比较少。一般可以不考虑
现在重点说一下第二种方式
第二种方式是Mysql会用一个大小写不敏感的的检查看看sql语句是不是以sel开头,如果是,mysql将考虑将sql语句的结果缓存起来,这里只是考虑,并不是每个以sel开头的sql语句都会被缓存起来,mysql的底层缓存逻辑是很复杂的。
mysql是如何判断缓存命中的。mysql判断缓存命中的方法很简单,缓存存放到一个引用表中,通过一个哈希引用。每个哈希引用包括如下因素:查询本身、当前查询的数据库、客户端的协议版本等等。有2点需要说明一下:
1、 mysql不会只能的检查两条sql是不是一样,也就是说因为一个空格的不一样就会导致不能使用缓存。所以运用层的sql编码规则的统一是很重要的。有一点是意外,sql的大小写是不敏感的。sel和SEL是一样的,但这限于检查是不是可以缓存的时候,不影响最后的缓存结果,例如:select * from table 和 SELECT * FROM TABLE 是不一样的。
2、 当sql语句中含有一些不确定的数据时是不能被缓存的。例如:CURRENT_USER或者CONNECTION_ID()的查询。
在这里要提一下的是,经常会有人说“如果一个查询里面包含不确定的函数时,mysql就不会坚持缓存”。事实上这种说法是不正确的。这种语句mysql是不缓存。也就是说,mysql每次都会检查。只是包含不确定函数的sql语句压根缓存不起来,即使检查也是查不到的。
InnoDB的处理要复杂一些。InnoDB的事务会限制缓存的使用。当一个语句中在事务中修改了某个表,mysql会将这个表的所有的查询缓存都设置失效。而事实上,innodb的多版本特性会暂时将这个修改对其他事务屏蔽。在这个事务提交前,这个表的相关查询是无法被缓存的。所以所有在这个表上面的查询都只能在这个事务提交后才被缓存。因此,长时间的事务运行会导致缓存命中率的下降。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。