【发布时间】:2011-11-07 20:30:41
【问题描述】:
我有一个位于 MySQL 5.5 数据库 (INNODB) 之上的服务。该服务有一个后台作业,应该每周左右运行一次。在高层次上,后台作业执行以下操作:
- 在一个事务中进行一些初始数据库读取和写入
- 在一个事务中使用一组参数执行 UMQ(如下所述)。
- 如果没有返回记录,我们就完成了!
- 处理来自 UMQ 的结果(这有点重,所以它在任何数据库之外完成 交易)
- 在一个事务中将上一步的结果写入数据库(此 写入 UMQ 查询的表,并确保 UMQ 不会再次找到相同的记录。
- 转到第 2 步。
UMQ - 丑陋的怪物查询:这是一个讨厌的数据库查询,它连接了一堆表,在其中几个表中的列上有条件,并且包含一个 NOT EXISTS 子查询和更多的连接和条件. UMQ 包括 ORDER BY 也有 LIMIT 1000。即使查询很糟糕,我已经尽我所能 - 所有列上都有索引过滤,并且连接都在外键关系上。
我确实希望 UMQ 很重并且需要一些时间,这就是它在后台作业中执行的原因。但是,我看到的是性能迅速下降,直到最终导致我的服务超时(10 次迭代后可能会慢 50 倍)。
首先我认为是因为UMQ查询的数据发生了变化(见上面的步骤4),但不是因为如果我从慢查询日志中取出最后一个查询(导致超时的那个)并执行我自己直接得到了相同的行为,直到我重新启动 MySQL 服务。在重新启动对完全相同的数据进行精确查询后,在重新启动前花费了 >30 秒的时间现在花费了
另外,使用question 中描述的技巧,我可以看到查询在重新启动后扫描了大约 60K 行,而不是之前的 18M 行。 EXPLAIN 告诉我应该扫描大约 10K 行,并且 EXPLAIN 的结果总是相同的。没有其他进程同时访问数据库,慢查询日志中的 lock_time 始终为 0。重启前后的 SHOW ENGINE INNODB STATUS 没有给我任何提示。
所以最后的问题是:有人知道我为什么会看到这种行为吗?我该如何进一步分析呢?
我觉得我需要以某种方式对 MySQL 进行不同的配置,但我已经疯狂地搜索和测试,但没有想出任何有影响的东西。
【问题讨论】:
-
您可以使用profiling 运行查询吗?
-
您要关闭交易吗?有限制的查询是否在每个循环中使用递增的偏移量?
-
@Michael Mior:好主意 - 我会玩一些分析并用我的发现更新问题。
-
@Darhazer:是的,我已经非常仔细地检查了我是否提交了交易。通过检查我的应用程序代码和检查 MySQL 常规日志。不,不使用递增偏移量 - 查询的数据以这样的方式更改,以至于在下一次迭代期间找不到它。