[玩转MySQL之四]MySQL缓存机制

一、前言

在当今的各种系统中,缓存是对系统性能优化的重要手段。MySQL Query Cache(MySQL查询缓存)在MySQL Server中是默认打开的,但是网上各种资料以及有经验的DBA都建议生产环境中把MySQL Query Cache关闭。按道理,MySQL Server默认打开,是鼓励用户使用缓存,但是大拿们却建议关闭此功能,并且国内各个云厂商提供的MySQL云服务中默认都是关闭这个功能,这是为什么?他们在使用中遇到了什么坑?本文将会从以下几方面来详解MySQL Query Cache。1.MySQL查询缓存是什么?2. MySQL缓存规则是什么?3. 如何配置和缓存MySQL缓存4. MySQL缓存的优缺点5. 生产要不要开启MySQL缓存

二、 MySQL查询缓存简介

MySQL查询缓存是MySQL中比较独特的一个缓存区域,用来缓存特定Query的整个结果集信息,且共享给所有客户端。为了提高完全相同的Query语句的响应速度,MySQL Server会对查询语句进行Hash计算后,把得到的hash值与Query查询的结果集对应存放在Query Cache中。当MySQL Server打开Query Cache之后,MySQL Server会对接收到的每一个SELECT 语句通过特定的Hash算法计算该Query的Hash值,然后通过该hashi值到Query Cache中去匹配。

  • 如果没有匹配,将这个hash值存放在一个hash链表中,并将Query的结果集存放到cache中,存放hashi值链表的每个hash节点存放了相应Quey结果集在cache中的地址,以及该query所涉及到一些table相关信息;
  • 如果通过hash值匹配到了一样的Query,则直接将cache中相应的Query结果集返回给客户端。

目前MySQL Query Cache只会cache select语句,其他类似show ,use的语句不会被cache MySQL 的每个Query Cache都是以SQL文本作为key来存储的,在应用Query Cache之前,SQL文本不会做任何处理。也就是说,两个SQL语句,只要相差哪怕一个字符(例如大小写不一样,多一个空格,多注释),那么这两个SQL将使用不同的Cache地址。如: 下面三条SQL将会被存储在三个不同的缓存里,虽然他们的结果都是一样的。select * FROM people where name='surfchen'; select * FROM people where /*hey~*/ name='surfchen'; SELECT * FROM people where name='surfchen';

三、MySQL缓存机制

MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行相同的SQL,服务器直接从缓存中取到结果,而不需要再去解析和执行SQL。如果表更改了,那么使用这个表的所有缓存查询将不再有效,查询缓存中值相关条目被清空。这里的更改指的是表中任何数据或是结构发生改变,包括INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些映射到改变了的表使用MERGE表的查询。显然,这对于频繁更新的表,查询缓存是不适合的,而对于一些不常改变数据且有大量相同SQL查询的表,查询缓存会节约很大的性能。

查询必须是完全相同(逐字节相同)才能够被认为是相同的。另外,同样的查询字符串由于其它原因可能认为是不同的。使用不同的数据库、不同的协议版本或者不同 默认字符集的查询被认为是不同的查询并且分别进行缓存。

需要注意的是MySQL Query Cache 是对大小写敏感的,因为Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以 任何SQL语句的改变重新cache. 

3.1 缓存规则

  • 开启了缓存,MySQL Server会自动将查询语句和结果集返回到内存,下次再查直接从内存中取;
  • 缓存的结果是通过sessions共享的,所以一个client查询的缓存结果,另一个client也可以使用
  • MySQL Query Cache内容为 select 的结果集, cache 使用完整的SQL字符串做 key, 并区分大小写,空格等。即两个SQL必须完全一致才会导致cache命中。即检查查询缓存时,MySQL Server不会对SQL做任何处理,它精确的使用客户端传来的查询,只要字符大小写或注释有点不同,查询缓存就认为是不同的查询;
  • prepared statement永远不会cache到结果,即使参数完全一样。在 5.1 之后会得到改善。
  • where条件中如包含任何一个不确定的函数将永远不会被cache, 比如current_date, now等。
  • date 之类的函数如果返回是以小时或天级别的,最好先算出来再传进去。
select * from foo where date1=current_date -- 不会被 cache
select * from foo where date1='2008-12-30' -- 被cache, 正确的做法

  • 太大的result set不会被cache (< query_cache_limit)
  • MySQL缓存在分库分表环境下是不起作用的
  • 执行SQL里有触发器,自定义函数时,MySQL缓存也是不起作用的

  • 9
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值