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

MySQL中的缓存机制

        了解工具特性的目的是为了更好的去运用,其中的设计思想也可以借鉴~

先看总结:

缓存类型MySQL 5.7 及之前MySQL 8.0作用是否推荐
​查询缓存(Query Cache)​✅ 支持(默认开启)❌ ​​已移除​缓存 SELECT 查询结果​不推荐(MySQL 8.0 移除)​
​InnoDB Buffer Pool​✅ 核心缓存✅ 核心缓存缓存表数据 & 索引,减少磁盘 I/O​✅ 强烈推荐(调优关键)​
​文件系统缓存(OS Cache)​✅ 操作系统缓存✅ 操作系统缓存操作系统缓存磁盘数据​自动生效,无需配置​
​应用层缓存(Redis)​❌ 不属于 MySQL❌ 不属于 MySQL缓存热点数据(如用户信息)​✅ 推荐(补充方案)​

        MySQL ​​的缓存机制​​,在不同版本和场景下有所不同​​,主要包括查询缓存(Query Cache,MySQL 5.7 及之前)、InnoDB Buffer Pool(缓冲池)、以及 MySQL 8.0 后的优化​​。

​​1. MySQL 查询缓存(Query Cache,MySQL 5.7 及之前)​​

​​(1)什么是查询缓存?​​

  • ​​MySQL 5.7 及更早版本​​提供了一个 ​​查询缓存(Query Cache)​​,它会 ​​缓存 SELECT 查询的结果集​​。
  • ​​当相同的 SQL 语句再次执行时,MySQL 可以直接从缓存返回结果,而不需要重新查询磁盘​​,从而提高查询速度。

​​(2)查询缓存的工作方式​​

  • ​​缓存的是完整的 SELECT 查询及其结果​​(包括表数据)。
  • ​​只有完全相同的 SQL(包括大小写、空格、参数)才会命中缓存​​。
  • ​​如果表数据发生变化(INSERT/UPDATE/DELETE),相关查询缓存会被自动失效​​。

​​(3)查询缓存的配置​​

  • ​​启用查询缓存​​(MySQL 5.7 默认开启,但 MySQL 8.0 移除了它):
    SHOW VARIABLES LIKE 'query_cache%';
    • query_cache_type:是否启用(ON/OFF/DEMAND)。
    • query_cache_size:缓存大小(默认 1MB,建议 0 或适当大小)。

​​(4)查询缓存的缺点​​

 ​​适用场景有限​​:

  • ​​只缓存 SELECT 查询,不缓存 INSERT/UPDATE/DELETE​​。
  • ​​表数据一旦变化,相关缓存全部失效​​(导致缓存命中率低)。
  • ​​高并发写入场景下,查询缓存可能成为性能瓶颈​​(因为要检查缓存一致性)。
  • ​​缓存粒度太粗​​(整个查询结果缓存,而不是部分数据)。

 ​​MySQL 8.0 已移除查询缓存​​(query_cache_type 参数不存在):

  • ​​官方认为查询缓存在现代高并发、高写入场景下收益不高,反而增加维护成本​​。

如何关闭查询缓存(5.7版本)?

永久关闭(修改配置文件,重启 MySQL 生效)​​

要 ​​永久关闭查询缓存​​,需要修改 MySQL 的配置文件(my.cnf或 my.ini),然后 ​​重启 MySQL 服务​​。

​​(1) 找到 MySQL 配置文件​​
  • ​​Linux​​:通常位于 /etc/my.cnf或 /etc/mysql/my.cnf

  • ​​Windows​​:通常位于 MySQL 安装目录 / my.ini

​​(2) 修改配置文件​​

在 [mysqld]部分添加或修改以下参数:

[mysqld] query_cache_type = 0 # 或 OFF(完全禁用查询缓存) query_cache_size = 0 # 缓存大小设为 0(确保禁用)

​​说明​​:

  • ​​query_cache_type = 0或 OFF​​:禁用查询缓存。

  • ​​query_cache_size = 0​​:确保查询缓存内存分配为 0。

​​(3) 重启 MySQL 服务​​
  • ​​Linux​​:

    sudo systemctl restart mysql # 或 sudo service mysql restart

  • ​​Windows​​:

    • 打开 ​​服务管理器(Services.msc)​​,找到 ​​MySQL​​ 服务,右键 ​​重启​​。

​​(4) 验证是否关闭​​

登录 MySQL,执行:

SHOW VARIABLES LIKE 'query_cache%';


​​2. InnoDB 缓冲池(Buffer Pool,MySQL 5.7 & 8.0 核心缓存)​​

​​(1)什么是 Buffer Pool?​​

  • ​​InnoDB 存储引擎的核心缓存机制​​,用于 ​​缓存表数据和索引数据​​,减少磁盘 I/O。
  • ​​它是 MySQL 最重要的缓存,直接影响性能​​。

​​(2)Buffer Pool 的作用​​

 ​​缓存数据页(Data Pages)​​:

  • 当查询访问表数据时,InnoDB 会先检查 ​​Buffer Pool​​ 是否有该数据页(如 SELECT * FROM users WHERE id=1)。
  • ​​如果数据在 Buffer Pool 中(缓存命中),直接返回,避免磁盘读取​​。
  • ​​如果不在 Buffer Pool 中(缓存未命中),则从磁盘加载到 Buffer Pool​​。

 ​​缓存索引页(Index Pages)​​:

  • ​​B+ 树索引​​ 也会被缓存在 Buffer Pool 中,加速查询。

 ​​支持预读(Read-Ahead)和脏页刷新(Dirty Page Flush)​​:

  • ​​预读​​:预测可能访问的数据页,提前加载到 Buffer Pool。
  • ​​脏页​​:修改后的数据页会先在 Buffer Pool 中缓存,再异步刷回磁盘。

​​(3)Buffer Pool 的配置​​

  • ​​查看 Buffer Pool 大小​​:

    SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
    • ​​默认值​​:通常为 ​​128MB~1GB​​(取决于服务器内存)。
    • ​​推荐设置​​:​​70%~80% 的可用物理内存​​(如果是纯 MySQL 服务器)。
  • ​​调整 Buffer Pool​​:

    SET GLOBAL innodb_buffer_pool_size = 4G; -- 视服务器内存而定

​​(4)Buffer Pool 的监控​​

SHOW ENGINE INNODB STATUS\G
  • 查看 ​​Buffer Pool 命中率​​(BUFFER POOL AND MEMORY 部分):
    • ​​理想命中率 > 95%​​(表示大部分查询从内存读取,而不是磁盘)。

​​3. MySQL 8.0 的缓存优化​​

​​(1)移除了查询缓存(Query Cache)​​

  • ​​MySQL 8.0 彻底删除了 query_cache 相关功能​​(因为高并发写入场景下性能不佳)。
  • ​​官方推荐依赖 InnoDB Buffer Pool 和应用层缓存(如 Redis)​​。

​​(2)优化了 InnoDB Buffer Pool​​

  • ​​支持多个 Buffer Pool 实例​​(减少锁竞争):
    SET GLOBAL innodb_buffer_pool_instances = 4; -- 建议 4~8 个(视 CPU 核心数)
  • ​​更智能的预读和脏页管理​​。

​​(3)其他缓存优化​​

  • ​​自适应哈希索引(Adaptive Hash Index)​​:
    • InnoDB 会自动为频繁访问的索引页构建 ​​内存哈希索引​​,加速查找。
  • ​​文件系统缓存(OS Cache)​​:
    • 即使 MySQL 缓存未命中,操作系统(如 Linux)也会缓存磁盘数据(Page Cache)。

​​4. 应用层缓存(扩展方案)​​

如果 ​​MySQL 缓存(Buffer Pool)仍然不够快​​,可以考虑:

​​(1)Redis / Memcached​​

  • ​​缓存热点数据​​(如用户信息、商品详情),减少 MySQL 查询。
  • ​​比 MySQL 查询缓存更灵活​​(可以缓存任意数据,而不仅是 SQL 结果)。

​​(2)本地缓存(如 Caffeine、Guava Cache)​​

  • ​​Java 应用可以缓存部分数据​​,减少数据库访问。

注意缓存一致性问题!!


​​5. 总结:MySQL 缓存机制对比​​

缓存类型MySQL 5.7 及之前MySQL 8.0作用是否推荐
​​查询缓存(Query Cache)​​✅ 支持(默认开启)❌ ​​已移除​​缓存 SELECT 查询结果​​不推荐(MySQL 8.0 移除)​​
​​InnoDB Buffer Pool​​✅ 核心缓存✅ 核心缓存缓存表数据 & 索引,减少磁盘 I/O​​✅ 强烈推荐(调优关键)​​
​​文件系统缓存(OS Cache)​​✅ 操作系统缓存✅ 操作系统缓存操作系统缓存磁盘数据​​自动生效,无需配置​​
​​应用层缓存(Redis)​​❌ 不属于 MySQL❌ 不属于 MySQL缓存热点数据(如用户信息)​​✅ 推荐(补充方案)​​

​​6. 实践​​

​​(1)MySQL 5.7 及之前​​

  • ​​查询缓存(Query Cache)​​:​​不建议依赖​​(命中率通常低,高并发写入时性能差)。
  • ​​InnoDB Buffer Pool​​:​​必须调优​​(innodb_buffer_pool_size 建议设为 70%~80% 物理内存)。

​​(2)MySQL 8.0​​

  • ​​查询缓存已移除​​,​​依赖 InnoDB Buffer Pool​​(调优 innodb_buffer_pool_size 和 innodb_buffer_pool_instances)。
  • ​​结合 Redis / 应用层缓存​​ 处理热点数据。

​​(3)通用优化建议​​

  1. ​​优先优化 SQL 和索引​​(比缓存更重要)。
  2. ​​调大 innodb_buffer_pool_size​​(减少磁盘 I/O)。
  3. ​​监控 Buffer Pool 命中率​​(目标 > 95%)。
  4. ​​高并发场景考虑 Redis 缓存​​(替代 MySQL 查询缓存)。

​​结论​​

  • ​​MySQL 有缓存机制​​,但 ​​查询缓存(Query Cache)在 MySQL 8.0 已移除​​,不再推荐使用。
  • ​​InnoDB Buffer Pool 是 MySQL 最重要的缓存​​(缓存表数据和索引),​​必须合理配置​​。
  • ​​应用层缓存(如 Redis)是更好的补充方案​​,适用于热点数据加速。

    ​​

    扩展

            问题一:通过什么条件判断 Buffer Pool 中是否存在所需的数据页?

            在 MySQL 的 InnoDB 存储引擎中,判断缓冲池(Buffer Pool)中是否存在所需的数据页是通过一个称为页面哈希表(page hash table)的结构来实现。下面是具体的过程和机制:

    缓冲池与页面哈希表

    1. 缓冲池(Buffer Pool):这是 InnoDB 用于缓存从磁盘读取的数据页和索引页的主要内存区域。它帮助减少从磁盘读取数据的频率,从而提高查询性能。

    2. 页面哈希表:为了快速查找缓冲池中的数据页,InnoDB 维护了一个页面哈希表。这个哈希表存储了每个数据页的元数据信息,包括空间 ID(space ID)、页码(page number),以及指向实际数据页在缓冲池中位置的指针。

    查找过程

    当 MySQL 需要访问某个特定的数据页时,它会根据以下步骤进行查找:

    1. 计算哈希值:MySQL 使用空间 ID 和页码作为键,通过哈希函数计算出对应的哈希值。这个哈希值将用于在页面哈希表中定位可能包含所需数据页的位置。

    2. 查找哈希表:使用计算得到的哈希值,在页面哈希表中查找是否存在匹配的空间 ID 和页码组合。如果找到了匹配项,则说明所需的页面已经在缓冲池中存在;否则,表示该页面尚未被加载到缓冲池中。

    3. 处理未命中情况:如果在页面哈希表中没有找到相应的条目,意味着需要从磁盘加载该页面到缓冲池中。此时,MySQL 会执行一次 I/O 操作,将对应的数据页从磁盘读入缓冲池,并更新页面哈希表以反映这一变化。

    4. 返回结果:一旦确定了页面位于缓冲池中(无论是之前就已经存在还是刚刚加载进来的),MySQL 就可以直接访问该页面的内容,而无需再次访问磁盘。

    关键点

    • 空间 ID 和页码:这两个参数共同唯一标识了一个数据页。空间 ID 对应于数据库表所在的表空间,而页码则是该表空间内的偏移量。
    • 锁机制:为了保证并发环境下对缓冲池的安全访问,InnoDB 在管理缓冲池时采用了适当的锁机制。例如,在插入或删除页面哈希表条目时可能会加锁,防止多个线程同时修改相同的资源导致不一致问题。
    http://www.lryc.cn/news/619766.html

    相关文章:

  1. 如何在VS里使用MySQL提供的mysql Connector/C++的debug版本
  2. 如何把ubuntu 22.04下安装的mysql 8 的 数据目录迁移到另一个磁盘目录
  3. 设计模式笔记_行为型_策略模式
  4. OpenJDK 17 源码 安全点轮询的信号处理流程
  5. 资源查看-lspci命令
  6. 如何准备一场技术演讲
  7. 各种排序算法(二)
  8. 磁悬浮轴承转子设计避坑指南:深度解析核心要点与高可靠性策略
  9. 基于js和html的点名应用
  10. 【电气】NPN与PNP
  11. B系列树详细讲解
  12. 16-docker的容器监控方案-prometheus实战篇
  13. Python 类元编程(导入时和运行时比较)
  14. Windows也能用!Claude Code硬核指南
  15. [激光原理与应用-259]:理论 - 几何光学 - 平面镜的反射、平面透镜的折射、平面镜的反射成像、平面透镜的成像的规律
  16. 网刻软件iVentoy软件使用方法
  17. @进程管理工具 - Glances工具详细指南
  18. Django REST Framework视图
  19. Java 大视界 -- Java 大数据机器学习模型在金融资产配置优化与风险收益平衡中的应用(395)
  20. 解惑rust中的 Send/Sync(译)
  21. 基于Java的Markdown转Word工具(标题、段落、表格、Echarts图等)
  22. 18.10 SQuAD数据集实战:5步高效获取与预处理,BERT微调避坑指南
  23. 实战多屏Wallpaper壁纸显示及出现黑屏问题bug分析-学员作业
  24. HTML <iframe> 标签 如何把html写入iframe标签
  25. 版图设计学习2_掌握PDK中的层定义(工艺文档精读)
  26. Spring Boot 集成 机器人指令中枢ROS2工业机械臂控制网关
  27. 如何在 Spring Boot 中设计和返回树形结构的组织和部门信息
  28. 大致计算服务器磁盘使用情况脚本
  29. GNhao/GN号,海外SIM号怎么获取的步骤指南
  30. npm install 的作用