记录和重放MySQL数据库负载

时间:2012-09-04 22:07:20

标签: mysql performance

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

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

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

3 个答案:

答案 0 :(得分: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-digest.html

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

答案 1 :(得分:0)

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

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

它正在获取并处理结果集,一次一行。如果循环需要100秒才能完成,那么表将在服务器上锁定100秒。

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

set global SQL_BUFFER_RESULT=ON;

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

答案 2 :(得分:0)

Percona正在开发一种名为Playback的新工具,它可以完全满足您的需求: http://www.mysqlperformanceblog.com/2013/04/09/percona-playback-0-6-for-mysql-now-available/