2

我正在调试 MySQL 服务器中的慢查询问题。查询通常在 100-400 毫秒内完成,但有时会飙升到 10 或 100 秒。

查询是由我无法控制的应用程序生成的,并且有多个数据库(每个客户一个)。慢查询似乎是随机出现的,当记录慢查询时,RAM、磁盘或 CPU 都没有加载。当我手动运行查询时,它们运行良好(以毫秒为单位),这让我怀疑与其他读写查询结合使用的锁定问题。查询本身很糟糕(无法在 WHERE 或 ORDER BY 子句中使用索引),但最大的表相对较小(最多 200.000 行),并且几乎没有 JOIN。当我分析查询时,大部分时间都花在对结果进行排序上(在查询运行良好的情况下)。

我无法在测试环境中重现极度缓慢的情况,我现在最好的想法是停止生产 MySQL 服务器,创建数据库副本,启用完整的查询日志记录并再次启动服务器。这样我应该能够重放负载并重现问题。但是一般的查询日志似乎只记录查询,而不是查询的目标数据库。我还有其他 MySQL 记录/重播选项吗?

4

3 回答 3

1

可以使用慢查询日志:http ://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html

只需将阈值设置为一个非常小的值(希望您正在运行 mysql > 5.1 )

否则你可以使用 tcpdump: http ://www.mysqlperformanceblog.com/2008/11/07/poor-mans-query-logging/

当然,如果您使用它,您可能需要查看 percona 工具包的 pt-query-digest 来处理 tcpdump 输出:http ://www.percona.com/doc/percona-toolkit/2.1/pt-query-摘要.html

为了将来参考,您可能需要设置查询和服务器监控: https ://github.com/box/Anemometer/wiki 和 https://github.com/box/RainGauge/wiki/What-is-Rain-Gauge %3F

于 2012-09-04T22:14:13.090 回答
0

我终于解决了这个问题。该应用程序正在执行以下操作:

cursor = conn.execute("SELECT * FROM `LargeTable`")
while cursor.has_more_rows():
  cursor.fetchrow()
  do_something_that_takes_a_while()
cursor.close()

它一次获取和处理结果集 1 行。如果循环需要 100 秒才能完成,则表会在服务器上锁定 100 秒。

在 MySQL 服务器上更改此设置:

set global SQL_BUFFER_RESULT=ON;

使缓慢的查询立即消失,因为结果集现在被推送到临时表,因此无论应用程序消耗结果集的速度有多慢,都可以删除表锁。该设置带来了许多其他性能问题,但幸运的是,服务器的尺寸可以处理这些问题。

于 2012-09-07T12:22:48.000 回答
0

Percona 正在开发一个名为 Playback 的新工具,它完全符合您的要求: http ://www.mysqlperformanceblog.com/2013/04/09/percona-playback-0-6-for-mysql-now-available/

于 2013-05-01T01:18:07.530 回答