PmaControl logo PmaControl
  • 首页
  • PmaControl
    • AI智能代理 13个本地代理
    • 定价方案 Community、Cloud、On-Premise、Premium
    • 文档 指南、API、架构
    • 客户 28+企业
    • 常见问题 25个问题 / 7个类别
    数据库
    • MariaDB 30 篇文章
    • MySQL 10 篇文章
    • Galera Cluster 6 篇文章
    • MaxScale 3 篇文章
    • ProxySQL 2 篇文章
    • Amazon Aurora MySQL 0 篇文章
    • Azure Database 0 篇文章
    • ClickHouse 0 篇文章
    • GCP CloudSQL 0 篇文章
    • Percona Server 0 篇文章
    • SingleStore 0 篇文章
    • TiDB 0 篇文章
    • Vitess 0 篇文章
    解决方案
    • 全天候支持 MariaDB & MySQL紧急支持
    • Observabilité SQL 监控、告警、拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Sécurité & conformité 审计、GDPR、SOC2
    • Migration & upgrade 零停机、pt-osc、gh-ost
  • 定价方案
  • 资源
    • 文档 技术指南与API
    • 常见问题 25个常见问题
    • 客户评价 客户反馈与案例
    • 博客 文章与洞察
    • 路线图 即将推出的功能
    专业领域
    • Observabilité SQL 监控、告警、Dot3拓扑
    • Haute disponibilité 复制、故障转移、Galera
    • Sécurité & conformité 审计、GDPR、SOC2、ISO 27001
    • Disaster Recovery 备份、恢复、RPO/RTO
    • Performance & optimisation Digests、EXPLAIN、调优
    • Migration & upgrade 零停机、pt-osc
    快速链接
    • GitHub Wiki 26页 — 安装、引擎、插件
    • 源代码 GitHub官方仓库
    • 全天候支持 MariaDB & MySQL紧急支持
    • 预约演示 30分钟 — 真实架构
  • 全天候支持
  • 预约演示
预约演示
🇫🇷 FR Français 🇬🇧 EN English 🇵🇱 PL Polski 🇷🇺 RU Русский 🇨🇳 ZH 中文
← 返回博客

玩转 MariaDB:查询缓存篇

发布于 2025年6月30日 作者 Sylvain ARBAUDIE
mariadb query-cache performance tuning
分享 X LinkedIn Facebook Email PDF
玩转 MariaDB:查询缓存篇

查询缓存的概念

MariaDB / MySQL 查询缓存是内置于服务器中的一种机制,用于在内存中存储 SELECT 查询结果。当相同的查询再次提交时,服务器直接返回缓存结果而无需执行查询。这很简单、优雅,而且可能非常高效。

这里的关键词是"可能"。查询缓存是 MariaDB / MySQL 中最被误解和配置错误的功能之一。正确使用时,它可以将响应时间降低 10 倍。配置不当时,它可能摧毁性能。

三种模式

查询缓存有三种工作模式,由 query_cache_type 变量控制:

OFF (0)

查询缓存完全禁用。不缓存任何查询,不执行任何缓存检查。这是写密集型工作负载的最安全选项。

ON (1)

所有 SELECT 查询默认都会被缓存,除了用 SQL_NO_CACHE 提示标记的查询。这是最激进的模式。

-- 这个查询将被缓存
SELECT * FROM products WHERE category_id = 5;

-- 这个查询不会被缓存
SELECT SQL_NO_CACHE * FROM products WHERE category_id = 5;

ON DEMAND (2)

默认不缓存任何查询。只有明确用 SQL_CACHE 标记的查询才会被缓存。这是最可控的模式,通常也是最有效的。

-- 这个查询不会被缓存(默认行为)
SELECT * FROM products WHERE category_id = 5;

-- 这个查询会被缓存
SELECT SQL_CACHE * FROM products WHERE category_id = 5;

ON DEMAND 模式是我在大多数情况下推荐的。它迫使你思考哪些查询值得被缓存,而不是盲目缓存一切。

失效:阿喀琉斯之踵

查询缓存在对某张表执行写操作后,会使该表的所有缓存条目失效。不仅仅是受影响的行——而是整张表。

-- 假设 'products' 表有 1000 个 SELECT 被缓存
UPDATE products SET price = 19.99 WHERE product_id = 42;
-- → 'products' 的所有 1000 个缓存条目都被失效

这是一个粗暴但必要的机制,用以保证一致性。问题在于,对于频繁修改的表,缓存会不断被失效和重建,消耗的资源比没有缓存还多。

缓存大小设置

查询缓存大小由 query_cache_size 控制:

[mysqld]
query_cache_type = 2
query_cache_size = 64M
query_cache_limit = 2M
query_cache_min_res_unit = 2048
  • query_cache_size:缓存总大小。不要超过 256 MB——超过这个值,全局缓存互斥锁会成为瓶颈。
  • query_cache_limit:单个结果的最大大小。更大的结果不会被缓存。
  • query_cache_min_res_unit:分配块大小。对于小结果减小此值可以降低碎片化。

监控缓存

Qcache_* 状态变量对于评估效果至关重要:

SHOW GLOBAL STATUS LIKE 'Qcache%';

关键指标:

变量 描述
Qcache_hits 从缓存提供服务的查询数
Qcache_inserts 添加到缓存的查询数
Qcache_not_cached 未被缓存的查询(过大、提示等)
Qcache_lowmem_prunes 因内存不足而被淘汰的条目数
Qcache_free_memory 缓存中的可用内存
Qcache_total_blocks 分配的块总数
Qcache_free_blocks 空闲块(高 = 碎片化)

效率比率

最重要的比率是命中率:

命中率 = Qcache_hits / (Qcache_hits + Com_select) * 100

解读:

  • > 40%:缓存有效,值得保持启用
  • 20-40%:灰色地带,需要逐案评估
  • < 20%:缓存无效,考虑禁用

第二个重要比率是淘汰率:

淘汰率 = Qcache_lowmem_prunes / Qcache_inserts * 100

如果此比率超过 10%,缓存太小——增大 query_cache_size 或减少缓存内容。

并发陷阱

查询缓存使用全局互斥锁。这意味着同一时间只有一个线程可以读取或写入缓存。在有 100 个并发连接的服务器上,这个互斥锁会成为严重的瓶颈。

这就是为什么 MySQL 8.0 完全移除了查询缓存。Oracle 团队认为在现代工作负载(高并发、频繁写入)中,互斥锁的开销超过了缓存的收益。

MariaDB 选择保留它,理由是它对特定使用场景仍然有用(读密集型负载、低并发、很少修改的表)。

查询缓存与 Galera:艰难的组合

在 Galera 集群中使用查询缓存是有问题的。Galera 将写操作复制到所有节点,但查询缓存对每个节点来说是本地的。结果是:

  1. 节点 A 接收一个 SELECT 并缓存结果
  2. 节点 B 通过 Galera 复制接收一个 UPDATE
  3. 节点 A 的缓存不会被失效——它不知道数据已经改变
  4. 节点 A 上的下一个 SELECT 返回过期数据

在 Galera 中安全使用查询缓存的唯一方法是设置 wsrep_causal_reads = ON,它会在每次读取前强制执行一致性检查。但这在很大程度上抵消了缓存的收益。

替代方案:MaxScale 缓存过滤器

对于需要分布式查询缓存的架构,MaxScale 缓存过滤器是更好的方案:

[query-cache]
type = filter
module = cache
storage = storage_inmemory
ttl = 10s
max_size = 256Mi

MaxScale 缓存是集中式的(在代理层),这消除了 Galera 节点之间的不一致问题。此外,MaxScale 可以基于查询类型智能地失效缓存,而不仅仅是基于被修改的表。

何时启用查询缓存

查询缓存在以下情况下是适用的:

  • 工作负载以读为主(> 80% SELECT)
  • 表很少被修改(配置表、参考数据)
  • 并发程度中等(< 50 个并发连接)
  • 相同的查询被频繁重复(有缓存未命中的 Web 应用)
  • 你在单机服务器上,不是 Galera 集群

查询缓存在以下情况下不适用:

  • 工作负载是读写混合的
  • 表频繁被修改(事务表)
  • 并发度高(全局互斥锁)
  • 你在 Galera 集群上(缓存不一致)

结论

MariaDB 的查询缓存是一个强大但精细的工具。带 SQL_CACHE 提示的 ON DEMAND 模式提供了最佳控制。通过 Qcache_* 变量进行监控对于评估效果至关重要。对于分布式架构,MaxScale 缓存过滤器通常是更好的选择。

与任何性能工具一样,关键在于度量。启用、监控、调整。如果命中率始终低于 20%,就禁用它并继续前进。


本文最初发表于 Medium。

分享 X LinkedIn Facebook Email PDF
← 返回博客

评论 (0)

暂无评论。

发表评论

PmaControl
+33 6 63 28 27 47 contact@pmacontrol.com
法律声明 GitHub 联系我们
不要等到故障发生才了解您的架构。 © 2014-2026 PmaControl — 68Koncept