当前位置: 首页 > news >正文

MySQL小知识:为何从8.0开始取消了MySQL查询缓存

前言

缓存是对系统性能优化的重要手段。但是有经验的DBA都建议生产环境中把MySQL Query Cache关闭。MySQL8.0更是直接取消了查询缓存。
一键获取MySQL核心数据结构、底层实现原理、索引、事务、锁机制、MySQL性能优化案例、美团MySQL中间件等。

这是为什么?查询缓存在使用中遇到了什么坑?带着如下几个问题,我们正式进入本文。

  • 什么是MySQL查询缓存?
  • MySQL缓存规则。
  • MySQL缓存的优缺点。
  • MySQL缓存对性能的影响。

在这里插入图片描述

什么是查询缓存

MySQL体系架构
在这里插入图片描述
为了提高完全相同的Query语句的响应速度,MySQL Server会对查询语句进行Hash计算后,把得到的hash值与Query查询的结果集对应存放在Query Cache中。

如果没有匹配,将这个hash值存放在一个hash链表中,并将Query的结果集存放到cache中。
如果通过hash值匹配到了一样的Query,则直接将cache中相应的Query结果集返回给客户端。
目前MySQL Query Cache只会cache select语句,其他类似show ,use的语句不会被cache

MySQL缓存管理和配置

在这里插入图片描述

have_query_cache: 该MySQL Server是否支持Query Cache。

query_cache_limit: MySQL能够缓存的最大查询结果,查询结果大于该值时不会被缓存。

query_cache_min_res_unit: 查询缓存分配的最小块的大小(字节)。

当查询进行的时候,MySQL把查询结果保存在qurey cache中,但如果要保存的结果比较大,超过query_cache_min_res_unit的值 ,这时候mysql将一边检索结果,一边进行保存结果,也就是说,有可能在一次查询中,mysql要进行多次内存分配的操作。适当的调节query_cache_min_res_unit可以优化内存。

query_cache_size: 为缓存查询结果分配的内存的数量,单位是字节,且数值必须是1024的整数倍。默认值是0,即禁用查询缓存。

query_cache_type: 设置查询缓存类型,默认为ON。设置GLOBAL值可以设置后面的所有客户端连接的类型。客户端可以设置SESSION值以影响他们自己对查询缓存的使用。

下面的表显示了可能的值:
在这里插入图片描述

query_cache_wlock_invalidate:如果某个表被锁住,是否返回缓存中的数据,默认关闭,也是建议的。

MySQL缓存规则

MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行完全相同的SQL,服务器直接从缓存中取到结果,而不需要再去解析和执行SQL。

如果表中任何数据或是结构发生改变,包括INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,那么使用这个表的所有缓存查询将不再有效,查询缓存中值相关条目被清空。

显然,这对于频繁更新的表,查询缓存是不适合的。

缓存规则:

将查询语句和结果集返回到内存,下次再查直接从内存中取;
sessions共享,一个client查询的缓存结果,另一个client也可以使用;
SQL必须完全一致才会导致cache命中;
不确定的函数将永远不会被cache, 比如current_date, now等;
太大的result set不会被cache (< query_cache_limit);
MySQL缓存在分库分表环境下是不起作用的;
执行SQL里有触发器,自定义函数时,MySQL缓存也是不起作用的;
在表的结构或数据发生改变时,基于该表相关cache立即全部失效。

缓存机制中的内存管理

  • MySQL Query Cache 使用内存池技术,自己管理内存释放和分配,而不是通过操作系统。内存池使用的基本单位是变长的block,
    用来存储类型、大小、数据等信息;一个result
    set的cache通过链表把这些block串起来。block最短长度为query_cache_min_res_unit。

  • 当服务器启动的时候,会初始化缓存需要的内存,是一个完整的空闲块。当查询结果需要缓存的时候,先从空闲块中申请一个数据块为参数query_cache_min_res_unit配置的空间,即使缓存数据很小,申请数据块也是这个,因为查询开始返回结果的时候就分配空间,此时无法预知结果多大。

  • 分配内存块需要先锁住空间块,所以操作很慢,MySQL会尽量避免这个操作,选择尽可能小的内存块,如果不够,继续申请,如果存储完时有空余则释放多余的。

  • 但是如果并发的操作,余下的需要回收的空间很小,小于query_cache_min_res_unit,不能再次被使用,就会产生碎片。

查询缓存的优缺点

优点:

Query Cache的查询,发生在MySQL接收到客户端的查询请求、查询权限验证之后和查询SQL解析之前。

也就是说,当MySQL接收到客户端的查询SQL之后,仅仅只需要对其进行相应的权限验证之后,就会通过Query Cache来查找结果,甚至都不需要经过Optimizer模块进行执行计划的分析优化,更不需要发生任何存储引擎的交互。

由于Query Cache是基于内存的,直接从内存中返回相应的查询结果,因此减少了大量的磁盘I/O和CPU计算,导致效率非常高。

缺点:

MySQL会对每条接收到的SELECT类型的查询进行hash计算,然后查找这个查询的缓存结果是否存在。虽然hash计算和查找的效率已经足够高了,一条查询语句所带来的开销可以忽略,但一旦涉及到高并发,有成千上万条查询语句时,hash计算和查找所带来的开销就必须重视了。
Query Cache的失效问题。如果表的变更比较频繁,则会造成Query Cache的失效率非常高。表的变更不仅仅指表中的数据发生变化,还包括表结构或者索引的任何变化。
查询语句不同,但查询结果相同的查询都会被缓存,这样便会造成内存资源的过度消耗。查询语句的字符大小写、空格或者注释的不同,Query Cache都会认为是不同的查询(因为他们的hash值会不同)。
相关系统变量设置不合理会造成大量的内存碎片,这样便会导致Query Cache频繁清理内存。

对性能的影响

读查询开始之前必须检查是否命中缓存。
如果读查询可以缓存,那么执行完查询操作后,会查询结果和查询语句写入缓存。
当向某个表写入数据的时候,必须将这个表所有的缓存设置为失效,如果缓存空间很大,则消耗也会很大,可能使系统僵死一段时间,因为这个操作是靠全局锁操作来保护的。
对InnoDB表,当修改一个表时,设置了缓存失效,但是多版本特性会暂时将这修改对其他事务屏蔽,在这个事务提交之前,所有查询都无法使用缓存,直到这个事务被提交,所以长时间的事务,会大大降低查询缓存的命中。

生产如何设置MySQL Query Cache

MySQL中的Query Cache是一个适用较少情况的缓存机制。如果你的应用对数据库的更新很少,那么QC将会作用显著。比较典型的如博客系统,一般博客更新相对较慢,数据表相对稳定不变,这时候QC的作用会比较明显。

但是一个更新频繁系统。Query Cache缓存的作用是很微小的,如果应用层能够实现缓存,将可以忽略Query Cache的效果。所以,如果经常有更新的系统,想要获得较高tps的话,建议一开始就关闭Query Cache

查询缓存的替代方案MySQL查询缓存工作的原则是:执行查询最快的方式就是不去执行,但是查询仍然需要发送到服务器端,服务器也还需要做一点点工作,如果对于某些查询完全不需要与服务器通信效果会如何呢,这时客户端缓存可以很大程度上分担MySQL服务器的压力。

最后

在这里插入图片描述

👇🏻 添加 博主 获取图中PDF文档 👇🏻

相关文章:

  • python数据类型(1)
  • HTML+CSS网页设计期末课程大作业 【茶叶文化网站设计题材】web前端开发技术 web课程设计 网页规划与设计
  • 8年三届世界杯,8年前端开发,梅西一共踢没了我八千八
  • 第十四届蓝桥杯模拟赛(第二期)——C语言版
  • c语言:关键字(一)
  • 毕业设计 单片机多功能红外空调遥控器 - 嵌入式 物联网
  • Docker 讲解与基本操作
  • 《PyInstaller打包实战指南》第二十二节 单文件模式打包Playwright
  • RK3399平台开发系列讲解(内存篇)ARM64虚拟地址空间布局
  • jsp474基于视频图像的人脸识别算法研究mysql
  • Android -- 每日一问:两个 Fragment 之间如何进行通信 ?
  • 【html5期末大作业】基于HTML+CSS+JavaScript管理系统页面模板
  • 【DL】Windiws10系统下安装CUDA和CUDNN实践教程
  • 【基础算法】几种特殊数(素数、公约数、完全数、亲密数) C++实现
  • 数据存储,详细讲解
  • SegmentFault for Android 3.0 发布
  • Android 架构优化~MVP 架构改造
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java的Interrupt与线程中断
  • java中具有继承关系的类及其对象初始化顺序
  • Koa2 之文件上传下载
  • Linux后台研发超实用命令总结
  • mysql外键的使用
  • PermissionScope Swift4 兼容问题
  • scala基础语法(二)
  • tab.js分享及浏览器兼容性问题汇总
  • ubuntu 下nginx安装 并支持https协议
  • 安装python包到指定虚拟环境
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 设计模式(12)迭代器模式(讲解+应用)
  • 通过npm或yarn自动生成vue组件
  • 微信小程序设置上一页数据
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 正则表达式
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #数学建模# 线性规划问题的Matlab求解
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (16)Reactor的测试——响应式Spring的道法术器
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (pojstep1.1.2)2654(直叙式模拟)
  • (备忘)Java Map 遍历
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (实战篇)如何缓存数据
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET Framework杂记
  • .Net Redis的秒杀Dome和异步执行
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题