MySQL的缓存机制

一、查询缓存

为什么MySQL8.0直接把查询缓存的功能删除了呢?
首先,查询缓存的效果取决于cache的命中率,只有命中cache的查询效果才能有改善,因此无法预测其性能。
其次,查询缓存的另一个大问题是它受到单个互斥锁的保护。在具有多个内核的服务器上,大量查询会导致大量的互斥锁争用。

1. 什么是查询缓存?

MySQL查询缓存即缓存查询数据的SQL文本及查询结果,用Key-Value的形式保存在服务器内存中。当查询命中缓存,MySQL会立刻返回结果,跳过了解析,优化和执行阶段。

2. 查询缓存的命中条件有哪些?

  • 首先你得确保开启了查询缓存。(手动狗头
  • MySQL将缓存存放在一个引用表(类似HashMap的数据结构)。通过一个哈希值索引,这个索引通过查询本身、当前查询的数据库、客户端协议、版本号等一些可能影响结果的信息计算得出。
  • 在判断命中前,MySQL不会解析SQl,首先使用SQL去查询缓存,SQL上有任何字符不同,如:空格、注释等都会导致缓存命中失败。
    4. 如果查询SQL中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL库中的系统表、其查询结果都不会被缓存。如:like now()current_date()函数等。

3. 缓存失效

查询缓存的失效非常频繁,在表结构或数据发生改变时,查询缓存中的数据不再有效,查询缓存值的相关条目将被清空。
insertupdatedeletetruncatealter tabledrop database都会导致缓存数据的失效。
注意:MySQL重启也会导致cache中的内容全部丢失。

4. 应用场景

对于频繁更新的表,查询缓存合适,查询缓存更加适用于“静态表”。

5. 查询缓存的弊端

  • 任何查询语句在开始之前都会经过缓存检查,即使这条SQL永远不会命中缓存。
  • 如果查询结果可以被缓存,那么执行完后,会将结果存入缓存,也会带来额外的系统消耗。
  • 写入或更新时,MySQL必须将对应表的所有缓存都设置失效。如果查询缓存很大或碎片很多时,这个操作可能给系统带来很大的系统消耗。
  • 如果Query_cache非常大,该表的查询结构又比较多,查询语句失效也慢,一个更新或是Insert就会很慢,这样看到的就是Update或是Insert怎么这么慢了。

二、缓存的相关参数

1. 查询缓存的参数:

show variables like "%query_cache%";

参数注释
query_cache_type是否打开缓存,可选参数有:OFF(0):关闭 ,不使用查询缓存。ON(1):总是打开 ,始终使用查询缓存。 DEMAND(2):按需使用查询缓存,只有明确写了SQL_CACHE的查询才会写入缓存
query_cache_size缓存使用的总内存空间大小,单位是字节,这个值必须是1024的整数倍;否则MySQL实际分配可能跟这个数值有偏差。语句:SET GLOBAL query_cache_size = 134217728;
query_cache_min_res_unit分配内存块时的最小单位大小
query_cache_limitMySQL能够缓存的最大结果,如果超出,则增加 Qcache_not_cached的值,并删除查询结果
query_cache_wlock_invalidate如果某个数据表被锁住,是否仍然从缓存中返回数据,默认是OFF,表示仍然可以返回
2. GLOBAL STATUS 中关于缓存的相关参数

show global status like "%qcache%";

参数注释
Qcache_free_blocks缓存池中空闲块的个数
Qcache_free_memory缓存中空闲内存量
Qcache_hits缓存命中次数
Qcache_inserts缓存写入次数
Qcache_lowmen_prunes因内存不足删除缓存次数
Qcache_not_cached查询未被缓存次数,例如查询结果超出缓存块大小,查询中包含可变函数等
Qcache_queries_in_cache当前缓存中缓存的SQL数量
Qcache_total_blocks缓存总block数

三、剖析缓存机制

MySQL在申请数据块时,首先要锁住空间块,然后找到合适大小的数据块,所以相对来说,分配内存块是一个非常慢的操作。
下面我们结合一张图来看看查询结果存储的过程

请添加图片描述
当有查询结果需要缓存时,先从空间A申请一个数据块B,然后将数据逐步写入数据块B,当数据块B空间用完时,向空间A申请数据块C,又向数据块C逐步写入,如此反复,直到查询结果全部写入完成,当数据块C还剩余部分空间D,这个剩余的空间D将被释放,并入到空闲空间A,而此时不会产生碎片,那么碎片是如何产生的呢?

从上图看出,当有一条查询结果需要缓存时,不会产生缓存碎片。
空间碎片的产生
现在我们假设一个场景,此时有两个查询结果需要缓存,且这两个查询结果都小于query_cache_min_res_unit设置的值,那么此时会有两个数据块正在写入数据。写入完成后,MySQL在回收剩余空间的时候,会发现在空间1和空间2中会有一个空隙(红色部分:由第一个空间块的剩余空隙产生),而空隙又小于query_cache_min_res_unit的值不能被再次使用,从而产生了碎片。
如下图所示:

请添加图片描述

从上图可以看出,SQL查询1的剩余空间小于query_cache_min_res_unit参数的值,所以无法再次使用,从而产生了碎片。SQL查询2的空间则并入到空闲空间当中,得到了释放。
注意:由于缓存失效,从而产生太小的数据块无法使用,也会产生碎片。
总结:
  1. 通过设置合理的query_cache_min_res_unit可以减少碎片的产生。
  2. 通过命令FLUSH QUERY CACHE 完成碎片整理。
  3. 使用RESET QUERY CACHE命令清空缓存。

相关内容

Kettle循环导出整库数据
https://blog.csdn.net/weixin_43932609/article/details/119610480
Kettle实现循环功能!!!
https://blog.csdn.net/weixin_43932609/article/details/119608497
ETL工具kettle的计算方式
https://blog.csdn.net/weixin_43932609/article/details/110371110
Kettle工具中Rest client组件的用法!!
https://blog.csdn.net/weixin_43932609/article/details/109988783
ETL工具kettle的Excel合并操作
https://blog.csdn.net/weixin_43932609/article/details/109326043
ETL工具kettle的插入更新操作
https://blog.csdn.net/weixin_43932609/article/details/109065366
ETL工具Kettle的发送邮件功能:
https://blog.csdn.net/weixin_43932609/article/details/108766325
ETL工具Kettle的列转行组件:
https://blog.csdn.net/weixin_43932609/article/details/108795244
ETL工具Kettle性能优化:
https://blog.csdn.net/weixin_43932609/article/details/108749304

=========================================================

人生得意须尽欢,莫使金樽空对月!
__一个热爱说唱的程序员。
今日份推荐音乐:王以太/艾热 AIR《别怕变老》

=========================================================

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像豆芽一样优秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值