【问题标题】:Query is cached on local setup, but never on server?查询缓存在本地设置上,但从不在服务器上?
【发布时间】:2012-12-03 21:47:12
【问题描述】:

我在一个项目的查询缓存方面遇到了很多麻烦:我正在运行 MySQL 的 Percona 风格,在我的本地开发机器上和生产服务器上的版本相同。现在,启用查询缓存在我的本地机器上给了我很好的结果:几乎所有应该缓存的查询都有效。

现在,生产服务器上没有缓存完全相同的查询。一切都一模一样; mysql 变量、数据库内容、代码库、登录用户……但在生产环境中,只有少数查询被缓存,最重要的查询都被跳过了。而且我不知道为什么:-)

因此,在寻找解决方案时,我正在使用以下查询,用于从主题表中选择最新的 3 个主题:(这是最“重”的查询,也是我绝对想要缓存的查询! )

SELECT `topic`.* FROM `topics` AS `topic` 
LEFT OUTER  JOIN `topics` AS `topic_helper` 
 ON (`topic`.`id` = `topic_helper`.`id` 
      AND `topic_helper`.`created_on` < `topic`.`created_on`) 
GROUP BY `topic`.`id` HAVING COUNT(*) < 3 
ORDER BY `topic`.`created_on` DESC;

所以,首先,SHOW VARIABLES LIKE '%query_cache% 给了我相同的结果,无论是本地还是生产:

+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| have_query_cache             | YES      |
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 10485760 |
| query_cache_strip_comments   | OFF      |
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

在第一次运行后,上面的查询被缓存在本地,SHOW PROFILE 清楚地告诉我它接近尾声:

| Waiting for query cache lock   | 0.000001 |
| Waiting on query cache mutex   | 0.000001 |
| freeing items                  | 0.000000 |
| storing result in query cache  | 0.000002 |
| logging slow query             | 0.000001 |
| cleaning up                    | 0.000006 |
+--------------------------------+----------+

第二次调用按预期从缓存中返回查询。

在生产服务器上,运行此查询永远不会将其存储在缓存中。 结果集完全相同,并且显然没有使用会使查询缓存无效的语句(根据http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html 的手册 - 我确信上述查询确实符合要求它被缓存。)

为了完整起见,生产服务器上同一查询的 SHOW PROFILE 的完整输出粘贴在此处:http://pastebin.com/7Jm5rmVd

另外,值得注意的是,虽然两台服务器上的配置完全相同,但我的本地版本是 5.5.27,比生产版本 5.5.17-55 上的稍新。难道这就是问题..?

我比较了我的本地服务器和生产服务器的完整SHOW VARIABLES; 输出,看看是否缺少任何东西,但除了系统时区和日志文件的路径等之外没有什么不同......

那么,你们中的任何人都知道下一步该去哪里寻找吗?或者有任何线索可能导致这种情况?

【问题讨论】:

  • 从您指向 MySQL 手册的链接中,我刚刚了解到“查询也不会被缓存 [如果] 用户对任何相关表具有列级权限”。您的生产服务器上可能是这种情况吗?此外,“对表的任何插入、更新、删除或其他修改都会导致查询缓存中的任何相关条目被刷新。”,dev.mysql.com/doc/refman/5.5/en/query-cache.html)。这可能在生产中比在测试服务器上更频繁地发生。您可能希望在低流量时间在生产环境中运行测试。
  • 您好 YaK,感谢您的洞察力。只是为了测试,我很快将我的 db 用户更改为 root,它应该没有任何特权。不幸的是,查询缓存仍然没有插入查询。另外,我正在使用暂存服务器(这当然是生产的精确克隆),所以我很确定我在测试时没有太多流量 :-) 非常感谢您的帮助!
  • 如果查询具有不确定的值,则不会缓存它。我不知道计数是否会被视为不确定,请尝试删除计数并测试它是否被缓存
  • Nit(问题略有矛盾):“我正在运行 MySQL 的 Percona 风格,在我的本地开发机器上与生产服务器上的版本相同。”和“ 我的本地版本是 5.5.27,比生产版本 5.5.17-55 稍新"
  • 请包含SHOW STATUS LIKE 'Qcache%';SHOW CREATE TABLE topics; 的输出,并在查询完成后确认查询不会在生产服务器上使用SHOW WARNINGS; 生成任何警告。

标签: mysql caching percona


【解决方案1】:

我们在这里经常使用 Percona 服务器,也使用社区 MySQL。

查询缓存功能强大且极其复杂。 MySQL 可能做的最糟糕的事情是返回一些陈旧的缓存数据。

MySQL 不仅缓存查询,还缓存数据库数据 - 并使用索引来提高性能。

任何可能使查询缓存失效的东西都会使其失效。

作为一个经验法则——我们不会过于关注它是否被缓存......我们相信 MySQL 的行为是智能的——如果出于任何原因它认为某些东西不应该被缓存,它就不会缓存它。我们所做的就是确保我们的查询尽可能高效和简单。

如果我可以这样说 - 如果您的示例查询是“您最常用的查询之一”,我认为无论查询缓存如何,您都会遇到严重的可伸缩性问题。一旦服务器忙起来,它就会像没有腿的狗一样跑!

根据您的 pastebin 条目 - 您至少创建了一个临时表,可能是由于外部连接(或 GROUP BY)。

我完全赞成规范化 - 但有时性能需要替代路线。

您不能自己在某种查找/汇总表中缓存其中的一些数据吗?触发器在这里可以成为你的朋友:)

【讨论】:

  • 当我们解决了这个问题时,我忘记了这个话题,没有收到通知。对于那个很抱歉。最后,我们确实通过重构我们的应用程序逻辑并让查询变得更简单来解决它。正如您所说,该查询是一个等待发生的问题 - 我们最终甚至不需要它。保持简单是这里的关键。
猜你喜欢
  • 2021-10-03
  • 1970-01-01
  • 2014-06-26
  • 2015-04-27
  • 2021-04-28
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 2011-02-08
相关资源
最近更新 更多